Home > Net >  Unity Input System Drag having an offset after dragging
Unity Input System Drag having an offset after dragging

Time:01-27

I am new to the new Unity Input System and implemented a dragging algorithm. It should work with the mouse upon click&drag. The dragging operation will move the cimemachine cameraTarget, and therefore the camera follows. It is working, but the fault is: after dragging it has a little offset. So the dragging on the screen is not 1:1 dragging the cameraTarget. Any ideas why this is happening?

here is my code:

public class DragManager : MonoBehaviour
{
    private InputControls.MouseActions mouseActions;
    private Coroutine _coroutine;
    private CameraHandler cameraHandler;
    private Vector3 _pointerStartPosition;
    private Vector3 _pointerCurrentPosition;

    private void OnEnable()
    {
        cameraHandler = CameraHandler.Instance;
        mouseActions.Enable();
        mouseActions.Drag.started  = Drag_started;
        mouseActions.Drag.canceled  = Drag_canceled;
    }

    private void OnDisable()
    {
        mouseActions.Drag.started -= Drag_started;
        mouseActions.Drag.canceled -= Drag_canceled;
        mouseActions.Disable();
    }

    private void Awake()
    {
        mouseActions = new InputControls().Mouse;
    }

    private void Drag_started(InputAction.CallbackContext obj)
    {
        _pointerStartPosition = mouseActions.MousePosition.ReadValue<Vector2>();
        _coroutine = StartCoroutine(HandleDragCoroutine());
    }

    private void Drag_canceled(InputAction.CallbackContext obj)
    {
        StopCoroutine(_coroutine);
    }


    private IEnumerator HandleDragCoroutine()
    {
        while (true)
        {
            _pointerCurrentPosition = mouseActions.MousePosition.ReadValue<Vector2>();
            var dragIteration = _pointerStartPosition - _pointerCurrentPosition; // drag _pointerCurrentPosition to _pointerStartPosition
            var cameraTargetTransform = cameraHandler.GetCameraTargetTransform();
            cameraTargetTransform.position  = delta * Time.deltaTime;
            _pointerStartPosition = _pointerCurrentPosition;
            yield return null; // wait for new frame Update
        }
    }
}

CodePudding user response:

Its common in unity, I went through this tons of time

Try this:

public static Vector2 TouchToScreenPoint(RectTransform draggingCanvasRectTransform)
    {
        Vector2 position = Vector2.zero ;
         
        if (Input.touchCount > 0)
        {
            // respect only first touch, mousePosition module will update on each finger touch the screen.
            RectTransformUtility.ScreenPointToLocalPointInRectangle(draggingCanvasRectTransform, Input.touches[0].position,
                Camera.main, out position);
        }
     }

This works all the way on any screen size , you can reference whatever camera you are using and the main canvas you are using.

Hope this works out for you

CodePudding user response:

So after couple of hours I found the solution. Below is the updated Code.

Explanation:

  • I had to recalculate the mouse position to world space (although it seemed correct)
  • remove the multiplication with Time.deltaTime, as this would lead to minimal movement.
  • Additionally to that, I was using Cinemachine. And on the virtual cam I had to set Soft Zone Height/Width to zero (0). Otherwise the camera would bounce when dragging.
public class DragManager : MonoBehaviour
{
    private InputControls.MouseActions mouseActions;
    private InputControls.TouchActions touchActions;
    private Coroutine _coroutine;
    private CameraTarget cameraTarget;
    private Camera _camera;
    private Vector3 _pointerStartPosition;
    private Vector3 _pointerCurrentPosition;

    private void OnEnable()
    {
        cameraTarget = CameraTarget.Instance;

        mouseActions.Enable();
        mouseActions.Drag.started  = Mouse_Drag_started;
        mouseActions.Drag.canceled  = Drag_canceled;
    }

    private void OnDisable()
    {
        mouseActions.Drag.started -= Mouse_Drag_started;
        mouseActions.Drag.canceled -= Drag_canceled;
        mouseActions.Disable();
    }

    private void Awake()
    {
        mouseActions = new InputControls().Mouse;
        _camera = Camera.main;
    }

    private void Mouse_Drag_started(InputAction.CallbackContext obj)
    {
        _pointerStartPosition = CalculatePositionToWorldSpace(mouseActions.MousePosition.ReadValue<Vector2>());
        _coroutine = StartCoroutine(HandleDragCoroutine(mouseActions.MousePosition));
    }

    private Vector3 CalculatePositionToWorldSpace(Vector3 _pointerPosition)
    {
        var worldDirection = _camera.ScreenToWorldPoint(_pointerPosition);
        worldDirection.z = 0f;
        return worldDirection - cameraTarget.Transform.position;
    }

    private void Drag_canceled(InputAction.CallbackContext obj)
    {
        if (_coroutine != null)
            StopCoroutine(_coroutine);
    }


    private IEnumerator HandleDragCoroutine(InputAction pointerPositionInputAction)
    {
        while (true)
        {
            _pointerCurrentPosition = CalculatePositionToWorldSpace(pointerPositionInputAction.ReadValue<Vector2>());
            var dragIteration = _pointerStartPosition - _pointerCurrentPosition; // drag _pointerCurrentPosition to _pointerStartPosition
            cameraTarget.Transform.position  = dragIteration;
            _pointerStartPosition = _pointerCurrentPosition;
            yield return null; // wait for new frame Update
        }
    }
}

  •  Tags:  
  • Related