夹紧四元数旋转的问题

Problems clamping quaternion rotation

我已经对此进行了一些研究,但似乎没有任何正确的方法。希望有人能阐明我做错了什么。

在我正在开发的这个 2D Unity 游戏中,我希望大炮跟随鼠标并绕 z 轴旋转。当前的代码正是这样做的,但我也想限制旋转。

Vector3 dir = Camera.main.ScreenToWorldPoint (Input.mousePosition);
    Quaternion targetRotation = Quaternion.LookRotation(transform.position - dir.normalized, Vector3.forward);
    targetRotation.x = 0;
    targetRotation.y = 0;
    transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, Time.deltaTime * rotationSpeed * 10);

我试过使用if-语句来限制旋转:

if(eulerAngle > 65 && eulerAngle < 295) //pseudo code
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, Time.deltaTime * rotationSpeed * 10)

这可行,但会将大炮的炮管锁定在 65 或 295 度。我没有运气使用 if 语句来 "unlock" 桶形旋转。

我也尝试过使用四元数的类似语句:

float amountToRotate = Quaternion.Angle (transform.rotation, targetRotation);

我猜,由于四元数的工作方式,即使远离目标,角度也会增加。类似于复平面上的数字?

mathf.clamp 函数一点运气都没有。

所有这些问题的解决方案可能都有一个简单的解决方案,但我似乎无法解决。

编辑:我更愿意使用 mathf.clamp,因为这似乎是 "cleanest" 解决方案。

问题似乎出在您的 if 状态逻辑中。

让我们把它分解成一些逻辑块:

  • 如果值大于 65 > 检查下一个块

如果不是这种情况,则表示该值小于或等于 65,并且 if 不会 运行。在下一个块中(如果值超过 65)

  • 如果值低于 295 > 执行 if 语句

如果不是这种情况,则表示该值大于或等于 295。

首先,我建议将您的 if 语句改为包含等于

if(eulerAngle >= 65 && eulerAngle <= 295)

这让我们可以少考虑一些检查。现在我们知道,如果你的大炮旋转冻结,那是因为角度低于 65 ( < 65) 或高于 295 (> 295)。

为了使 if 语句能够继续,您将希望该值再次位于这些值之间,因为您还向这些值添加了 = 检查。您现在可以根据超出范围将它们设置为 65 或 295。示例给你一个想法:

else if( eulerAngle < 65)
    eulerAngle = 65;