Quaternion

Quaternion.identity

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

1
Quaternion rotation = Quaternion.identity;

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

ランダムな角度のQuaternionを オイラー角 から生成する。 Quaternion.Euler(Vector3) でも大丈夫

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

quaternion.eulerAngles

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

1
Vector3 euler = quaternion.eulerAngles;

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

目的の角度に到達させるのに必要な、途中の角度を取得できます。 3つめの引数を調整する事でどれくらいの速さで到達するかを調整する事が可能です。

1
2
3
4
5
6
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 の値を触れる事で動き方を変更したり、すでに動いている要素に加算して力を加えたりする事ができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 目的の角度にあとどれくらい足りないか、差分を調べる
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(向きたいオブジェクトの座標 - 自分の座標)とすれば求められる。

1
2
3
4
5
6
7
8
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))とする事で求める事ができる。

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

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

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

1
2
3
4
5
6
7
8
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 で受け取る事ができます。

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

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

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

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