Unity - 将旋转角度限制在任意角度之间

3

我有一个任务,需要将一个角度夹在另外两个角度之间。

问题是限制可以是>360或<0

(例如[-45,45]或[275,45]).

有没有一种简洁的方法来考虑所有特殊情况?

(例如,范围[-45,45]和输入角度为225应该是-45)。

提前致谢! P.S. 我正在使用Unity,因此我手头有所有默认的Quaternion方法。

当前代码:

  Quaternion inputAngle = Quaternion.identity;
            if (Character.IsFacingRight)
                inputAngle = Quaternion.FromToRotation(forwardVector, playerInput);
            else
                inputAngle = Quaternion.FromToRotation(playerInput, forwardVector);
            Quaternion minAngle = Quaternion.Euler(0F, 0F, addedForce.force.angle);
            Quaternion angleRange = Quaternion.Euler(0F, 0F, addedForce.force.angleRange);
            Quaternion maxAngle = angleRange * minAngle;

            // var yaw = Math.Atan2(2.0 * (inputAngle.y * inputAngle.z + inputAngle.w * inputAngle.x), inputAngle.w * inputAngle.w - inputAngle.x * inputAngle.x - inputAngle.y * inputAngle.y + inputAngle.z * inputAngle.z);
            // var pitch = Math.Asin(-2.0 * (inputAngle.x * inputAngle.z - inputAngle.w * inputAngle.y));
            float roll = (float)Math.Atan2(2.0 * (inputAngle.x * inputAngle.y + inputAngle.w * inputAngle.z), inputAngle.w * inputAngle.w + inputAngle.x * inputAngle.x - inputAngle.y * inputAngle.y - inputAngle.z * inputAngle.z);

            Quaternion correctedRotation = Quaternion.Euler(0F, 0F, roll / Mathf.PI * 180F);

            float endAngleZ = ClampRotation2(correctedRotation.eulerAngles.z, minAngle.eulerAngles.z, maxAngle.eulerAngles.z);

            Quaternion endAngle = Quaternion.Euler(0F, 0F, endAngleZ);

ClampRotation2:

public static float ClampRotation2(float angle, float min, float max)
{
    if (angle < 0) angle += 360;

    if (max < 0) max += 360;

    if (min < 0) min += 360;
    if (min > max) min -= 360;

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

1
抱歉,请问您能否更详细地解释您的问题?您正在做什么?此外,在您的问题中添加您尝试过的代码会很有帮助。 - Programmer
@程序员 更新了帖子以包含我正在使用的当前代码。问题很简单:我有3个角度:最小值、最大值和输入角度,我希望输入角度始终在最小值和最大值之间。 - Borissow
好的,当前代码有什么问题?Mathf.Clamp应该可以解决... - Programmer
@程序员,实际上不是这样的,就像例子中提到的:范围为[-45,45],输入角度为225将返回45,但应该返回-45,因为在三角函数圆上,225更接近于-45。 - Borissow
1个回答

2

好的,我找到了一个解决方案,可以在所有情况下正确地夹住角度。

Quaternion.Angle()带给您:

Quaternion inputAngle = Quaternion.identity;
            if (Character.IsFacingRight)
                inputAngle = Quaternion.FromToRotation(forwardVector, playerInput);
            else
                inputAngle = Quaternion.FromToRotation(playerInput, forwardVector);
            Quaternion minAngle = Quaternion.Euler(0F, 0F, addedForce.force.angle);
            Quaternion angleRange = Quaternion.Euler(0F, 0F, addedForce.force.angleRange);
            Quaternion maxAngle = angleRange * minAngle;

            float roll = (float)Math.Atan2(2.0 * (inputAngle.x * inputAngle.y + inputAngle.w * inputAngle.z), inputAngle.w * inputAngle.w + inputAngle.x * inputAngle.x - inputAngle.y * inputAngle.y - inputAngle.z * inputAngle.z);
            float correctedRotation = roll / Mathf.PI * 180F;

            float minAngleF = minAngle.eulerAngles.z;
            float maxAngleF = maxAngle.eulerAngles.z;

            if (correctedRotation < 0) correctedRotation += 360;

            if (maxAngleF < 0) maxAngleF += 360;

            if (minAngleF < 0) minAngleF += 360;
            if (minAngleF > maxAngleF) minAngleF -= 360;

            if (correctedRotation < minAngleF || correctedRotation > maxAngleF)
            {
                float rotationToMax = Quaternion.Angle(Quaternion.Euler(0F, 0F, correctedRotation), Quaternion.Euler(0F, 0F, maxAngleF));
                float rotationToMin = Quaternion.Angle(Quaternion.Euler(0F, 0F, correctedRotation), Quaternion.Euler(0F, 0F, minAngleF));
                if (Mathf.Abs(rotationToMax) < Mathf.Abs(rotationToMin))
                    correctedRotation = maxAngleF;
                else
                    correctedRotation = minAngleF;
            }
            Quaternion endAngle = Quaternion.Euler(0F, 0F, correctedRotation);

3
啊,我的宿敌,我们又见面了。四元数...总有一天我会理解你。 - Draco18s no longer trusts SE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接