Drag and Drop Using an Arrow in Unity
Since Chambergon Battle Logic (CBL) is a card game — and players often need to actually put together the contents of a card — we need to be able to drag and drop stuff.
Here’s how I am currently implementing drag-and-drop functionality in the early stages of remaking CBL in Unity.
//This doesn’t need to be public, but it helps when you’re initially trying to find the right size
public float arrowheadSize;
Vector3 startPosition, mouseWorld;
GameObject arrow;
LineRenderer arrowLine;
void Start(){
arrowLine = arrow.GetComponentInChildren<LineRenderer> ();
mouseWorld = new Vector3 ();
arrowheadSize = 0.02f;
}
void OnMouseDown(){
mouseWorld = Camera.main.ScreenToWorldPoint (
Input.mousePosition.y,
Camera.main.nearClipPlane
));
startPosition = mouseWorld;
}
void OnMouseDrag(){
arrowLine.enabled = true;
DrawArrow ();
}
void DrawArrow(){
mouseWorld = Camera.main.ScreenToWorldPoint (
Input.mousePosition.y,
Camera.main.nearClipPlane
));
//The longer the line gets, the smaller relative to the entire line the arrowhead should be
float percentSize = (float) (arrowheadSize / Vector3.Distance (startPosition, mouseWorld));
//h/t ShawnFeatherly (http://answers.unity.com/answers/1330338/view.html)
arrowLine.SetPosition (0, startPosition);
arrowLine.SetPosition (1, Vector3.Lerp(startPosition, mouseWorld, 0.999f – percentSize));
arrowLine.SetPosition (2, Vector3.Lerp (startPosition, mouseWorld, 1 – percentSize));
arrowLine.SetPosition (3, mouseWorld);
arrowLine.widthCurve = new AnimationCurve (
new Keyframe (0.999f – percentSize, 0.4f),
new Keyframe (1 – percentSize, 1f),
new Keyframe (1 – percentSize, 1f),
new Keyframe (1, 0f));
}
void OnMouseUp(){
arrowLine.enabled = false;
RaycastHit hit;
Physics.Raycast(Camera.main.ScreenPointToRay (Input.mousePosition), out hit, 100);
transform.position = new Vector3(hit.point.x, transform.position.y, hit.point.z);
}
A few things to note:
OnMouseDown(), OnMouseUp(), and OnMouseDrag() only seem to be called for objects that have RigidBodies and colliders.
Second, the code above only works if you have some sort of backdrop collider (attached to the plane or ground on which you are moving objects around).
Third, since this is in 3D, it only works if the objects being dragged around are relatively close (on the “depth” axis) to the backdrop collider. Otherwise, perspective issues will arise such that the point of the arrow won’t be anywhere near where the object ends up.
Fourth, the code for the arrow changes the percentage of the total line devoted to the arrowhead based on how long the line is and an arbitrary length you decide on. If you don’t include that correction, the arrowhead will stretch as the line lengthens.