平滑旋转 - 四元数

Smooth Rotation - Quaternions

我正在尝试制作第一人称角色控制器,但在平滑外观旋转方面遇到了问题。我的 LookRotation 脚本接受我的鼠标输入并使用它来旋转角色。尽管使用 Quaternion.Slerp() 存在问题,但我已使用 Quaternion.Slerp() 来平滑我的外观旋转。一旦所需的旋转距离当前旋转大于 180 度,它将只采用较短的路线(相反的方式)。问题出在最后两行代码中。有没有人有办法防止这个问题?提前致谢!

#region Variables
// Sensitivity variables
[Range(0.0f, 10.0f)] public float horizontalSensitivity = 2.0f, verticalSensitivity = 2.0f;

// Smoothing Variables
[Range(0.0f, 30.0f)] public float smoothAmount = 5.0f;

// Character rotation variables
private Quaternion characterTargetRotation;
private Quaternion cameraTargetRotation;

public Transform character;
public Transform characterCamera;    
#endregion

private void Update()
{
    float horizontalRotation = Input.GetAxis("Mouse X") * horizontalSensitivity;
    float verticalRotation = Input.GetAxis("Mouse Y") * verticalSensitivity;

    characterTargetRotation *= Quaternion.Euler(0.0f, horizontalRotation, 0.0f);
    cameraTargetRotation *= Quaternion.Euler(-verticalRotation, 0.0f, 0.0f);

    character.localRotation = Quaternion.Lerp(_character.localRotation, characterTargetRotation, smoothAmount * Time.deltaTime);
    characterCamera.localRotation = Quaternion.Lerp(_characterCamera.localRotation, cameraTargetRotation, smoothAmount * Time.deltaTime);
}

无法使用四元数和 Lerp 完成,我使用欧拉角解决了这个问题。

    horizontalAngle += (Input.GetAxis("Mouse X") * horizontalSensitivity);
    verticalAngle += (-Input.GetAxis("Mouse Y") * verticalSensitivity);

    horizontalSmoothAngle = Mathf.Lerp(horizontalSmoothAngle, horizontalRotation, smoothAmount * Time.deltaTime);
    verticalSmoothAngle = Mathf.Lerp(verticalSmoothAngle , verticalRotation, smoothAmount * Time.deltaTime);

    horizontalRotation = Quaternion.Euler(0, smoothRotation ? horizontalSmoothAngle: horizontalAngle, 0);
    verticalRotation = Quaternion.Euler(smoothRotation ? verticalSmoothAngle : verticalAngle, 0, 0);

使用此方法会产生您必须处理的替代问题,但使用四元数和 Lerp 会产生无法解决的问题。如上所述,Lerp 将始终找到最短距离。 Eulers 可以达到您想要的最高值(或者更准确地说,达到数据类型允许的最高值),因此它没有这个问题。

虽然如果您继续增加角度,这对普通玩家来说不太可能成为问题,但在这种情况下 float 的数据类型最终会失去精度。为避免这种情况,只需减去或添加(取决于值是正数还是负数)角度和平滑角度的 360 度的任何倍数,其数量足够高,不会影响 Lerp.

使用此方法获取 x 轴上的起始角度存在一些问题,但与此问题无关,因此任何想知道如何做到这一点的人都必须找到解决该问题的替代来源。