在 Unity3D 中拖动时保持相机和鼠标移动速度相同

Keeping camera & mouse movement speeds the same on Drag in Unity3D

这个问题有点长,请大家多多包涵。

我正在使用 Unity3D 的较新输入系统,我已经能够设置相机移动,因此当用户单击鼠标中键时,他们可以沿 X 轴和 Y 轴拖动相机。然而,它有一种非常视差的感觉,我正在努力避免这种情况。据我了解,这是因为鼠标移动速度和相机移动速度不一样 (See, visual)。

我的输入控制器class:

public class InputController : MonoBehaviour
{
    private InputControls inputControls;

    [Header("Camera Movement")]
    [SerializeField] CameraController cameraController;
    private InputAction.CallbackContext context;

    void Awake()
    {
        inputControls = new InputControls();
    }

    private void Start()
    {
        inputControls.Mouse.MiddleButton.started += MiddleButton_started;
    }

    public void MiddleButton_started(InputAction.CallbackContext ctx)
    {
        context = ctx;
    }

    private void Update()
    {
        bool mouseIsDown = context.performed;
        if (mouseIsDown)
        {
            Vector2 delta = inputControls.Mouse.DeltaPosition.ReadValue<Vector2>();
            cameraController.Move(delta, false);
        }
    }
}

我的相机控制器class:

public class CameraController : MonoBehaviour
{
    [SerializeField] Vector2 minPosition;
    [SerializeField] Vector2 maxPosition;
    [SerializeField] float speed = 3;
    [SerializeField] float zPosition = -10f;
    private Camera mainCam;

    private void Start()
    {
        mainCam = GetComponent<Camera>();
    }


    public void Move(Vector2 deltaPosition, bool convertToViewportPoint = true)
    {
        if (convertToViewportPoint) deltaPosition = mainCam.ScreenToViewportPoint(deltaPosition);

        Vector3 moveTo = new Vector3(deltaPosition.x, deltaPosition.y, 0);
        Vector3 target = transform.position - moveTo;

        float clampedX = Mathf.Clamp(target.x, minPosition.x, maxPosition.x);
        float clampedY = Mathf.Clamp(target.y, minPosition.y, maxPosition.y);

        transform.position = Vector3.Lerp(transform.position, new Vector3(clampedX, clampedY, -10), speed * Time.deltaTime);

        }
}

现在,在这个版本的 CameraController 中,视差感可能来自 Lerp 速度恒定的事实,而鼠标移动的速度却不是。

但是,我已经用各种量级(即鼠标位置增量、当前鼠标位置、从鼠标位置增量减去当前鼠标位置等的量级等)进行了测试,一般情况下相同的结果 - 相机移动速度太快,反之亦然。

根据我对三角函数的有限但不断增长的理解,幅度表示矢量的速度,但我无法使相机移动速度和鼠标移动速度相匹配。我希望发生这种情况,以便当用户单击某个点时,该点在移动时通常会停留在光标下方 (See other visual)。

有人可以帮助我了解如何实现这一目标吗?

谢谢。

为了防止有人遇到这个问题,我所做的是在第一次单击鼠标时获取光标的位置。我们可以称之为 dragOrigin。然后我们可以获取鼠标移动时位置的变化(通过 Unity 的输入系统轮询输入可以通过 Update 函数完成)。然后我们从 dragOrigin 中减去新的鼠标位置。一旦我们有了差异——我们称之为 deltaPosition——我们只需将它添加到相机的当前位置。

为了确保速度与鼠标的速度匹配,运行deltaPosition和currentMousePosition通过SmoothDamp来获取变化的速度。它的幅度将是您希望相机移动的速度。

例如:

// Call this when the user first clicks the mouse.
// Lets assume this is part of a class that controls the camera.
public void SetDragOrigin(Vector2 mousePosition)
{
    // could probably cache Camera.main for efficiency
    dragOrigin = Camera.main.ScreenToWorldPoint(mousePosition);
}
     
// This is called in an update function of another class that deals with input.
// (Or perhaps you can simply pass the input controls to the class controlling the camera, but that's not the case here).
public void Move(Vector2 newMousePosition)
{
    mousePosition = mainCam.ScreenToWorldPoint(mousePosition);
     
    Vector2 deltaPosition = dragOrigin - mousePosition;
    Vector3.SmoothDamp(deltaPosition, mousePosition, ref dragVelocity, 0.1f, 250f, Time.deltaTime);
     
    cameraPosition += new Vector3(deltaPosition.x, deltaPosition.y, 0) * dragVelocity.magnitude * Time.deltaTime;
     
    // anything else you want to do like clamping camera position
    // ....
}

这里要注意的一件事是,SmoothDamp 的第 5 个参数是 maxSpeed。我在此示例中对其进行了硬编码,但您可能想尝试一下。当我没有设置 maxSpeed 时,随着时间的推移 dragVelocity 会发生一些奇怪的事情,因此最好将 maxSpeed 设置为最适合您的值。