Version: 2020.1
Important Classes - Transform
Important Classes - 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

При сложении 2 векторов результат эквивалентен тому, что получится если исходные векторы принять за следующие друг за другом “шаги”. Заметьте, что порядок двух слагаемых не важен, т.к. в любом случае результат будет одинаковый.

Если первый вектор принять за точку в пространстве, то второй вектор можно интерпретировать как сдвиг или “прыжок” из этой точки. Например, чтобы для поиска точки 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

Вычитание векторов чаще всего используется, чтобы узнать расстояние и направление одного объекта относительно другого. Заметьте, что при вычитании порядок параметров имеет значение:-

// 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;

Отрицательный вектор имеет ту же величину, что и исходный вектор, и лежит на той же прямой, только в обратном направлении.

Direction and Distance from One Object to Another

Если вычесть координаты одной точки в пространстве из координат другой, то получим вектор, который “выходит” из второй точки и “заканчивается” в первой:

// Gets a vector that points from the player's position to the target's.
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) {
    // Target is within range.
}

Это намного более эффективно, чем вычислять именно модуль при сравнении.

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;  // This is the overground heading.

Scalar Multiplication and Division

Говоря о векторах, в порядке вещей обращаться к обычным числам (например, значениям типа float) как к скалярам. Это значит, что у них есть только “размер” или величина, в то время как у векторов есть и величина и направление.

Умножение вектора на скаляр даёт в результате вектор, с тем же направлением, что и исходный вектор. Тем не менее, величина нового вектора равна исходной величине умноженной на скалярное значение.

Аналогично, скалярное деление делит исходную величину вектора на скаляр.

Эти операции полезны, когда вектор представляет из себя смещение движения или силу. Они позволяют вам изменить величину вектора без влияния на его направление.

Когда любой вектор делится на собственную величину, то в результате получается вектор величиной 1, известный как нормированный (единичный) вектор. Если нормированный вектор умножить на скаляр, то величина результата будет равна значению скаляра. Это полезно, когда направление силы постоянно, а величина - нет (например, сила от колеса автомобиля всегда толкает вперёд, но её мощность контролируется водителем).

Dot Product

Скалярное произведение получает 2 вектора и возвращает скаляр. Этот скаляр равен произведению величин этих векторов, умноженному на косинус угла между ними. Когда оба вектора - нормированные, косинус по сути дела утверждает, как далеко первый вектор простирается в направлении второго (или наоборот - порядок параметров роли не играет).

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:

Результат будет направлен в противоположную сторону, если поменять порядок исходных векторов.

Для мешей нормаль должна быть нормализована. Это может быть сделано с помощью свойства normalized, но есть другая хитрость, которая иногда может быть полезна. Вы можете нормализовать перпендикуляр, разделив его на его же длину:-

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.

Important Classes - Transform
Important Classes - Quaternion