为什么我的 2 个向量的角度函数 return NaN 即使我遵循公式
Why is my angle of 2 vectors function return NaN even though i follow the formula
我正在制作一个函数,使用点积公式为我的统一游戏计算 2 个给定向量之间的角度:
vector(a)*vector(b)=|vector(a)|*|vector(b)|*cos(the angle)
所以我认为角度等于
acos((vector(a)*vector(b))/(|vector(a)|*|vector(b)|))
无论如何,这是我的代码:
float rotateAngle(Vector2 a,Vector2 b)
{
return Mathf.Acos((a.x * b.x + a.y * b.y) / ((Mathf.Sqrt(a.x * a.x + a.y * a.y)) * (Mathf.Sqrt(b.x * b.x + b.y * b.y)))) * (180 / Mathf.PI);
}
但是当我播放它时,控制台显示 NaN
。我尝试并查看了代码和公式,但空手而归。
有人可以帮助我吗?先谢谢你!!
NaN 通常是对浮点数进行无效数学运算的结果。一个常见的来源是除以零,所以我猜向量是 0,0。
我还建议使用内置函数来计算规范化,Length/Magnitude,点等,这将使代码更易于阅读,编译器应该相当擅长优化这种代码。如果您需要进行任何额外的优化,请在完成一些测量后进行。
float.NaN
是未定义(对于实数)数学运算的结果,例如 0 / 0
(请注意文档中 x / 0
其中 x != 0
而不是 returns 正无穷大或负无穷大)或负值的平方根。一旦操作中的一个操作符已经是 NaN
,那么整个操作也是 returns 再次 NaN
.
第二个(负值的平方根)在这里不会发生,因为您使用的是平方值,所以很可能您的向量的大小为 0
。
如果您查看 Vector2
source code you will find their implementation of Vector2.Angle
or Vector2.SignedAngle
(顺便说一句,您应该使用它,因为它们经过测试并且效率更高)。
public static float Angle(Vector2 from, Vector2 to)
{
// sqrt(a) * sqrt(b) = sqrt(a * b) -- valid for real numbers
float denominator = (float)Math.Sqrt(from.sqrMagnitude * to.sqrMagnitude);
if (denominator < kEpsilonNormalSqrt)
return 0F;
float dot = Mathf.Clamp(Dot(from, to) / denominator, -1F, 1F);
return (float)Math.Acos(dot) * Mathf.Rad2Deg;
}
// Returns the signed angle in degrees between /from/ and /to/. Always returns the smallest possible angle
public static float SignedAngle(Vector2 from, Vector2 to)
{
float unsigned_angle = Angle(from, to);
float sign = Mathf.Sign(from.x * to.y - from.y * to.x);
return unsigned_angle * sign;
}
在那里你会发现他们检查的第一件事是
float denominator = (float)Math.Sqrt(from.sqrMagnitude * to.sqrMagnitude);
if (denominator < kEpsilonNormalSqrt)
return 0F;
这基本上可以确保两个给定的向量都具有“足够大”的幅度,特别是不是 0
;)
长话短说:不要重新发明轮子,而是使用已经内置的 Vector2.Angle
or Vector2.SignedAngle
我正在制作一个函数,使用点积公式为我的统一游戏计算 2 个给定向量之间的角度:
vector(a)*vector(b)=|vector(a)|*|vector(b)|*cos(the angle)
所以我认为角度等于
acos((vector(a)*vector(b))/(|vector(a)|*|vector(b)|))
无论如何,这是我的代码:
float rotateAngle(Vector2 a,Vector2 b)
{
return Mathf.Acos((a.x * b.x + a.y * b.y) / ((Mathf.Sqrt(a.x * a.x + a.y * a.y)) * (Mathf.Sqrt(b.x * b.x + b.y * b.y)))) * (180 / Mathf.PI);
}
但是当我播放它时,控制台显示 NaN
。我尝试并查看了代码和公式,但空手而归。
有人可以帮助我吗?先谢谢你!!
NaN 通常是对浮点数进行无效数学运算的结果。一个常见的来源是除以零,所以我猜向量是 0,0。
我还建议使用内置函数来计算规范化,Length/Magnitude,点等,这将使代码更易于阅读,编译器应该相当擅长优化这种代码。如果您需要进行任何额外的优化,请在完成一些测量后进行。
float.NaN
是未定义(对于实数)数学运算的结果,例如 0 / 0
(请注意文档中 x / 0
其中 x != 0
而不是 returns 正无穷大或负无穷大)或负值的平方根。一旦操作中的一个操作符已经是 NaN
,那么整个操作也是 returns 再次 NaN
.
第二个(负值的平方根)在这里不会发生,因为您使用的是平方值,所以很可能您的向量的大小为 0
。
如果您查看 Vector2
source code you will find their implementation of Vector2.Angle
or Vector2.SignedAngle
(顺便说一句,您应该使用它,因为它们经过测试并且效率更高)。
public static float Angle(Vector2 from, Vector2 to) { // sqrt(a) * sqrt(b) = sqrt(a * b) -- valid for real numbers float denominator = (float)Math.Sqrt(from.sqrMagnitude * to.sqrMagnitude); if (denominator < kEpsilonNormalSqrt) return 0F; float dot = Mathf.Clamp(Dot(from, to) / denominator, -1F, 1F); return (float)Math.Acos(dot) * Mathf.Rad2Deg; } // Returns the signed angle in degrees between /from/ and /to/. Always returns the smallest possible angle public static float SignedAngle(Vector2 from, Vector2 to) { float unsigned_angle = Angle(from, to); float sign = Mathf.Sign(from.x * to.y - from.y * to.x); return unsigned_angle * sign; }
在那里你会发现他们检查的第一件事是
float denominator = (float)Math.Sqrt(from.sqrMagnitude * to.sqrMagnitude); if (denominator < kEpsilonNormalSqrt) return 0F;
这基本上可以确保两个给定的向量都具有“足够大”的幅度,特别是不是 0
;)
长话短说:不要重新发明轮子,而是使用已经内置的 Vector2.Angle
or Vector2.SignedAngle