Search code examples
c#unity-game-engine2disometric

Object only moving small amount in dragged direction [Unity 2D isometric]


So I'm currently working on an isometric 2D game and I'm trying to drag objects with the mouse. I've added the script below after following some tutorials but the object only moves a little bit in the direction it's being dragged. I have no idea why the object is not just following the mouse's coordinates but if you need any other info I don't mind providing.

private void OnMouseDown()
{
    mouseOffset = MouseWorldPos() - (Vector2)transform.position;
}

private void OnMouseDrag()
{
    transform.position = MouseWorldPos() - mouseOffset;
}

private Vector2 MouseWorldPos()
{
    Vector2 mousePos = Input.mousePosition;
    return Camera.main.ScreenToViewportPoint(mousePos);
}

Solution

  • why do you convert to Viewport coordinates?

    Viewport space is normalized and relative to the camera. The bottom-left of the camera is (0,0); the top-right is (1,1). The z position is in world units from the camera.

    => You first do

    mouseOffset = MouseWorldPos() - (Vector2)transform.position;
    

    which can maximum be a position 0 to √(2) away from the transform.position.

    Then you do

    transform.position = MouseWorldPos() - mouseOffset;
    

    which basically keeps it at your original position +- √(2) in any direction.


    You probably would rather want to do something like e.g.

    private readonly struct DragInfo
    {
        public Plane Plane { get; }
        public Vector3 StartHitPoint { get; }
        public Vector3 OriginalPosition { get; }
    
        public DragInfo(Plane plane, Vector3 startHitPoint, Vector3 originalPosition)
        {
            Plane = plane;
            StartHitPoint = startHitPoint;
            OriginalPosition = originalPosition;
        }
    }
    
    private DragInfo? dragInfo;
    
    private Camera mainCamera;
    
    private void OnMouseDown()
    {
        if(!mainCamera) mainCamera = Camera.main;
    
        var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
    
        var plane = new Plane(-mainCamera.transform.forward, transform.position);
        if(!plane.Raycast(ray, out var hitDistance)) return;
        
        var startPoint = ray.GetPoint(hitDistance);
    
        dragInfo = new DragInfo(Plane, startPoint, transform.position);
    }
    
    private void OnMouseDrag()
    {
        if(!dragInfo.HasValue) return;
    
        var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
    
        if(!dragInfo.Plane.Raycast(ray, out var hitDistance)) return;
    
        var currentPoint = ray.GetPoint(hitDistance);
    
        var delta = currentPoint - dragInfo.StartHitPoint;
        transform.position = dragInfo.OriginalPosition + delta;
    }
    
    private void OnMouseUp()
    {
        dragInfo = null;
    }