为什么我的 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