Quaternion

Quaternion.identity

回転していない空の Quaternion を生成する。

Quaternion rotation = Quaternion.identity;

Quaternion.Euler(xの角度, yの角度, zの角度)

ランダムな角度の Quaternion を「オイラー角」から生成します。 Quaternion.Euler(Vector3) でも同様です。

Quaternion rotation = Quaternion.Euler(10, 0, 0);

quaternion.eulerAngles

回転の「オイラー角」を取得する。

Vector3 euler = quaternion.eulerAngles;

Quaternion.Slerp (現在の角度, 目的の角度, どれくらい近づくか)

目的の角度に到達させるのに必要な途中の角度を補間します。 3つめの引数を調整することで、どれくらいの速さで到達するかを制御できます。

void FixedUpdate ()
{
  // 目的の角度に到達させるのに必要な、このフレームでの角度を取得する
  Quaternion target_rot = Quaternion.Slerp (transform.rotation, target.transform.rotation, 0.1f);
  transform.rotation = target_rot;
}

Quaternion.Inverse (現在の角度)

“逆クォータニオンを取得する”と言われると想像しにくいですが、たとえば 目的の角度 * Quaternion.Inverse(現在の角度) とすることで、目的の角度まで AddTorque するのに必要な角度を求められます。

見た目は Slerp と大きく変わらないかもしれませんが、Rigidbody の物理で動いているため、Angular Drag の値で挙動を変えたり、既に動いている要素に加算して力を加えたりできます。

// 目的の角度にあとどれくらい足りないか、差分を調べる
Quaternion target_rot = target.transform.rotation * Quaternion.Inverse (transform.rotation);

// マイナス値の場合には値を補正(より近い方から回転する)
if (target_rot.w < 0f) {
  target_rot = Quaternion.Inverse (target_rot);
}

// 足りない角度分を Torque で回転を加える
rb.AddTorque (new Vector3(target_rot.x, target_rot.y, target_rot.z)*40f);

Quaternion.LookRotation(向きたい座標)

相手の方向を向く時には Quaternion.LookRotation(向きたいオブジェクトの座標 - 自分の座標) とします。

void FixedUpdate ()
{
  // 相手のいる角度を求める
  Quaternion target_rot = Quaternion.LookRotation(target.transform.position - transform.position);

  // 回転する
  transform.rotation = target_rot;
}

また、相手とは反対側を向きたい場合には、さらに 180 度回転した角度を掛けて、Quaternion.LookRotation(向きたいオブジェクトの座標 - 自分の座標) * Quaternion.Euler(new Vector3(0, 180f, 0)) とします。

void FixedUpdate ()
{
  // 相手とは反対側の角度を求める
  Quaternion target_rot = Quaternion.LookRotation(target.transform.position - transform.position) * Quaternion.Euler(new Vector3(0, 180f, 0));

  // 回転する
  transform.rotation = target_rot;
}

あるいは、進行方向にキャラクターを向かせたい場合は、前のフレームの座標を保持しておき、古い座標と新しい座標を比較して目的の方向に向きを変更できます。

Vector3 prev;
void Update(){
  Vector3 diff = transform.position - prev;
  if (diff.magnitude > 0.01) {
    transform.rotation = Quaternion.LookRotation(diff);
  }
  prev = transform.position;
}

Quaternion.Angle(クォータニオンA, クォータニオンB)

2つの回転の間の角度を float で取得できます。

Quaternion diff_rot = Quaternion.Angle(transform.rotation, target.transform.rotation);

Quaternion.FromToRotation(座標A, 座標B)

座標 A と B の回転の差分を取得できます。

transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);