Вращение вокруг оси при движении вдоль нее

#unity3d #rotation #quaternions

#unity3d #вращение #кватернионы

Вопрос:

Следующие две строки в Update() гарантируют, что мое преобразование всегда будет обращено в прямом направлении (this.Направьте.вперед) на заданный угол поворота (this.Вращение, плавающее значение в диапазоне от 0 до 360) вокруг этой прямой оси.

 this.transform.rotation = Quaternion.AngleAxis(this.Rotation, this.Point.forward);
this.transform.rotation = Quaternion.LookRotation(this.Point.forward, this.transform.up);
  

Однако по каким-то причинам теперь я хочу сгладить / уменьшить вращение; поэтому вместо того, чтобы напрямую устанавливать ‘this.transform.rotation’, я добавляю свойство ‘targetRotation’ в класс и изменяю эти строки на;

 targetRotation = Quaternion.AngleAxis(this.Rotation, this.Point.forward);
targetRotation = Quaternion.LookRotation(this.Point.forward, this.transform.up);
  

И добавьте;

 this.transform.rotation = Quaternion.Slerp(

    this.transform.rotation,
    targetRotation,
    this.rotationSpeed * Time.deltaTime
);
  

(Очевидная) проблема с изменением заключается в том, что второе назначение targetRotation заменяет первое.

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

Я попытался их умножить, но это заставляет вращение вращаться все быстрее и быстрее, а не просто придерживаться значения this .Вращение.

Спасибо!

Ответ №1:

Сначала поверните глобал вверх на вращение вокруг this.Point.forward . Для этого можно использовать * оператор:

 Vector3 upDir = Quaternion.AngleAxis(this.Rotation, this.Point.forward) * Vector3.up;
  

Затем, повернув его вверх, продолжайте, как и раньше:

 targetRotation = Quaternion.LookRotation(this.Point.forward, upDir);

this.transform.rotation = Quaternion.Slerp(
    this.transform.rotation,
    targetRotation,
    this.rotationSpeed * Time.deltaTime
);
  

И, кстати, использование функций Lerp / Slerp с a t , значение которого никогда не гарантируется равным или превышающим 1, может привести к ошибкам из-за ошибок округления, если вам нужна гарантия, что результат в конечном итоге будет точно равен целевому.

Если эта гарантия не нужна, этот ответ здесь подойдет.

Если эта гарантия необходима, рассмотрите возможность использования чего-то другого (например, rotateTowards ) вместо Slerp .