Version: 2020.3
重要的类 - Transform
重要的类 - Quaternion

Important Classes - Vectors

Vectors are a fundamental mathmatical concept which allow you to describe a direction and magnitude. In games and apps, vectors are often used describe some of the fundamental properties such as the position of a character, the speed something is moving, or the distance between two objects.

Vector arithmetic is fundamental to many aspects of computer programming such as graphics, physics and animation, and it is useful to understand it in depth to get the most out of Unity.

Vectors can be expressed in multiple dimensions, and Unity provides the Vector2, Vector3 and Vector4 classes for working with 2D, 3D, and 4D vectors. These three types of Vector classes all share many of the same functions, such as magnitude, so most of the information on this page applies to all three types of Vector unless otherwise specified.

This page provides an overview of the Vector classes and their common uses when scripting with them. For an exhaustive reference of every member of the vector classes, see the script reference pages for Vector2, Vector3 and Vector4.

Understanding Vector Arithmetic

Addition

当两个矢量相加时,结果相当于将原始矢量依次作为“步骤”。请注意,两个参数的顺序无关紧要,因为两种方式的结果都相同。

如果将第一个矢量视为空间中的一个点,那么第二个矢量可以解释为从该位置的偏移或“跳跃”。例如,为了找到地面上某个位置上方 5 个单位的点,可使用以下计算:

 var pointInAir = pointOnGround + new Vector2(0, 5);

如果矢量代表力,那么从力的方向和大小来考虑它们将会更直观。两个力矢量相加会产生一个等于力的组合的新矢量。施加的力同时有若干单独分量起作用时(例如,向前推进的火箭还可能受到侧风影响),此概念通常很有用。

Although the examples here show 2D vectors, the same concept applies to 3D and 4D vectors.

Subtraction

矢量减法通常用于获取从一个对象到另一个对象的方向和距离。请注意,两个参数的顺序对于减法很__重要__:

// 矢量 d 的大小与 c 相同,但指向相反的方向。
var c = b - a;
var d = a - b;

与数字一样,与负向矢量相加相当于减去正向矢量。

// 这两者得出相同的结果。
var c = a - b;
var c = a + -b;

负向矢量的大小与原始矢量相同并沿着同一条线指向,但在完全相反的方向上。

Direction and Distance from One Object to Another

如果从空间中的一个点减去另一个点,则得到的结果是从一个对象“指向”另一个对象的矢量:

// 获取从玩家位置指向目标位置的矢量。
var heading = target.position - player.position;

As well as pointing in the direction of the target object, this vector’s magnitude is equal to the distance between the two positions. You may need a “normalized” vector giving the direction to the target, but with a fixed distance (say for directing a projectile). You can normalize a vector by dividing it by its own magnitude:

var distance = heading.magnitude;
var direction = heading / distance; // This is now the normalized direction.

此方法优于单独使用大小和归一化属性,因为大小和归一化属性都非常耗费 CPU(都涉及计算平方根)。

如果只需要使用距离进行比较(例如,进行接近检查),则可以完全避免大小计算。sqrMagnitude 属性给出大小值的平方,计算方式与大小相似,但不需要进行耗时的平方根运算。不要将大小与已知距离进行比较,可将大小的平方与距离的平方进行比较:

if (heading.sqrMagnitude < maxRange * maxRange) {
    // 目标在范围内。
}

这种算法比在比较中使用真实大小要高效得多。

Sometimes, when working in 3D, you might need an “overground heading” to a target. For example, imagine a player standing on the ground who needs to approach a target floating in the air. If you subtract the player’s position from the target’s then the resulting vector will point upwards towards the target. This is not suitable for orienting the player’s transform since they will also point upwards; what is really needed is a vector from the player’s position to the position on the ground directly below the target. You can obtain this by taking the result of the subtraction and setting the Y coordinate to zero:-

var heading = target.position - player.position;
heading.y = 0;  // 这是平行于地面的方向。

Scalar Multiplication and Division

在讨论矢量时,通常将普通数(例如,浮点值)称为标量。这意味着标量只有“标度”或大小,而矢量兼具大小和方向。

将矢量乘以标量会产生与原始矢量方向相同的矢量。但是,新矢量的大小等于原始大小乘以标量值。

同样,标量除法将原始矢量的大小除以标量。

当矢量表示移动偏移或力时,这些运算很有用。通过这些运算可以更改矢量的大小而不影响其方向。

当任何矢量除以其自身的大小时,得到的结果是大小为 1 的矢量,即所谓的归一化矢量。如果归一化矢量乘以标量,则结果的大小将等于该标量值。当力的方向恒定但强度可控时(例如,来自车轮的力总是向前推动,但是动力由驾驶员控制),这会很有用。

Dot Product

点积取两个矢量并返回标量。该标量等于两个矢量相乘的大小,得到的结果再乘以矢量之间角度的余弦。当两个矢量都被归一化时,余弦本质上表示第一个矢量在第二个矢量的方向上延伸的距离(反之亦然 - 参数的顺序无关紧要)。

Below you can see a comparison of how vectors of varying angles compared with a reference vector return a dot product value between 1 and –1 :

The dot product is a mathematically simpler operation than calculating the cosine, so it can be used in place of the Mathf.Cos function or the vector magnitude operation in some circumstances (it doesn’t do exactly the same thing but sometimes the effect is equivalent). However, calculating the dot product function takes much less CPU time and so it can be a valuable optimization.

The dot product is useful if you want to calculate the amount of one vector’s magnitude that lies in the direction of another vector.

For example, a car’s speedometer typically works by measuring the rotational speed of the wheels. The car may not be moving directly forward (it may be skidding sideways, for example) in which case part of the motion will not be in the direction the car is facing - and so won’t be measured by the speedometer. The magnitude of an object’s rigidbody.velocity vector will give the speed in its direction of overall motion but to isolate the speed in the forward direction, you should use the dot product:

var fwdSpeed = Vector3.Dot(rigidbody.velocity, transform.forward);

当然,方向可以是您喜欢的任何方向,但为了进行此计算,必须对方向矢量进行归一化。这样,不仅结果比速度大小更准确,而且无需执行在查找大小时需要的缓慢的平方根运算。

Cross Product

The cross product is only meaningful for 3D vectors. It takes two 3D vectors as input and returns another 3D vector as its result.

The result vector is perpendicular to the two input vectors. You can use the “left hand rule” to remember the direction of the output vector from the ordering of the input vectors. If the first parameter is matched up to the thumb of the hand and the second parameter to the forefinger, then the result will point in the direction of the middle finger. If the order of the parameters is reversed then the resulting vector will point in the exact opposite direction but will have the same magnitude.

结果的大小等于输入矢量的大小相乘,然后该值再乘以二者之间角度的正弦。正弦函数的一些有用值如下所示:

The cross product can seem complicated since it combines several useful pieces of information in its return value. However, like the dot product, it is very efficient mathematically and can be used to optimize code that would otherwise depend on slower transcendental functions such as sine and cosine.

Computing a Normal/Perpendicular vector

A “normal” vector (ie. a vector perpendicular to a plane) is required frequently during mesh generation and is also useful in path following and other situations. Given three points in the plane, say the corner points of a mesh triangle, you can find the normal as follows: - Pick one of the three points - Subtract it from each of the two other points separately (resulting in two new vectors, “Side 1” and “Side 2”) - Calculate the cross product of the vectors “Side 1” and “Side 2” - The result of the cross product is a new vector that is perpendicular to the plane the three original points lie on - the “normal”.

Vector3 a;
Vector3 b;
Vector3 c;

Vector3 side1 = b - a;
Vector3 side2 = c - a;

Vector3 normal = Vector3.Cross(side1, side2);

The “left hand rule” can be used to decide the order in which the two vectors should be passed to the cross product function. As you look down at the top side of the surface (from which the normal will point outwards) the first vector should sweep around clockwise to the second:

如果输入矢量的顺序颠倒,结果将指向完全相反的方向。

对于网格,法向矢量也必须归一化。可通过归一化属性来实现此目的,但是还有另一个偶尔有用的技巧。还可以将垂直矢量除以其大小,从而将其归一化:

float perpLength = perp.magnitude;
perp /= perpLength;

Another useful note is that the area of the triangle is equal to perpLength / 2. This is useful if you need to find the surface area of the whole mesh or want to choose triangles randomly with probability based on their relative areas.

重要的类 - Transform
重要的类 - Quaternion