В этой статье мы поговорим о математических основах вращения объектов, Эйлеровых углах и проблематике их использования, а также о Кватернионах и причинах выбрать Кватернионы перед Эйлеровыми углами.
Математические основы вращения объектов
На базовом математическом уровне существует следующая формула:
(формула 1)
Эта пара значений описывает положение точки на окружности единичного радиуса с центром в начале координат, то есть .
В ранее приведенной формуле переменная представляет собой угол, который задается в радианах, где

На рисунке 1 можно видеть точку , положение которой было определено той же формулой при значении
, на единичной окружности с центром в начале координат.
Первая формула - это частный случай полной формулы, потому что такой вид применяется только для окружности единичного радиуса с центром в начале координат. Однако, если речь заходит о расчете координат объекта, который должен двигаться по круговой траектории не единичного радиуса, а также относительно другого объекта, то здесь всплывает необходимость использования полной формулы:
,
где - это точка привязки, вокруг которой и должен осуществляться поворот физического тела, а
- радиус окружности.
Стоит понимать, что реализация поворота объектов столь классическим способом - это не всегда правильное и оправданное решение, поскольку тригонометрические функции работают сравнительно медленно. Поэтому для поворота большого количества точек используются матрицы поворота.
Матрицы поворота
Матрица поворота - это базовый инструмент линейной алгебры, который позволяет нам описывать и применять вращение объектов в пространстве посредством умножения векторов на специальные матрицы.
Это сильно упрощенное определение матриц поворота, при желании можете взглянуть на описание этого же термина в википедии здесь
Для поворота объекта нам нужно умножить вектор на матрицу, где вектор будет описывать положение нашего объекта, а вид нашей матрицы определим из формулы.
Матрицы поворота разнятся в зависимости от мерности пространства. Если мы работаем с двумерным пространством, то имеем следующий вид матрицы:

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

А вот так выглядит пример перемножения вектора на матрицу все с того же источника:

Матрица поворота - это матрица в ее стандартном понимании, поэтому создавать свои матрицы поворота внутри c# кода в Unity проектах можно с использованием структуры Matrix4x4. В Unity принято работать преимущественно с матрицами четвертого порядка, поскольку движок рассчитывает все локальные и мировые преобразования как Matrix4x4. Пример создания матрицы для поворота вокруг оси :
Matrix4x4 rotationMatrix = new Matrix4x4();
//Первая строка матрицы
rotationMatrix.m00 = 1f;
rotationMatrix.m01 = 0f;
rotationMatrix.m02 = 0f;
rotationMatrix.m03 = 0f;
//Вторая строка матрицы
rotationMatrix.m10 = 0f;
rotationMatrix.m11 = Mathf.Cos(angle);
rotationMatrix.m12 = -Mathf.Sin(angle);
rotationMatrix.m13 = 0f;
//Третья строка матрицы
rotationMatrix.m20 = 0f;
rotationMatrix.m21 = Mathf.Sin(angle);
rotationMatrix.m22 = Mathf.Cos(angle);
rotationMatrix.m23 = 0f;
//Четвертая строка матрицы
rotationMatrix.m30 = 0f;
rotationMatrix.m31 = 0f;
rotationMatrix.m32 = 0f;
rotationMatrix.m33 = 1f;
Для большей наглядности и возможности сравнения напомню вид математического представления матрицы поворота в трехмерном пространстве вокруг оси :

Эйлеровы углы
Особенности и методы использования
В математическом контексте поворот таким способом реализуется с указанием последовательности из трех координат: ,
и
. В Unity для задания такой последовательности используется структура Vector3, принимающая те же координаты в виде параметров. Каждый из параметров соответствует конкретной оси, вокруг которой мы поворачиваем наш объект, то есть выражение new Vector3(90, 30, 0) будет говорить о наших намерениях повернуть объект на 90 градусов вокруг оси
и на 30 градусов вокруг оси
соответственно.
В действительности, то, что мы используем в игровых движках на сегодняшний день, это расширенная версия Эйлеровых углов. Сам Леонард Эйлер описывал вращение объекта по двум осям с использованием трех переменных. Часто такой метод поворота описывают визуализацией юлы

Расширенная же версия углов Эйлера, можно догадаться, описывает поворот вокруг трех осей с использованием трех переменных
В Unity существует свойство, которое принимает стиль параметров, свойственный для нашего способа поворота, то есть последовательность трех координат. Соединив эту информацию воедино, мы получаем примерный вид выражения:
transform.rotation.eulerAngles = new Vector3(90, 0, 0);
Всем вышесказанным мы разобрали первую особенность использования Эйлеровых углов: повороты задаются конкретной последовательностью трех чисел. Теперь поговорим о второй особенности.
Эйлеровы углы подразумевают, что поворот по каждой из осей осуществляется последовательно, а сам порядок может быть разным. При использовании порядка наш объект изначально повернется на нужное значение вокруг оси
, далее прибегнет к повороту относительно
оси и, наконец, повернется по последней оси
. В контексте углов Эйлера мы можем использовать как последовательность
, так любую другую последовательность.
Проблематика
Использование Эйлеровых углов несет в себе одну серьезную проблему, которой оказалось достаточно, чтобы считать этот подход несовершенным и проблематичным во многих ситуациях. Дело в существовании проблемы Gimbal Lock, которую еще могут называть блокировкой осей, шарнирным замком и складыванием рамок. Данная проблема связана с тем, что в контексте использования углов Эйлера присваивание поворота конкретному объекту по каждой оси должно протекать в определенном порядке, как об этом было сказано ранее. Если мы хотим изменить поворот какого-либо объекта сразу по трем осям, то присвоение нужного поворота не пройдет за одну операцию. Казалось бы, и в чем же тут проблема?
Дело в том, что при таком подходе могут возникать ситуации, когда две оси будут совпадать, отчего мы потеряем поворот по одной из осей. Например, при повороте объекта на 90 градусов вокруг оси , вращая далее объект по осям
и
мы заметим, что они идентично поворачивают объект, к чему и приводит вторая особенность Эйлеровых углов.
Цитируя: “Gimbal Lock возникает, когда две оси выравниваются, что приводит к потере независимой оси вращения”.
При желании можно более подробно и наглядно ознакомиться с проблемой в статье по ссылке здесь
Однако здесь есть один крайне важный ньюанс: так или иначе Unity все равно преобразует это выражение на лад использования кватернионов. Сделано это для того, чтобы как раз-таки избегать проблемы шарнирного замка. Иначе говоря, мы можем задавать повороты углами Эйлера, однако “под капотом” Unity преобразует все в кватернионы во избежание проблемы.
Кроме такой острой проблемы, как Gimbal Lock, использование такого способа поворота объекта влечет за собой еще одну немаловажную проблему: плохая интерполяция.
Не стоит делать выводы, что нужно избегать использования Эйлеровых углов, потому что со многими базовыми задачами они справляются удачно. Например, их можно использовать для задания вращения винту или колесам машины.
Кватернионы
Принято считать, что основное отличие Эйлеровых углов от кватернионов заключается в наличии четвертой координаты. То есть, если первое можно ассоциировать с ,
и
координатами, то второе связывают с
,
,
и, внимание,
координатой. Однако называть
“координатой” – это не совсем корректное действие. В подходе с кватернионами мы не работаем в четырехмерном пространстве, а работаем во всем том же трехмерном пространстве с тремя векторными координатами. Возникает вопрос, в чем тогда смысл существования загадочной величины
? Эту загадочную “координату” называют скалярной величиной.
Каждый кватернион задается первоначальным уравнением:
Где ,
,
– векторная часть уравнения, а
– скалярная. При использовании метода Quaternion.Euler() для указания угла поворота внутрь мы передаем объект типа Vector3, который путем дальнейших преобразований приходит в вид кватерниона:
Можно сказать, что кватернионы не поворачивают объект “сначала по этой оси, потом по этой”, а сразу поворачивают объект по всем нужным осям, считывая весь поворот математическим уравнением
Кватернионы - сравнительно сложная тема, поскольку для полного понимания принципа их работы требуется глубинное понимание многих математических аспектов. Наиболее подробно и доступно ознакомиться с кватернионами на таком уровне можно по ссылке здесь.