如何正确夹持相机旋转轴?

How to clamp camera rotation axis correctly?

我正在尝试夹紧相机的 X 轴和 Y 轴,我已经设法做到了。但是,当钳位值达到 MAX 阈值时,它将跳回到 MIN 阈值! 知道是什么导致我的代码出现这种情况吗?

 private void ClimbingLookRotation()
    {
        if (input.mouseX != 0 || input.mouseY != 0f)
        {
            orientation.rotation *= Quaternion.AngleAxis(input.mouseX, Vector3.up);
            orientation.rotation *= Quaternion.AngleAxis(input.mouseY, Vector3.right);
        }

        var rotX = orientation.eulerAngles.x;
        var rotY = orientation.eulerAngles.y;

        rotX = Mathf.Clamp(rotX, 1, 25);
        rotY = Mathf.Clamp(rotY, 200, 355);            

        orientation.eulerAngles = new Vector3(rotX, rotY, 0);
    }

如有任何帮助,我们将不胜感激! 谢谢。

您可以将欧拉角围绕中心值重新居中,然后缩小差值:

float centralX = 13f;
float extentX = 12f;

float centralY = 277.5f;
float extentY = 77.5f;

private static float ClampEuler(float val, float center, float extent)
{
    return center + Mathf.Clamp((val - center + 360f) % 360f, -extent, extent);
}

private void ClimbingLookRotation()
{
    if (input.mouseX != 0 || input.mouseY != 0f)
    {
        orientation.rotation *= Quaternion.AngleAxis(input.mouseX, Vector3.up);
        orientation.rotation *= Quaternion.AngleAxis(input.mouseY, Vector3.right);
    }

    var rotX = orientation.eulerAngles.x;
    var rotY = orientation.eulerAngles.y;

    rotX = ClampEuler(rotX, centralX, extentX);
    rotY = ClampEuler(rotY, centralY, extentY);

    orientation.eulerAngles = new Vector3(rotX, rotY, 0);
}

顺便说一句,您可能想要 orientation.rotation *= Quaternion.AngleAxis(input.mouseY, orientation.right); 围绕局部右转而不是全局右转。围绕全局右旋转可能会随着时间的推移产生滚动效果,这可能是您不想要的。

我发现了一些效果很好的东西所以我想我会回答以防它对任何人有帮助!

 public static float ClampAngle(float angle, float min, float max)
    {   //Normalises angle value passed in between -180 to 180 to make the angle clampable
        angle = NormalizeAngle(angle);
        if (angle > 180)
        {
            angle -= 360;
        }
        else if (angle < -180)
        {
            angle += 360;
        }

        min = NormalizeAngle(min);
        if (min > 180)
        {
            min -= 360;
        }
        else if (min < -180)
        {
            min += 360;
        }

        max = NormalizeAngle(max);
        if (max > 180)
        {
            max -= 360;
        }
        else if (max < -180)
        {
            max += 360;
        }

        return Mathf.Clamp(angle, min, max);
    }

    public static float NormalizeAngle(float angle)
    { //If the angle is above or below 360 degrees, normalise it
        while (angle > 360)
            angle -= 360;
        while (angle < 0)
            angle += 360;
        return angle;
    }

然后只需在需要限制值的地方调用 ClampAngle 方法,例如:

private void ClimbingLookRotation()
    {
        if (input.mouseX != 0 || input.mouseY != 0f)
        {
            orientation.rotation *= Quaternion.AngleAxis(input.mouseX, Vector3.up);
            orientation.rotation *= Quaternion.AngleAxis(input.mouseY, Vector3.right);
        }

        var rotX = orientation.eulerAngles.x;
        var rotY = orientation.eulerAngles.y;

        rotX = HelperFunctions.ClampAngle(rotX, -10, 25); //Here
        rotY = HelperFunctions.ClampAngle(rotY, 200, 340); //And here

        orientation.eulerAngles = new Vector3(rotX, rotY, 0);
    }

我在我的相机旋转函数中调用它来夹住 rotX 和 rotY,稍后应用于我的方向游戏对象的旋转。

再次感谢 Ruzihm 之前的帮助:)