Search code examples
c#unity-game-engine2dcollision

Why does my dragging logic in Unity not work? (only once)


I have a script attached to a GameObject with a Collider2D attached to it as well.

The script should enable me to drag the GameObject while holding down the mouse and "dropping" it by simply letting go. However, I can only do this once... It doesn't work a second time, only if I restart playing mode or disable and enable the Collider2D again.

I am using using Unity Version 6 and I've looked up the problem already and haven't found a proper solution. Someone suggested on the Unity Forum to check if Physics2d.autoSimulation is set to false in the Project Settings because that could cause the issue, but I have found no such setting.

private bool _dragging;
    
private void Update()
{
    if (_dragging)
    {
        var mousePosition = _camera.ScreenToWorldPoint(Mouse.current.position.ReadValue());
        transform.position = new Vector3(mousePosition.x, mousePosition.y, 0);
    }
}

private void OnMouseDown()
{
    _dragging = true;
}

private void OnMouseUp()
{
    _dragging = false;
}

Solution

  • If OnMouseDown doesn't fire a second time, it's possible that the position of the collider has not updated for the physics system. Keep in mind that you should never more any collider manually that isn't part of a rigidbody. Unity only supports rigidbody physics. For 3d physics it uses PhysX, for 2d physics it uses Box2D.

    When you move an object with a Collider2D component or an object that has a child with a Collider2D component, that object should have a Rigidbody2D component attached. When the object is completely controlled by your code, check the "kinematic" checkbox so it's not influenced by any kind of forces.

    That way when you move the GameObject around, the physics engine will actually update the collider representation.

    Note that OnMouseUp only fires when the mouse is actually released on the object. You may want to set _dragging back to false by using

    if (Input.GetMouseUp(0))
    {
        _dragging = false;
    }
    

    inside Update().

    If you have many objects that can be dragged around, it usually makes more sense to put a dragging script on the camera and use a raycast to pick and choose the object that should be dragged. Currently each object would have their own _dragging variable and each would run their own Update.