I have 2 Spheres in my scene. I want to be able to drag and drop my mouse from one sphere to the other, and have an indicator (a straight line for example) while dragging. After releasing the mouse button, I want to store in the first sphere the other sphere (as GameObject).
I need this in UnityScript, but I can accept C# ideas.
So far I have thought about onMouseDown
event on the first Sphere, and then onMouseEnter
to the other sphere, I'll store the data in some global variable (which I donno how to do yet) and in case of onMouseExit
I'll just put the global variable as null.
Then onMouseUp
on the first Sphere I'll store the global variable in the pressed object (the sphere).
Any tips and tricks on how to do it?
Assumptions/Setup
You're working in a 2D worldspace; the logic for dragging the object for this part of the solution would need changing.
Setting parent after click drag, referred to setting the object you didn't click to be the child of the parent you did click on.
The camera should be an orthographic camera; using a perspective camera will cause the dragging to not align with where you think it should be.
In order to make the dragging work, I created a quad that was used as the 'background' to the 2D scene, and put that on a new layer called 'background'. Then setup the layermask field to only use the background layer.
Create and setup a material for the line renderer, (I'm using a Particles/Additive shader for the above example), and for the parameters of the line renderer I'm using Start Width: 0.75
, End Width: 0
, and make sure Use World Space
is ticked.
Explanation
Firstly setup the otherSphere
field to be pointing to the other sphere in the scene. OnMouseDown
and OnMouseUp
toggle the mouseDown bool, that is used to determine if the line renderer should be updated. These are also used to turn on/off the line renderer, and set/remove the parent transform of the two spheres.
To get the position to be dragged to, I'm getting a ray based off of the mouse position on screen, using the method ScreenPointToRay. If you wanted to create add smoothing to this drag functionality, you should enable the if (...) else
statement at the bottom, and set the lerpTime to a value (0.25 worked well for me).
Note; when you release the mouse, the parent is immediately set, as such both objects end up getting dragged, but the child will return to it's former position anyway.
[RequireComponent(typeof(LineRenderer))]
public class ConnectedSphere : MonoBehaviour
{
[SerializeField]
private Transform m_otherSphere;
[SerializeField]
private float m_lerpTime;
[SerializeField]
private LayerMask m_layerMask;
private LineRenderer m_lineRenderer;
private bool m_mouseDown;
private Vector3 m_position;
private RaycastHit m_hit;
public void Start()
{
m_lineRenderer = GetComponent<LineRenderer>();
m_lineRenderer.enabled = false;
m_position = transform.position;
}
public void OnMouseDown()
{
//Un-parent objects
transform.parent = null;
m_otherSphere.parent = null;
m_mouseDown = true;
m_lineRenderer.enabled = true;
}
public void OnMouseUp()
{
//Parent other object
m_otherSphere.parent = transform;
m_mouseDown = false;
m_lineRenderer.enabled = false;
}
public void Update()
{
//Update line renderer and target position whilst mouse down
if (m_mouseDown)
{
//Set line renderer
m_lineRenderer.SetPosition(0, transform.position);
m_lineRenderer.SetPosition(1, m_otherSphere.position);
//Get mouse world position
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out m_hit, m_layerMask))
{
m_position.x = m_hit.point.x;
m_position.y = m_hit.point.y;
}
}
//Set position (2D world space)
//if (m_lerpTime == 0f)
transform.position = m_position;
//else
//transform.position = Vector3.Lerp(transform.position, m_position, Time.deltaTime / m_lerpTime);
}
}
Hope this helped someone.