Это второе из двух занятий по созданию скрипта «Look At» в Unity 2022, который позволяет одному объекту поворачиваться в сторону другого.


Видеоверсия этого руководства в настоящее время недоступна на этом языке.


Текстовая расшифровка видео

Всем привет!

Это второе из двух занятий по созданию скрипта «Look At» в Unity 2022, который позволяет одному объекту поворачиваться в сторону другого.

В первой части мы разобрали задачу и реализовали решение с мгновенным поворотом объекта. В этом же уроке мы создадим более медленный и плавный поворот, используя Quaternions и Slerp.

В этом занятии я предполагаю, что вы знакомы с такими понятиями, как Time.deltaTime и метод Quaternion.Slerp, поскольку я уже рассматривал их в других уроках. Если вы с ними не знакомы, рекомендую сначала изучить соответствующие материалы.

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

Затем мы свели задачу к двумерной плоскости и вычислили угол поворота, на который нужно повернуть 3D-модель Surveillance Camera.

В нашем скрипте этот угол называется deltaAngle и измеряется в градусах.

Чтобы использовать Slerp, нам нужны три вещи:

кватернион, задающий начальную ориентацию;

кватернион, задающий целевую ориентацию;

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

Первый пункт самый простой: свойство rotation у transform задаёт ориентацию объекта в виде кватерниона, поэтому для этого мы будем использовать transform.rotation.

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

Поворот, который необходимо выполнить в нашем скрипте, это deltaAngle, выраженный в градусах. Нам нужно представить его в виде Quaternion.

К счастью, функция Euler класса Quaternion подходит идеально: она принимает три параметра, то есть углы вращения вокруг осей X, Y и Z, и возвращает кватернион, представляющий это преобразование.

Как уже упоминалось, чтобы получить целевой кватернион, нужно умножить начальный на кватернион поворота, поэтому в Update я могу написать:

Quaternion targetRotation = (transform.rotation * (Quaternion.Euler(0f, 0f, deltaAngle)));

Сразу после этого я могу обновить ориентацию объекта, присвоив transform.rotation кватернион, вычисленный с помощью Quaternion.Slerp:

transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, evaluationTime);

Теперь нам нужно определить evaluationTime: значение типа float от 0 до 1, которое показывает, на каком этапе перехода от начальной ориентации к конечной мы находимся.

Сначала я объявляю и инициализирую эту переменную, написав:

private float evaluationTime;

в начале класса скрипта и

evaluationTime = 0f;

внутри метода Start.

Затем переменную evaluationTime нужно увеличивать на каждом кадре, что можно сделать так:

evaluationTime += Time.deltaTime;

сразу после инструкции с Slerp.

Разумеется, это лишь пример. Я советую умножать Time.deltaTime на переменную, значение которой можно изменять в реальном времени в Inspector, чтобы подобрать оптимальную скорость вращения. Эту тему я подробно рассматривал в уроке о Time.deltaTime.

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

Но когда его нужно сбрасывать?

Вопрос можно сформулировать так: когда мы готовы начать новый поворот модели?

Ответ таков: когда модель уже направлена на Player и ждёт, пока он начнёт движение.

Обычно можно было бы сказать, что когда модель Surveillance Camera направлена на Player, а Player остаётся неподвижным, то deltaAngle равен 0, поскольку поворот выполнять не нужно. Однако при работе с float, особенно при преобразованиях между различными единицами измерения, лучше оставить небольшой допуск. Поэтому будем считать, что анимация завершена и новая может начаться, как только Player начнёт движение, если абсолютное значение deltaAngle меньше 1f.

Итак, непосредственно перед созданием targetRotation, внутри метода Update, я пишу:

if(Mathf.Abs(deltaAngle) < 1f) evaluationTime = 0f;

Затем три последующие инструкции, то есть определение целевого кватерниона, изменение ориентации с помощью Slerp и увеличение evaluationTime, я помещаю в блок else этого условия.

Я сохраняю изменённый скрипт, возвращаюсь в редактор Unity и нажимаю Play, чтобы посмотреть результат. В этом случае скорость вращения определяется исключительно Time.deltaTime и может быть уменьшена или увеличена, как уже упоминалось, путём умножения Time.deltaTime на переменную, настраиваемую в реальном времени.

Итак, подведём итог. В этом уроке мы рассмотрели, как преобразовать угол поворота в Quaternion, чтобы вычислить кватернион целевой ориентации, а затем использовали Slerp для выполнения более медленных поворотов. Их скорость можно настраивать, сохраняя независимость от платформы выполнения, благодаря Time.deltaTime.

Мы также определили условие сброса для Slerp, чтобы поворот начинался заново, когда Player остаётся неподвижным и готов к новому движению.

На этом всё для этих двух уроков. До скорой встречи!

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


РАСШИРЕННАЯ ИНФОРМАЦИЯ О ПОЛИТИКЕ КОНФИДЕНЦИАЛЬНОСТИ И ИСПОЛЬЗОВАНИИ ФАЙЛОВ COOKIE