夹紧四元数旋转的问题
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;
我已经对此进行了一些研究,但似乎没有任何正确的方法。希望有人能阐明我做错了什么。
在我正在开发的这个 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;