Не понимаю TransformDirection в Unity
Допустим у нас есть куб в нулевых координатах сцены. Я изменяю его позицию, чтобы он сдвинулся вперед на 10 единиц:
transform.position = new Vector3(x, y, 10);
Когда я поверну куб на 45 градусов и снова сдвину его на 10 единиц по оси z, он точно так же сдвинется относительно координат сцены, то есть глобальных координат, он не сдвинется в направлении своей z. Однако же, использование TransformDirection означает преобразование значений вектора из локальных в глобальные:
Vector3 direction = new Vector3(x, y, z);
Vector3 worldDirection = transform.TransformDirection(direction);
transform.position += worldDirection;
И теперь, если я поверну куб на 45 градусов, то сдвинется он уже относительно своей оси z, так в чем же логика? Получается ведь наоборот, если я не использую TransfromDirection, то объект сам по-себе по дефолту движется по глобальной оси z, а использование TransfromDirection наоборот заставляет объект двигаться по своим собственным координатам. Прошу развеять мой конфуз, потому что в интернете не нагуглил вменяемого объяснения этого метода.
Ответы (1 шт):
Изменение координаты, это НЕ ДВИЖЕНИЕ, а телепортация! При перемещении таким образом, не задействована физика и объект может проходить сквозь стены, хотя тело стены будет при симуляции пытаться выталкивать из себя тело передвигаемого объекта, но пройдёт ли зависимости от скорости, толщины тела стены и частоты кадров, что является не стабильным и не надёжным. При загрузке баннера, происходит лаг и персонаж вылетает за пределы карты, а пользователь удаляет игру.
На тему логики, почему прибавив к позиции 0, 0, 1
вектор 0, 0, 1
, должно получиться не 0, 0, 2
?? Какая разница, как там этот объект повернут и какой у него масштаб? position
не зависят от rotation
, а rotation
не зависят от scale
, изменяя их, другие значения не страдают.
Допустим у тебя есть корпус автомобиля и к нему прикреплено колесо, оно имеет некоторую координату 2, 1, 0
(переднее-правое) и было бы как то странно, если бы это колесо меняло свое местоположение при повороте. Ты почему то ожидаешь, что координаты изменятся относительно поворота колеса, причём не вокруг корпуса, а вокруг центра сцены ?.
Transform
это параметры осей, сдвиг начала координат localPosition
, поворот осей localRotation
и масштаб localScale
, в инспекторе мы видим именно их. Оси сцены являются корневыми родительскими для всех осей и называются глобальными. Значения осей объекта пересчитанные по иерархии, в глобальных осях это position
, rotation
и lossyScale
.
У трансформа есть две группы методов, для конвертации координат между двумя системами осей, вектора и позиции.
Методы для получения локального вектора в значениях глобальных осей и на оборот, с учётом или без учёта масштаба (Transform.TransformVector и Transform.TransformDirection).
Написав один из этих вариантов:
transform.position += transform.TransformDirection(Vector3.forward) * distance;
transform.position += transform.forward * distance;
transform.Translate(transform.forward * distance, Space.World);
transform.Translate(Vector3.forward * distance);
Vector3.forward == new Vector3(0, 0, 1)
, у векторов есть статические свойства содержащие базовые направления и нулевое значение для удобства, а у transform
свойства с методом TransformDirection
для положительных направлений, поскольку часто используются.
В итоге это один и тот-же код с одним и тем-же результатом, перемещением объекта по направлению его локальной оси z
.
Полёт от первого лица, относительно осей камеры, как это происходит в редакторе, выглядит так:
private void Update ()
{
Vector3 input = GetInputAxis();
float deltaSpeed = speed * Time.deltaTime;
Vector3 vx = transform.right * input.x;
Vector3 vy = transform.up * input.y;
Vector3 vz = transform.forward * input.z;
transform.position += (vx + vy + vz) * deltaSpeed;
// или
transform.Translate(input * deltaSpeed);
// так же, кроме своих, локальных Space.Self или мировых Space.World осей,
// можно указывать конкретно, относительно пространства какого объекта
transform.Translate(input * deltaSpeed, Camera.main.transform);
}
private Vector3 GetInputAxis ()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
float y = 0;
if (Input.GetKeyDown("e")
y++;
if (Input.GetKeyDown("q")
y--;
return new Vector3(x, y, z);
}
Метод для получения локальнонй позиции в значениях глобальных осей, когда учитывается всё, и позиция и поворот и масштаб (Transform.TransformPoint).