c# - 为什么我的 2 个向量角度函数返回 NaN,即使我遵循公式

标签 c# unity-game-engine vector nan angle

我正在创建一个函数,使用点积公式计算 Unity 游戏的 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。我尝试并检查了代码和公式,但空手而归。

有人可以帮助我吗?提前谢谢您!!

最佳答案

float.NaN是未定义(对于实数)数学运算的结果,例如 0/0 (文档中的注释是 x/0 其中 x != 0 code> 相反返回正无穷大或负无穷大)或负值的平方根。一旦运算中的一个操作符已经是 NaN,那么整个运算也会再次返回 NaN

第二个(负值的平方根)在这里不会发生,因为您使用的是平方值,所以很可能您的向量的大小为 0


如果你看Vector2 source code你会发现他们的 Vector2.Angle 的实现或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.AngleVector2.SignedAngle

关于c# - 为什么我的 2 个向量角度函数返回 NaN,即使我遵循公式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68843016/

相关文章:

c++ - 从 vector 的元素初始化结构

unity-game-engine - 旋转对象使其面向相反方向

C# 为什么将类实例传递给接受对象作为参数并将其装箱回来的方法

c# - 如何从字符串中获取这些值?

unity-game-engine - 如果填充文本组件的文本未知,如何调整文本组件的高度?

c# - 角色移动、加速 C# Unity

c# - 如何在没有管理员权限的情况下读写注册表_C#

c# - 确定变量是否等于 'list' 值中的值的最简洁方法

ios - 在 ios 中未收到 Firebase 云消息传递通知

r - 向量元素的所有组合之间的乘积