有时当我移动鼠标(围绕角色旋转相机)时,我的角色会旋转。 但我没有鼠标任何字符旋转。 这是我的旋转代码,它仅依赖于键盘输入(我从标准统一样本中获取此代码):
private void ConvertMoveInput()
{
Vector3 localMove = transform.InverseTransformDirection(_moveInput);
_turnAmount = Mathf.Atan2(localMove.x, localMove.z);
_forwardAmount = localMove.z;
}
我发现有时当我移动鼠标Mathf.Atan2时返回数字PI,即使两个参数仍然等于零。这是怎么发生的?
我的演示项目here。
答案 0 :(得分:5)
请记住,atan2(x, z)
返回z轴与矢量之间的角度(x,z):
但是对于atan2(0, 0)
,你试图找到一个点与z轴或x轴之间的角度,这是没有意义的:
即使atan2(0, 0)
毫无意义,如果atan2(x, y)
和x
是有效数字,大多数编程语言数学库都会y
返回值而不是错误代码,并且在atan2(0, 0)
的特殊情况下,返回值为pi。 The implementation of atan2()
in the C++ standard library does this,我认为很多语言,包括Unity的C#实现,都是如此。
这意味着您需要检查x
和z
都是0的特殊情况。例如:
if ((localMove.x != 0) && (localMove.z != 0)) {
_turnAmount = Mathf.Atan2(localMove.x, localMove.z);
}
else {
_turnAmount = 0;
}
答案 1 :(得分:2)
tan
函数是周期性的,周期为π
。因此,在tan
和0
上调用π
会产生相同的值(即零)。
这是你不能简单地使用atan
来恢复原始角度的原因之一 - 你丢失了很多原始信息,而你所获得的角度只会介于{ {1}}和-π/2
。
+π/2
旨在解决此问题 - 它需要Atan2
和x
坐标,而不是它们的划分(这就是你使用y
的方式)。然后它可以找出角度的正确象限 - 适当地偏移它。同样重要的是,它处理atan
坐标为零时的情况 - 这通常会导致除零错误。例如,y
可能会返回0°,[1; 0]
270°(注意 - 我不确定确切的数字;这取决于“参考”的位置,我没有使用过此在Unity3D中。关键是原则,而不是确切的值。)
然而,这只有在至少有一个坐标不为零时才有效 - 坐标[0; 1]
不对[0; 0]
有任何有意义的角度。所有角度都同样有效(或两者都不同,具体取决于您的观点)。无论出于何种原因,Unity都会从所有可能的选项中选择[0; 0]
。它真的和其他任何东西一样好。唯一真正的替代方案是抛出一个异常并让你的游戏崩溃 - 这通常不会像这样的小故障首选:)