如何正确夹持360度重叠?

How to properly clamp 360 degrees overlap?

我有一个相机脚本,如果我的角色在旋转,相机也会旋转。然而,相机也可以通过鼠标指针旋转。这种运动受到一组特定的给定度数的限制,比如 30 (maximumX)。所以鼠标控制的相机移动范围应该在0到60之间,相当于-30到30度。

如果角色旋转整整 360 度,则 maxX 值与 360 度重叠,必须返回到 0。而最小值可能保持在 300 左右。这会造成相机 "snap" 和没有正确保留其之前的旋转。

var newMaxX = ClampAngle(_target.localEulerAngles.y + maximumX, -360, 360);
var newMinX = ClampAngle(_target.localEulerAngles.y - maximumX, -360, 360);
if(newMinX > newMaxX)
{
    var tmp = newMaxX;
    newMaxX = newMinX;
    newMinX = tmp;
}

if (axes == RotationAxes.MouseXAndY) {
    rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    rotationY += Input.GetAxis("Mouse Y") * sensitivityY;

    rotationX = ClampAngle (rotationX, newMinX, newMaxX);
    rotationY = ClampAngle (rotationY, minimumY, maximumY);

    var xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
    var yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);

    cameraTransform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
else if (axes == RotationAxes.MouseX) 
{
    rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    rotationX = ClampAngle (rotationX, newMinX, newMaxX);

    xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
    cameraTransform.localRotation = originalRotation * xQuaternion;
}
else 
{
    rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
    rotationY = ClampAngle (rotationY, minimumY, maximumY);

    yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
    cameraTransform.localRotation = originalRotation * yQuaternion;
}

这是 ClampAngle 函数:

static function ClampAngle (angle : float, min : float, max : float) : float
{
    if (angle < -360.0)
        angle += 360.0;
    if (angle > 360.0)
        angle -= 360.0;
    return Mathf.Clamp (angle, min, max);
}

有什么建议吗?

我发现的问题是使用:

_target.localEulerAngles.y

作为基地。这是因为 localEulerAngels 在 运行 时只能从 0 到 360。在编辑器中,它没有被限制。 运行时,钳位。这会极大地改变事情,因为最初在旋转 0,如果你向左移动,它会循环到 360。我把它当作它会去 -1。因此,认为我的数学错误或者我没有正确夹紧。

夹紧不会做任何事情,因为它不会注意到任何关于 0 变成 360 的事情。

因此,我决定将其视为 -180 到 180。

var eulerTargetY = _target.localEulerAngles.y;
var newMaxX = 0;
var newMinX = 0; 

if(eulerTargetY > 180)
{
    var adjustedEuler = eulerTargetY - 360;
    newMaxX = adjustedEuler + m_rangeX;
    newMinX = adjustedEuler - m_rangeX;
}
else
{
    newMaxX = eulerTargetY + m_rangeX;
    newMinX = eulerTargetY - m_rangeX;
}

var xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
var yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = ClampAngle (rotationY, minimumY, maximumY);
rotationX = ClampAngle (rotationX, newMinX, newMaxX);

if (axes == RotationAxes.MouseXAndY) {
    cameraTransform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
else if (axes == RotationAxes.MouseX) 
{
    cameraTransform.localRotation = originalRotation * xQuaternion;
}
else 
{
    cameraTransform.localRotation = originalRotation * yQuaternion;
}

为清楚起见,我将 maximumX 设为 m_rangeX,因为之前我将它作为 2 个独立的单元使用,而目前我同时使用 30 个。所以现在,相机可以正确扫描玩家将鼠标指向 _target.localEulerAngles.y - 30 和 _target.localEulerAngles.y + 30 之间的圆形重叠区域。