包含此页的版本:
不含此页的版本:
向量是一个基本的数学概念,它允许您描述方向和大小。在游戏和应用程序中,向量通常用于描述基本属性,例如角色的位置、物体移动的速度或两个对象之间的距离。
矢量算术是计算机编程许多方面的基础,例如图形、物理和动画,深入了解它对于充分利用 Unity 非常有用。
向量可以在多维度上表示,Unity 提供了用于处理 2D、3D 和 4D 向量的 Vector2、Vector3 和 Vector4 类。 这三种类型的 Vector 类都共享许多相同的函数,例如大小,因此除非另有说明,否则本页上的大多数信息都适用于所有三种类型的 Vector。
本页概述了 Vector 类及其在编写脚本时的常见用途。有关向量类的每个成员的详尽参考,请参阅 Vector2、Vector3 和 Vector4 的脚本参考页面。
当两个向量相加时,结果相当于将原始向量作为“步骤”,一个接一个。请注意,两个参数的顺序无关紧要,因为无论哪种方式结果都是相同的。
如果第一个向量被当作空间中的一个点,那么第二个向量可以解释为从该位置的偏移或“跳跃”。例如,要查找地面上某个位置上方 5 个单位的点,可以使用以下计算:
var pointInAir = pointOnGround + new Vector2(0, 5);
如果向量代表力,那么根据它们的方向和大小来考虑它们会更直观(大小表示力的大小)。添加两个力向量将产生一个与力组合相等的新向量。当同时作用多个独立组件时施加力时,这个概念通常很有用(例如,向前推进的火箭也可能受到侧风的影响)。
此处的示例使用 2D 矢量,但相同的概念适用于 3D 和 4D 矢量。
矢量减法最常用于获取从一个对象到另一个对象的方向和距离。请注意,两个参数的顺序对于减法很重要:
// The vector d has the same magnitude as c but points in the opposite direction.
var c = b - a;
var d = a - b;
与数字一样,将向量的负数相加与减去正数相同。
// These both give the same result.
var c = a - b;
var c = a + -b;
向量的负数与原始矢量具有相同的大小,并且指向同一条线,但方向完全相反。
如果空间中的一个点从另一个点中减去,那么结果是一个从一个对象“指向”另一个对象的向量:
// Gets a vector that points from the player's position to the target's.
var heading = target.position - player.position;
除了指向目标物体的方向外,该向量的大小也等于两个位置之间的距离。您可能需要一个“归一化”向量来给出目标的方向,但距离是固定的(例如用于引导射弹)。您可以通过将向量除以自己的大小来归一化向量:
var distance = heading.magnitude;
var direction = heading / distance; // This is now the normalized direction.
这种方法比单独使用大小和归一化属性更可取,因为它们都非常耗费 CPU(它们都涉及计算平方根)。
如果您只需要使用距离进行比较(例如,用于邻近度检查),那么您可以完全避免大小计算。这sqrMagnitude属性给出了大小值的平方,并且与大小一样计算,但没有耗时的平方根运算。您可以将大小的平方与距离的平方进行比较,而不是将大小与已知距离进行比较:
if (heading.sqrMagnitude < maxRange * maxRange) {
// Target is within range.
}
这比在比较中使用真实幅度要有效得多。
有时,在 3D 中工作时,您可能需要一个指向目标的“地面航向”。例如,想象一个玩家站在地上,需要接近漂浮在空中的目标。如果从目标的位置中减去玩家的位置,则生成的向量将向上指向目标。这不适合调整玩家的变换方向,因为它们也会指向上方;真正需要的是从玩家位置到目标正下方地面位置的向量。您可以通过获取减法结果并将 Y 坐标设置为零来获得此值:
var heading = target.position - player.position;
heading.y = 0; // This is the overground heading.
在讨论向量时,通常将普通数字(例如浮点数)称为标量。这样做的意思是,标量只有“尺度”或大小,而向量同时具有大小和方向。
将向量乘以标量会得到指向与原始方向相同的向量。但是,新向量的大小等于原始大小乘以标量值。
同样,标量除法将原始向量的大小除以标量。
当矢量表示运动偏移或力时,这些作非常有用。它们允许您在不影响其方向的情况下更改矢量的大小。
当任何向量除以其自身的大小时,结果是大小为 1 的向量,称为归一化向量。如果归一化向量乘以标量,则结果的大小将等于该标量值。当力的方向恒定但强度可控时(例如,来自汽车车轮的力总是向前推动,但动力由驾驶员控制),这很有用。
点积采用两个向量并返回一个标量。该标量等于两个向量的大小相乘,结果乘以向量之间角度的余弦。当两个向量都归一化时,余弦本质上表示第一个向量在第二个向量方向上延伸多远(反之亦然 - 参数的顺序无关紧要)。
下面您可以看到不同角度的向量与参考向量相比如何返回 1 和 –1 之间的点积值的比较:
点积在数学上比计算余弦更简单,因此可以用它来代替Mathf.Cos函数或矢量幅度运算(它不会做完全相同的事情,但有时效果是等效的)。然而,计算点积函数需要更少的 CPU 时间,因此它可能是一个有价值的优化。
如果要计算一个向量位于另一个向量方向的大小的量,点积非常有用。
例如,汽车的车速表通常通过测量车轮的转速来工作。汽车可能不会直接向前移动(例如,它可能会侧向打滑),在这种情况下,部分运动不会在汽车所面向的方向上 - 因此不会被车速表测量。对象的rigidbody.velocityvector 将给出其整体运动方向的速度,但要隔离正向速度,您应该使用点积:
var fwdSpeed = Vector3.Dot(rigidbody.velocity, transform.forward);
方向可以是你喜欢的任何方向,但对于此计算,方向向量必须始终归一化。结果不仅比速度的大小更准确,而且还避免了查找大小所涉及的缓慢平方根运算。
叉积仅对 3D 矢量有意义。它接受两个 3D 向量作为输入,并返回另一个 3D 向量作为其结果。
结果向量垂直于两个输入向量。您可以使用“右旋螺丝规则”从输入向量的顺序中记住输出向量的方向。如果可以按照输入向量的顺序卷曲手指,则拇指指向输出向量的方向。如果参数的顺序颠倒,则生成的向量将指向完全相反的方向,但大小相同。
结果的大小等于输入向量的大小相乘,然后该值乘以它们之间角度的正弦。正弦函数的一些有用值如下所示:-
叉积可能看起来很复杂,因为它在其返回值中结合了几个有用的信息。然而,与点积一样,它在数学上非常有效,可用于优化代码,否则这些代码将依赖于较慢的超越函数,例如正弦和余弦。
在期间经常需要“法线”向量(即垂直于平面的向量)meshUnity 的主要图形原语。网格体构成了 3D 世界的很大一部分。Unity 支持三角或四边形多边形网格。Nurbs、Nurms、Subdiv 曲面必须转换为多边形。更多信息
请参阅术语表生成,在路径跟踪和其他情况下也很有用。给定平面中的三个点,比如网格三角形的角点,你可以按如下方式找到法线:
Vector3 a;
Vector3 b;
Vector3 c;
Vector3 side1 = b - a;
Vector3 side2 = c - a;
Vector3 normal = Vector3.Cross(side1, side2);
“左手法则”可用于决定将两个向量传递给叉积函数的顺序。当您低头看表面的顶部(法线将从那里指向外)时,第一个向量应该顺时针扫到第二个向量:
如果输入向量的顺序相反,结果将指向完全相反的方向。
对于网格,法向量也必须归一化。这可以通过归一化属性来完成,但还有另一个偶尔有用的技巧。您还可以通过将垂直向量除以其大小来归一化它:-
float perpLength = perp.magnitude;
perp /= perpLength;
另一个有用的注意事项是三角形的面积等于perpLength/ 2. 如果您需要找到整个网格的表面积,或者想要根据三角形的相对面积随机选择三角形,这非常有用。