【问题标题】:How to clamp camera rotation axis correctly?如何正确夹紧相机旋转轴?
【发布时间】:2021-06-08 12:05:10
【问题描述】:

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

任何帮助将不胜感激! 谢谢。

【问题讨论】:

    标签: c# unity3d camera game-development quaternions


    【解决方案1】:

    您可以围绕中心值重新定位欧拉角,然后钳制差异:

    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); 围绕本地权利而不是全局权利旋转。围绕全局右侧旋转可能会随着时间的推移产生滚动效果,您可能不希望这样做。

    【讨论】:

    • 感谢您的建议。我尝试运行它,但我仍然遇到同样的问题,只要 rotX 或 rotY 达到 extentX/extentY 值,它就会迅速切换到它的 centraX/centralY 值。我仍然习惯于使用四元数,如果我遗漏了任何明显的东西,我深表歉意。再次感谢您!
    【解决方案2】:

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

     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 之前的帮助 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-15
      • 1970-01-01
      • 2013-09-15
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多