如何正确夹紧360度重叠?

时间:2015-01-23 04:39:41

标签: unity3d camera unityscript quaternions euler-angles

我有一个相机脚本,如果我的角色正在旋转,相机也会旋转。但是,相机也可以旋转鼠标指针。此移动受特定度量的限制,例如30(maximumX)。因此,鼠标控制的相机移动范围应介于0到60之间,相当于-30和30度。

如果角色旋转整整360度,那么maxX值将重叠360并且必须返回0.而min可能会保持类似于300.这会产生一个问题,即相机将“捕捉”并且不会保留其先前的正确旋转。

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

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

我发现的问题是使用:

_target.localEulerAngles.y

作为基础。这是因为localEulerAngels在运行时只从0到360。在编辑器中,它没有被钳制。在跑步时,它被夹紧。这会大大改变一切,因为最初在旋转0时,如果你向左移动,它会循环到360.我正在将它视为-1。因此,认为我的数学错误或者我没有正确地夹紧。

Clamping不会做任何事情,因为它不会注意到任何关于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;
}

为了清楚起见,我将maxX设为m_rangeX,因为之前我把它作为2个单独的单位而且我目前正在使用30个双向方式。所以现在,相机可以正确地扫描玩家将鼠标指向_target.localEulerAngles.y - 30和_target.localEulerAngles.y + 30之间的圆形重叠。