Unity Input System Drag 拖动后有一个偏移量

Unity Input System Drag having an offset after dragging

我是新Unity输入系统的新手,实现了拖动算法。它应该在点击和拖动时与鼠标一起工作。拖动操作将移动 cimemachine cameraTarget,因此相机会随之移动。它正在工作,但错误是:拖动后它有一点偏移。所以在屏幕上的拖动不是 1:1 拖动 cameraTarget。知道为什么会这样吗?

这是我的代码:

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
        }
    }
}

在unity中很常见,我经历了这么多时间

试试这个:

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);
        }
     }

这在任何屏幕尺寸上都适用,您可以参考您使用的任何相机和您使用的主要 canvas。

希望这对你有用

所以几个小时后我找到了解决方案。以下是更新后的代码。

说明:

  • 我不得不重新计算鼠标在世界中的位置space(虽然看起来是正确的)
  • 删除与 Time.deltaTime 的乘法,因为这会导致最小的移动。
  • 除此之外,我还在使用 Cinemachine。在虚拟凸轮上,我必须将软区 Height/Width 设置为零 (0)。否则拖动时相机会弹起。
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
        }
    }
}