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

问题描述

我正在尝试夹紧相机的 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,0);
    }

我在我的相机旋转函数中调用了它来钳制 rotX 和 rotY,这后来被应用于我的方向游戏对象的旋转。

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