テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

UnityのベクトルとQuaternionによる回転について

Quaternionは回転情報です。transform.rotationに格納されています。

 

このQuaternion(回転)ですが、Vector3(ベクトル)と合わせると、Vector3を回転させる事ができます。

 

Quaternionでベクトルを回す

 

例えば、Unityで「向いている方向のベクトル」を得るには、transform.forward等を使用します。2Dの場合はtransform.up等でしょう。

 

実はこのtransform.upの値は、以下のコードと一致します。

var dir = transform.rotation * Vector3.up;

つまり「Vector3.up(上方向)を基準にtransformの持つQuaternion(回転情報)にを掛けて回転させる」と、tranfsorm.upと一致するという事です。

  

この「ベクトルにQuaternionをかけるとベクトルが回る」…というのは面白く、例えば「-30度位の弾」を出したい場合、プレイヤーのベクトルに-30度のQuaternionをかけると斜め-30度のベクトルが求められるので、後はひたすら求めたベクトルを加算していけば弾は斜めに飛んでいきます。

f:id:tsubaki_t1:20140802022347j:plain

 

Quaternionの加算

 

Quaternionですが、足したり出来ます。例えば以下のようなコードがあった場合、最終的には合計の角度となります。

 

transform.rotation = targets[0].rotation * targets[1].rotation;

 

f:id:tsubaki_t1:20140802114102j:plain

ベクトルに複数Quaternion合計した結果を得たい場合、Vector3に合計したQuaternionを足しても良いですし、Vector3を何度もQuaternionで回しても良いです。

 

Quaternionを求める

 

Quaternionの回転を作るには、Quaternion.AngleAxisを使います。これの基本は「軸を決めて回す」です。そもそもQuaternionは「xyzで軸を決めてWで捻る」物だそうで。

Quaternion.AngleAxis( -30, -Vector3.forward );

イメージ的には、「リンゴに軸方向から串をぶっさして捻る」をイメージしてもらうと分かりやすいかもしれません。串を縦(Y軸方向)にぶっ刺したらコマのように回せるのです。同様にZ軸を指定すると、2Dがクルクルと回ります。

 

ちなみにQuaternionに使う軸情報の値は正規化(xyzの合計値が1になる)されるらしく、軸となる値を大きくしても回転角度に変化はありません。大きな値を入れるのは微妙な斜めを表現する為に使う程度の認識で良さそうです。

 f:id:tsubaki_t1:20140802024735g:plain

 

後もう一つ、ベクトルの相対値角度からQuaternionを求める方法があります。3Dゲームではコッチのほうが使うかもしれません。

2つのベクトル(ベクトルAからベクトルBへ回転させる為のQuaternion)を得るには、Quaternion.FromToRotationを使用します。下のコードは、targets[0]とtargets[1]の差を自身の回転にします。同じ値だと上を向き、違う値だとその分傾きます。

transform.rotation = Quaternion.FromToRotation(targets[0].transform.uptargets[1].transform.up );

 

これを応用すると、2DのLookAtが可能です。targetに対象の情報を格納してある条件で、こんな感じ。

var diff = (target.position - transform.position ).normalized;

transform.rotation = Quaternion.FromToRotationVector3.up,  diff);

 

f:id:tsubaki_t1:20140802030453g:plain

 

最後に、2つの角度の中間点を求めたい場合はQuaternion.Lerpを使用します。これはモーション等を補完したり、対象をゆっくり向くのに使えます。

 Quaternion.Lerp(targetA.rotationtargetB.rotation, 0.5f);

最後の0.5は合成率みたいなものです。ここが1だと100%合成、0だと0%合成となり、0.5だと50%(中間地点)となります。

f:id:tsubaki_t1:20140802113331g:plain

 

サンプル

 

Quaternionのサンプル試作

 

その他

 

ちなみにInspectorの奴は多分オイラー角ぽい何か(x,y,zの値で回す手法)。Unityの回転がややこしいのは大体この設計のせいな気がします。