Once upon a time... There was a rabbit who wanted to bury a few radishes in the pit. Now it's the way to detect the radish in the pit. Tell me about the needs.
1. Mouse dragging radish can be put into different pits.
2. When the radish is not dragged into the pit, it returns to its original position.
3. When the radish is dragged into the pit, the radish is put into the pit.
I use Trigger Event to detect, by the way, I have done some logic, language description is not good enough, or code it:
using UnityEngine;
/// <summary>
/// Drag interface
/// </summary>
public interface IDrag
{
/// <summary>
/// startDrag
/// </summary>
void OnStartDrag();
/// <summary>
/// Dragging
/// </summary>
void OnDrag();
/// <summary>
/// put down
/// </summary>
void OnDrop();
}
/// <summary>
/// Event monitoring and handling
/// </summary>
public interface IDispatch
{
/// <summary>
/// Adding event listeners
/// </summary>
void AddEvent();
/// <summary>
/// Remove monitoring of events
/// </summary>
void RemoveEvent();
}
The interface above is used to describe what I need to do in the drag. The following is to achieve:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DraggerImpler : IDrag{
private GameObjDrag host;
public DraggerImpler(GameObjDrag _host)
{
host = _host;
}
public void OnStartDrag()
{
host.IsDraging = true;
}
public void OnDrag()
{
host.IsDraging = true;
}
public void OnDrop()
{
host.IsDraging = false;
if (host.IsReturn)
{
host.targetTransform.position = host.startTransform.position;
}
else
{
host.targetTransform.position = host.currTransform.position;
}
}
}
The script above implements the Idrag interface, because I didn't expect to start dragging and dragging whatever needs to be done first regardless of him, when I put it down, I made a judgment that is this:
public void OnDrop()
{
host.IsDraging = false;
if (host.IsReturn)
{
host.targetTransform.position = host.startTransform.position;
}
else
{
host.targetTransform.position = host.currTransform.position;
}
}
This means that if you need to return, you give the location of the initial record to the targetTransform, and if you don't need to return, you give the location of the currTransform to the targetTransform.
The following script is used for post-collision detection event processing. The logic of radish entering the pit and exiting the pit is written here.
Here's another new requirement:
When this pit is occupied by radish, other radishes can no longer enter the pit.
Solution: So I put a mark in the radish pit and remove it when the radish leaves the pit.
Question: How do I know that I removed my own tag?
Solution: Give each tag a unique ID, and determine if it's the tag you add based on the ID?
Problem: When two pits are very close, moving from one pit to another triggers an entry into the next pit.
Event, then triggered the exit event of the pit, causing the ID I recorded to be changed to the ID of the new pit, which made it impossible for me to remove the mark of the pit I left. There are no radishes in this pit, and they can't be put in any more.
Solution: Make a List of tags, add an ID to the List of tags when entering the pit, check if there is an ID to leave the pit when leaving the pit, remove the tag of the pit, and remove the ID from the List.*
using System.Collections.Generic;
using UnityEngine;
public class TriggerImpler : IDispatch
{
/// <summary>
/// After listening in, we are right. Obj Operating
/// </summary>
GameObjDrag _obj;
/// <summary>
/// Trigger event monitoring
/// </summary>
TriggerEvent _te;
/// <summary>
/// sign ID list
/// </summary>
List<int> _markIDs;
public TriggerImpler(GameObjDrag obj)
{
_te = TriggerEvent.AddComponentToGameObject(obj.gameobject);
_obj = obj;
_markIDs = new List<int>();
}
public void AddEvent()
{
_te.TriggerEnter += OnEnter;
_te.TriggerExit += OnExit;
}
public void RemoveEvent()
{
_te.TriggerEnter -= OnEnter;
_te.TriggerExit -= OnExit;
}
public void OnExit(GameObject obj)
{
//If the tag is self-added, it can be removed, not self-added.
Mark ma = obj.GetComponent<Mark>();
if (ma != null)
{
if (_markIDs.Contains(ma.GetInstanceID()))
{
UnityEngine.GameObject.Destroy(ma);
_markIDs.Remove(ma.GetInstanceID());
}
}
//If the exit obj is not the obj of the current record, it will not be returned
if (_obj.currTransform.position == obj.transform.position)
{
_obj.IsReturn = true;
_obj.currTransform.position = Vector3.zero;
}
}
public void OnEnter(GameObject obj)
{
//If the entry Obj is marked, then no assignment is made, if not, then mark Obj, and assign a value.
Mark ma = obj.GetComponent<Mark>();
if (ma == null)
{
ma = obj.AddComponent<Mark>();
//_markID = ma.GetInstanceID();
_markIDs.Add(ma.GetInstanceID());
_obj.IsReturn = false;
_obj.currTransform.position = obj.transform.position;
}
}
}
using System;
using UnityEngine;
public class TriggerEvent : MonoBehaviour {
public Action<GameObject> TriggerEnter;
public Action<GameObject> TriggerExit;
/// <summary>
/// Add this event listener class to an object
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static TriggerEvent AddComponentToGameObject(GameObject obj)
{
TriggerEvent com = obj.GetComponent<TriggerEvent>();
if (com == null)
{
com = obj.AddComponent<TriggerEvent>();
}
return com;
}
public void OnTriggerEnter(Collider other)
{
//Debug.Log("TriggerEnter" + other.gameObject.name);
TriggerEnter(other.gameObject);
}
public void OnTriggerExit(Collider other)
{
//Debug.Log("TriggerExit" + other.gameObject.name);
TriggerExit(other.gameObject);
}
}
The above script is used for collision detection. Pay attention to the radish plus rigid body and collider. Just add Collider to the pit. Check the isTrigger of the collider.
Tagged scripts:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// A script for marking up
/// </summary>
public class Mark : MonoBehaviour {
/// <summary>
/// Users are not allowed to modify manually. Look at the test ID
/// </summary>
public int ID;
// Use this for initialization
void Start () {
ID = GetInstanceID();
//Debug.Log(gameObject.name + "This object has been marked, ID is" + ID);
}
// Update is called once per frame
void Update () {
}
public void OnDestroy()
{
//Debug.Log(gameObject.name + tag removed);
}
}
The following are the key points:
using UnityEngine;
public class GameObjDrag
{
public Position startTransform;
public Position currTransform;
public Position targetTransform;
private bool _isReturn;
/// <summary>
/// Whether to return to the original position,true It's return. false No return
/// </summary>
public bool IsReturn
{
get { return _isReturn; }
set { _isReturn = value; }
}
private bool isDraging;
/// <summary>
/// Are you dragging?
/// </summary>
public bool IsDraging
{
get { return isDraging; }
set { isDraging = value; }
}
/// <summary>
/// Drag-and-drop interface
/// </summary>
public IDrag _dragInterface;
/// <summary>
/// Event Interface
/// </summary>
public IDispatch _dispatchInterface;
/// <summary>
/// Dragged objects
/// </summary>
public GameObject gameobject;
public GameObjDrag(GameObject obj)
{
gameobject = obj;
startTransform = new Position(obj.transform.position,obj.transform.eulerAngles,obj.transform.localScale);
currTransform = new Position();
targetTransform = new Position();
_isReturn = true;
_dragInterface = new DraggerImpler(this);
_dispatchInterface = new TriggerImpler(this);
_dispatchInterface.AddEvent();
}
public void SetDraggerImp(IDrag dragger)
{
_dragInterface = dragger;
}
public void SetTriggerImp(IDispatch trigger)
{
_dispatchInterface = trigger;
}
public void OnStartDrag()
{
_dragInterface.OnStartDrag();
}
public void OnDrag()
{
_dragInterface.OnDrag();
}
public void OnDrop()
{
_dragInterface.OnDrop();
}
}
/// <summary>
/// position
/// </summary>
public class Position
{
/// <summary>
/// position
/// </summary>
public Vector3 position;
/// <summary>
/// rotate
/// </summary>
public Vector3 rotation;
/// <summary>
/// Size
/// </summary>
public Vector3 scale;
public Position(Vector3 pos, Vector3 rot, Vector3 sca)
{
position = pos;
rotation = rot;
scale = sca;
}
public Position()
{
position = Vector3.zero;
rotation = Vector3.zero;
scale = Vector3.zero;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EPGameObj : MonoBehaviour
{
GameObjDrag ep;
void Start()
{
ep = new GameObjDrag(this.gameObject);
// ep.SetDragImp(new DraggerImpler(ep));
}
IEnumerator OnMouseDown()
{
ep.OnStartDrag();
//Converting an object from a world coordinate system to a screen coordinate system
Vector3 screenSpace = Camera.main.WorldToScreenPoint(transform.position);
//Two steps have been completed.1Because the coordinate system of the mouse is2Dimensional, needs to be transformed into3Dimensional world coordinate system
Vector3 mouseScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);
//2Only in three-dimensional case can we calculate the distance between the mouse position and the object. offset That is distance.
Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(mouseScreenSpace);
while (Input.GetMouseButton(0))//The left mouse button is continuously pressed.
{
ep.OnDrag();
//Get the mouse now2Dimensional coordinate system position
Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);
//Put the current mouse's2Dimensional Position Conversion3Dimensional position
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset;
//curPosition is the position attribute assigned to transform by the object's motion vector.
transform.position = curPosition;
yield return new WaitForFixedUpdate();
}
}
public void OnMouseUp()
{
ep.OnDrop();
transform.position = ep.targetTransform.position;
}
void Dispose()
{
//Remember remote drag collision detection events
ep._dispatchInterface.RemoveEvent();
}
}
The script above is the script that we need to hang on the carrot to drag. It mainly controls the movement of the carrot and changes the key position when loosening the mouse.