Плавный поворот по вектору Unity
данный код резко поворачивает объект по направлению вектора. А как сделать плавный поворот по вектору?
Отслеживать
задан 13 янв 2020 в 12:40
BigCubeCat BigCubeCat
740 7 7 серебряных знаков 20 20 бронзовых знаков
Либо используйте корутины, либо в Update используйте множитель Time.deltaTime
13 янв 2020 в 12:42
поворачивайте с помощью физики + Time.deltaTime
13 янв 2020 в 12:42
И ещё, не называл бы ты переменные направления, как rotation. То, что ты называешь rotation, в твоём случае это direction.
16 янв 2020 в 3:38
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
[SerializeField] float _velocity = 10; //скорость поворота Transform _target; //Цель, за которой будем следить public void SetTarget(Transform target) < _target = target; //устанавливаем цель, например откуда-то снаружи >private void Update() < if (_target != null) //если есть цель - поворачиваемся в её сторону < Vector2 new_rotation = _target.position - transform.position; transform.up = Vector2.MoveTowards(transform.up, new_rotation, Time.deltaTime * _velocity); >>
Метод Vector2.MoveTowards (и его перегрузки для других значимых типов) сдвигает нас от текущего значения в сторону целевого на значение третьего параметра (maxDistanceDelta), но не дальше, чем до целевого значения. Например:
Mathf.MoveToward(0, 1, 0.5f) //вернёт 0.5f Mathf.MoveToward(0.7f, 1, 0.5f) //вернёт 1 Mathf.MoveToward(0.5f, 0, 0.6f) //вернёт 0
Направление и расстояние от одного объекта до другого.
Если вычесть координаты одной точки в пространстве из координат другой, то получим вектор, который “выходит” из второй точки и “заканчивается” в первой:
// 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. >
Это намного более эффективно, чем вычислять именно модуль при сравнении.
Иногда, требуется узнать направление к надземной цели. Например, представьте, что игроку, который стоит на земле нужно приблизиться к парящему в воздухе предмету. Если вычесть координаты позиции игрока из координат цели, тогда полученный вектор будет указывать вверх и по направлению к цели. Этот вариант не подходит, чтобы придать ориентацию компоненту transform игрока, так как он тоже будет указывать вверх. Что тут действительно нужно сделать — это вычислить вектор от игрока к позиции на земле прямо под предметом. Это легко сделать, если у вектора, являющегося результатом вычитания, установить координату Y в ноль:-
var heading = target.position - player.position; heading.y = 0; // This is the overground heading.
Понимание векторной арифметики
Векторная арифметика — основа 3D графики, физики и анимации, и, для получения максимальной отдачи от Unity, весьма полезно досконально разбираться в этой теме. Ниже приведены описания основных операций и несколько советов о том, для чего они могут быть использованы.
Сложение
При сложении 2 векторов результат эквивалентен тому, что получится если исходные векторы принять за следующие друг за другом “шаги”. Заметьте, что порядок двух слагаемых не важен, т.к. в любом случае результат будет одинаковый.

Если первый вектор принять за точку в пространстве, то второй вектор можно интерпретировать как сдвиг или “прыжок” из этой точки. Например, чтобы для поиска точки 5-тью единицами выше точки на земле, вы могли бы использовать следующий расчёт:-
var pointInAir = pointOnGround + new Vector3(0, 5, 0);
Вычитание
Вычитание векторов чаще всего используется, чтобы узнать расстояние и направление одного объекта относительно другого. Заметьте, что при вычитании порядок параметров имеет значение:-

// 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;
Отрицательный вектор имеет ту же величину, что и исходный вектор, и лежит на той же прямой, только в обратном направлении.
Скалярные умножение и деление
Говоря о векторах, в порядке вещей обращаться к обычным числам (например, значениям типа float) как к скалярам. Это значит, что у них есть только “размер” или величина, в то время как у векторов есть и величина и направление.
Умножение вектора на скаляр даёт в результате вектор, с тем же направлением, что и исходный вектор. Тем не менее, величина нового вектора равна исходной величине умноженной на скалярное значение.
Аналогично, скалярное деление делит исходную величину вектора на скаляр.
Эти операции полезны, когда вектор представляет из себя смещение движения или силу. Они позволяют вам изменить величину вектора без влияния на его направление.
Когда любой вектор делится на собственную величину, то в результате получается вектор величиной 1, известный как нормированный (единичный) вектор. Если нормированный вектор умножить на скаляр, то величина результата будет равна значению скаляра. Это полезно, когда направление силы постоянно, а величина — нет (например, сила от колеса автомобиля всегда толкает вперёд, но её мощность контролируется водителем).
Скалярное произведение (Dot Product)
Скалярное произведение получает 2 вектора и возвращает скаляр. Этот скаляр равен произведению величин этих векторов, умноженному на косинус угла между ними. Когда оба вектора — нормированные, косинус по сути дела утверждает, как далеко первый вектор простирается в направлении второго (или наоборот — порядок параметров роли не играет).

Если работать с точки зрения углов, то можно достаточно просто найти соответствующие косинусы используя калькулятор. Тем не менее, полезно иметь интуитивное понимание основных значений косинуса, как показано на диаграмме ниже:-

Скалярное произведение — это очень простая операция, которую, при некоторых обстоятельствах, можно использовать вместо функции Mathf.Cos или операции векторных величин (оно не делает в точности то же самое, но иногда эффект получается одинаковый). Тем не менее, вычисление скалярного произведения на уровне процессора проходит значительно быстрее, так что оно может оказаться ценной оптимизацией.
Векторное произведение (Cross Product)
Другие операции предназначены для 2D или 3D векторов и для действительных векторов с любым числом измерений. Векторное произведение же, напротив, имеет смысл применять только для 3D векторов. Оно использует 2 вектора как входную информацию и возвращает ещё один вектор в качестве результата.
Итоговый вектор перпендикулярен двум исходным векторам. Можно использовать “правило левой руки”, чтобы запомнить направление выходного вектора относительно исходных векторов. Если первый параметр совпадает с большим пальцем руки, а второй параметр с указательным пальцем, то результат будет указывать в направлении среднего пальца. Если использовать обратный порядок параметров, то тогда итоговый вектор будет указывать в противоположном направлении, но его величина не изменится.

Величина результата равна произведению величин исходных векторов, умноженному на синус угла между ними. Некоторые полезные значения функции синуса указаны ниже:-

Векторное произведение может выглядеть сложным, т.к. оно включает в себя сразу несколько полезных частей информации в возвращённой величине. Тем не менее, как и скалярное произведение, оно очень эффективно с математической точки зрения и может быть использовано для оптимизации кода, который иначе будет зависеть от медленных и сложных функций. Если векторы представляют собой силы, то более естественно будет думать о них с точки зрения их направления и величины (величина определяет мощность силы). Сложение двух векторов силы в результате даёт новый вектор, эквивалентный комбинации этих сил. Этот концепт зачастую очень полезен при применении сил с различными раздельными компонентами, которые работают одновременно (например, на летящую вперёд ракету может влиять встречный или боковой ветер).
Vector3
This structure is used throughout Unity to pass 3D positions and directions around. It also contains functions for doing common vector operations.
Besides the functions listed below, other classes can be used to manipulate vectors and points as well. For example the Quaternion and the Matrix4x4 classes are useful for rotating or transforming vectors and points.
Static Variables
| back | Сокращенное написание Vector3(0, 0, -1). |
| down | Сокращенное написание Vector3(0, -1, 0). |
| forward | Сокращенное написание Vector3(0, 0, 1). |
| left | Сокращенное написание Vector3(-1, 0, 0). |
| negativeInfinity | Shorthand for writing Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity). |
| one | Сокращенное написание Vector3(1, 1, 1). |
| positiveInfinity | Shorthand for writing Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity). |
| right | Сокращенное написание Vector3(1, 0, 0). |
| up | Сокращение для написания Vecror3(0,1,0) |
| zero | Сокращение для написания Vector3(0,0,0) |
Variables
| magnitude | Returns the length of this vector (Read Only). |
| normalized | Returns this vector with a magnitude of 1 (Read Only). |
| sqrMagnitude | Возвращает квадрат длины этого vector’a (Read Only) |
| this[int] | Доступ к x,y,z компонентам используются [0],[1],[2] соответственно |
| x | X компонент vector’a |
| y | Y компонент вектора. |
| z | Z компонент vector’a |
Constructors
| Vector3 | Создайте новый vector с заданными x,y,z компанентами |
Public Functions
| Equals | Returns true if the given vector is exactly equal to this vector. |
| Set | Set x, y and z components of an existing Vector3. |
| ToString | Возвращает отформатированной строки для этого vector’a |
Static Functions
| Angle | Returns the angle in degrees between from and to. |
| ClampMagnitude | Returns a copy of vector with its magnitude clamped to maxLength. |
| Cross | Векторное произведение двух векторов. |
| Distance | Возвращает расстояние между a и b. |
| Dot | Dot Product of two vectors. |
| Lerp | Linearly interpolates between two points. |
| LerpUnclamped | Linearly interpolates between two vectors. |
| Max | Возвращает vector, который сделан из компонентов двух vector’oв |
| Min | Возвращает vector, который сделан из мелких компонентов двух vector’oв |
| MoveTowards | Calculate a position between the points specified by current and target, moving no farther than the distance specified by maxDistanceDelta. |
| Normalize | Makes this vector have a magnitude of 1. |
| OrthoNormalize | Makes vectors normalized and orthogonal to each other. |
| Project | Projects a vector onto another vector. |
| ProjectOnPlane | Projects a vector onto a plane defined by a normal orthogonal to the plane. |
| Reflect | Reflects a vector off the plane defined by a normal. |
| RotateTowards | Поворот vector’a от current к /target/ |
| Scale | Покомпонентное умножение двух vector’oв |
| SignedAngle | Returns the signed angle in degrees between from and to. |
| Slerp | Сферически интерполяцию между двумя векторами |
| SlerpUnclamped | Сферически интерполяцию между двумя векторами |
| SmoothDamp | Gradually changes a vector towards a desired goal over time. |
Operators
| operator — | Вычитает один vector из другого |
| operator != | Возвращает истину, если vector отличается |
| operator * | Умножает vector на число |
| operator / | Делит vector на число |
| operator + | Добавляет два вектора. |
| operator == | Returns true if two vectors are approximately equal. |