OnMouseDrag not working

Hello,
I want to be able to move ui sprites in my scene
OnMouseDrag gets called but does not move sprite, pls help
I attached this script to my ui sprite and added a boxcollider2d in order to use OnMouseDrag
I am not able to find out why this isnt working

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Draggable : MonoBehaviour
{
    private bool isDragged = false;
    private Vector3 mouseDragStartPosition;
    private Vector3 spriteDragStartPosition;

    private void OnMouseDown()
    {
        Debug.Log("OnMouseDown");
        isDragged = true;
        mouseDragStartPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        spriteDragStartPosition = transform.localPosition;
    }

    private void OnMouseDrag()
    {
      
        if (isDragged)
        {
            transform.localPosition = spriteDragStartPosition + (Camera.main.ScreenToWorldPoint(Input.mousePosition) - mouseDragStartPosition);
            Debug.Log("OnMouseDrag");
        }
    }

    private void OnMouseUp()
    {
        Debug.Log("OnMouseUp");
        isDragged = false;
    }
}

edit: if I change the camera projection form perspective to orthographic it works

Because the perspective camera is a cone shape, the screen is a point in the world. That makes that regardless where your cursor is, translating this to a world point will always end up being the same exact point. Because of this, no change is actually made in moving the mouse and the sprite does not change position.

What you want to do is project a ray from the point on the screen into the world, and project it onto the plane your sprite is on. On this you can detect the change.

I use this code to drag squares over a plane in the scene view. I am sure you can use this code to write something for your own situation that works.

 private void performFloorDrag()
        {
            //Drag a floor to move it
            if (dragFloor != null)
            {
                //If no floor selected, nothing to drag
                if (selectedFloor == null)
                {
                    dragFloor = null;
                    return;
                }

                //If the mouse is on the plane
                if (getPointOnPlaneOnMouse(out Vector2 point))
                {
                    //If the mouse has moved since last drag
                    if (point != dragPoint)
                    {
                        //Calculate the move onthe mouse
                        Vector2 move = point - dragPoint;

                        //Get the current position for the dragging floor
                        Vector3 currentFloorPosition = dragFloor.LocalPosition;

                        //Calculate the new intended position for the floor
                        Vector3 intendedNewFloorPosition = dragFloor.LocalPosition + new Vector3(move.x, 0f, move.y);

                        //Set the new floor position
                        moveFloor(dragFloor, intendedNewFloorPosition);

                        //Get actual new floor position
                        Vector3 newFloorPosition = dragFloor.LocalPosition;

                        //Calculate actual performed move on the floor
                        Vector3 performedFloorMove = newFloorPosition - currentFloorPosition;

                        //Set new dragpoint to increase with actual move on floor
                        dragPoint += new Vector2(performedFloorMove.x, performedFloorMove.z);
                    }
                }
            }

            //If mouse up of leaves window, stop dragging
            if (Event.current.type == EventType.MouseUp && Event.current.button == 0 || Event.current.type == EventType.MouseLeaveWindow)
            {
                dragFloor = null;
                dragPoint = Vector2.zero;
            }
        }

        private bool getPointOnPlaneOnMouse(out Vector2 _point)
        {
            //Set default value
            _point = Vector2.zero;

            //Create a ray from the scene view into the world
            Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
           
            //Create a plane for the floorplan plane
            Plane plane = new Plane(component.transform.up, component.transform.position);

            //If the cast ray has hit
            if (plane.Raycast(ray, out float hit))
            {
                //Get the point of the hit
                Vector3 point = component.transform.InverseTransformPoint(ray.GetPoint(hit));
               
                //Convert to a Vector2 position on the floorplan
                _point = new Vector2(point.x, point.z);
               
                //Return true because hit
                return true;
            }

            //Return false if not hit
            return false;
        }
1 Like

Hi! I’m having the same issue… did you fix the issue with the suggested resolution?
The only difference in my case is that switching to an orthographic camera doesn’t seem to fix the issue.

public class CellDragScript : CellScript
{
    public Transform tr;
    public float offsetX;
    public float offsetY;
    public Vector3 origin;

    void Start()
    {
        tr = transform;
    }

    private void OnMouseDown()
    {
        origin = transform.localPosition;

        Vector3 point = Camera.main.ScreenToWorldPoint(Vector3.right * Input.mousePosition.x + Vector3.up * Input.mousePosition.y + Vector3.forward * tr.localPosition.y);       
        offsetX = tr.localPosition.x - point.x;
        offsetY = tr.localPosition.z - point.y; // this is intentional, the object is flipped.
    }

    private void OnMouseDrag()
    {
        Vector3 point = Camera.main.ScreenToWorldPoint(Vector3.right * Input.mousePosition.x + Vector3.up * Input.mousePosition.y + Vector3.forward * tr.localPosition.y);
        tr.localPosition = (Vector3.right * (point.x + offsetX)) + (Vector3.forward * (point.y + offsetY)) + (Vector3.up * tr.localPosition.y);
    }

    private void OnMouseUp()
    {
        tr.localPosition = origin;
    }
}

The directions work correctly, the problem is the speed of the sprite, is not as fast as the cursor.

Hello,
I ended up using IEndDragHandler, IDragHandler and IBeginDragHandler Interfaces

1 Like