Rigidbody.MoveRotation: умножение кватернионов вызывает постоянное вращение - PullRequest
1 голос
/ 09 июня 2019
Quaternion q1 = Quaternion.LookRotation(Vector3.Cross(transform.right, normal), normal);
Quaternion q2 = Quaternion.LookRotation(target.position - transform.position, normal);

Я пытаюсь повернуть объект в трехмерной сцене, используя два кватерниона вместе, чтобы объект оставался перпендикулярно местности под ним (q1), а передняя часть объекта обращена к целевому преобразованию (q2);

В FixedUpdate при использовании Rigidbody.MoveRotation(q1) или Rigidbody.MoveRotation(q2) объект поворачивается на требуемое вращение и продолжает указывать в этом направлении.Если я использую Rigidbody.MoveRotation(q1 * q2), он вращается вокруг своей оси.

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

Нужно ли кэшировать какую-то дельту вращения или что-то, чтобы отследить, как далеко она повернулась с момента последнего кадра и отрегулировать?1015 *.

1 Ответ

0 голосов
/ 10 июня 2019

Каждый кватернион, создаваемый LookRotation, таков, что вращается от единичного вращения до вращения, указанного параметрами. Применение второго поворота из неидентичного поворота (что и делает q1 * q2) может привести к тому, что он не будет соответствовать одному или обоим из LookRotation параметров, с которыми q2 был создан.

Используйте Vector3.OrthoNormalize, чтобы найти вектор, ортогональный normal, ближайший к target.position - transform.position. Вам придется справиться с ситуацией, когда нормальное и это направление параллельны.

Затем используйте Quaternion.LookRotation, чтобы получить вращение, которое укажет forward и up преобразования в следующих направлениях:

Vector lookDirection = target.position - transform.position;
if (Mathf.Approximately(1f, Vector3.Dot(normal, lookDirection)))
{
    // normal and lookDirection are parallel
    // Do something reasonable about look direction here.
    // That may mean doing nothing at all!
    return;
}


Vector3.OrthoNormalize(ref normal, ref lookDirection);
Quaternion newRotation = Quaternion.LookRotation(lookDirection, normal);

Rigidbody.MoveRotation(newRotation);

Альтернативой является использование LookRotation, чтобы смотреть в направлении normal и располагаться как можно ближе к направлению от цели, вначале, насколько это возможно, затем наклон вниз на 90 градусов:

Vector lookDirection = target.position - transform.position;
if (Mathf.Approximately(1f, Vector3.Dot(normal, lookDirection)))
{
    // normal and lookDirection are parallel
    // Do something reasonable about look direction here.
    // That may mean doing nothing at all!
    return;
}

Quaternion bottomTowardsTarget = Quaternion.LookRotation(normal, -lookDirection);
Quaternion newRotation = bottomTowardsTarget * Quaternion.Euler(-90f,0,0);

Rigidbody.MoveRotation(newRotation);
...