Unityの角度計算メソッドをわかりやすくするサンプルの作成

今回はUnityの方向から角度を求めるメソッド群、角度から別の角度を求めるメソッド群をサンプルを使って視覚的にわかりやすくしたいと思います。

今回使用する角度計算のメソッドは

  • Vector3.Angle
  • Vector3.SignedAngle
  • Quaternion.Angle
  • Quaternion.AngleAxis
  • Quaternion.FromToRotation
  • Quaternion.LookRotation
  • Vector3.Dot
  • Vector3.Cross
  • です。

    今回作成するサンプルを作成すると、

    上のような感じでシーンビューでゲームオブジェクトを動かすとそれに応じてすぐに結果を見ることが出来るので、メソッドの計算結果がどのようになるかを視覚的に確認出来ます。

    スポンサーリンク

    シーンビューで角度を確認出来るサンプルの作成

    シーンビューでゲームオブジェクトを動かして角度をどのように計算しているかがわかるサンプルを作成します。

    ヒエラルキー上で右クリック→Create Emptyを選択し、名前をCalculateAngleにします。

    ヒエラルキー上で右クリック→3D Object→Planeを選択します。

    ヒエラルキー上で右クリック→3D Object→Cubeを選択します。

    Cubeを選択しインスペクタのTransformのScaleのXYZを全て0.3にします。

    Cubeを選択した状態でCtrl+Dキーを押して二つのCubeを複製し、名前をBaseObj、FromObj、ToObjとします。

    BaseObjが元となる位置にするゲームオブジェクトで、FromObjが最初の方向を計算する位置、ToObjが次の方向を計算する位置です。

    ゲームオブジェクトをシーンビュー上でわかりやすくアイコン表示したい場合はインスペクタの名前の横のアイコンを押して変更します。

    シーンビュー上のゲームオブジェクトをアイコン表示する

    作成したゲームオブジェクトは下のようになりました。

    角度計算用のサンプルオブジェクト達

    CalculateAngleゲームオブジェクトに新しくCalculateAngleスクリプトを作成し取り付けます。

    全てのメソッドの計算で使うが下のようなスクリプトになり、OnDrawGizmosメソッド内を変更して確認出来ます。

    CalculateAngleゲームオブジェクトのインスペクタでGUIStyleでテキストのフォントサイズ等も変更出来ます。

    シーンビュー上でBaseObj、FromObj、ToObjを動かすとそれに応じて結果を確認出来ます(Unityのプレイボタンを押す必要はありません)。

    CalculateAngleのインスペクタにBaseObj、FromObj、ToObj、Planeを設定しておきます。

    インスペクタのAngleModeを変更することでメソッドを変更してサンプルを試すことが出来ます。

    スクリプトの詳細は個々のメソッド毎に説明していきます。

    Vector3.Angle

    Vector3.Angleを見ていきます。

    Vector3.Angleはfromとtoの間の角度を計算します。

    得られる結果は0~180度の間のfloat値が得られます。

    BaseObjからFromObjの方向とBaseObjからToObjの方向を求めその間の角度を計算しています。

    ラベルに渡す時にstring型にする必要がある為ToString()メソッドで変換しています。

    Handles.Labelでは第1引数でラベルを表示する位置、第2引数で表示するテキスト、第3引数でテキストのスタイルを指定しています。

    Vector3.Angleの計算結果

    Vector3.SignedAngle

    Vector3.SignedAngleを見ていきます。

    Vector3.SignedAngleはaxisを軸にしたfromとtoの角度を計算します。

    得られる結果は-180~180度の間のfloat値が得られます。

    axisをVector3.upにした場合はY軸を軸とした回転なのでわかりやすいですが、軸を変えるとすごくわかりにくくなりますね。

    角度計算部分以外はVector3.Angleと同じなので問題ないと思います。

    Vector3.SignedAngleを使った計算結果

    Quaternion.Angle

    Quaternion.Angleを見ていきます。

    Quaternion.Angleはaの角度とbの角度の間の角度を計算します。

    得られる結果は0~180度のfloat値です。

    別の点CがあるとしてCからAに線を引き、CからBに線を引いたとしてそのCAとCBの線の間の角度が得られるようです。

    スクリプトを流用する為にfromObjとtoObjという名前でそのまま使ってます。

    Handles.DrawLineでfromObj、toObjの位置から前方5mの線を引きます。

    fromObjとtoObjの角度を変更するとその間の角度が計算されます。

    わかりやすくする為にFromObjとToObjの位置を同じにし、BaseObjゲームオブジェクトの左側には計算できた角度で扇形を作っています。

    Quaternion.Angleでの計算結果

    Quatenrion.AngleAxis

    Quaternion.AngleAxisを見ていきます。

    Quaternion.AngleAxisはaxisを軸にangle度回転させたQuaternionを計算します。

    上のスクリプトではVector3.right(ワールドのX軸)を軸にしてFromObjのTransformのRotationのYの角度分回転させたQuaternionを取得し、BaseObjの角度に設定しています。

    FromObjのTransformのRotationのYを60にした場合はBaseObjのTransformのRotationのXが60になります。

    Quaternion.AngleAxisの実行結果

    Quaternion.FromToRotation

    Quaternion.FromToRotationを見ていきます。

    Quaternion.FromToRotationに関しては

    UnityのQuaternion.FromToRotationで2つの方向から角度を求める事が出来ますが、その時の方向にPhysics.Raycastで得られたRaycastHit.normalの値を使う事が多々あります。このRaycastHit.normalとはなんなのか?を調べました。

    も参照してください。

    Quaternion.FromToRotationはfromDirectionの方向からtoDirectionの方向のQuaternionを計算します。

    「BaseObjから見たFromObjの方向」から「BaseObjから見たToObjの方向」の角度を求められます。

    BaseObjの位置のXYZを0、FromObjの位置をX:0、Y:0、Z:5、ToObjの位置をX:5、Y:-5、Z:0とした場合は以下のようになります。

    Quaternion.FromToRotationの実行結果

    Quaternion.LookRotation

    Quatenrion.LookRotationを見ていきます。

    Quaternion.LookRotationはupwardsを上向き方向にしてforward方向に回転したQuaternionを計算します。

    Quaternion.LookRotationの第2引数は省略出来ますが省略するとVector3.upがデフォルト値になります。

    上のスクリプトでは上向きをplaneのローカルの上方向を指定しているのでPlaneゲームオブジェクトの角度を変えると計算結果が変わります。

    試しにPlaneのTransformのRotationのY軸の角度を315とすると、

    Quaternion.LookRotationの実行結果

    上のようにFromObjの方向を向きつつBaseObjの上向きがPlaneの上向きと同じになります。

    地べたを歩くゾンビ等で上向きを歩く床の向きと合わせたい時に便利です。

    Unityのアクションゲームでゾンビに足を捕まれ、そこから脱出する機能の作成と敵であるゾンビを地面に合わせて傾きを変更して移動させる機能を作成します

    Vector3.Dot

    Vector3.Dotを見ていきます。

    Vector3.Dotはlhsのベクトルとrhsのベクトルの内積を計算します。

    lhsとrhsベクトルが正規化されていた場合(長さ1の単位ベクトル)に得られる値は-1~1の値です。

    2つのベクトルの内積を求めるとlhsベクトルの前方に対するrhsベクトルの位置を把握する事が出来ます。

    得られた内積が1の場合は完全に同じ方向を向いていて、0の場合は垂直、-1の場合は完全に反対方向を向いています。

    今回はBaseObjからFromObjのベクトルとBaseObjからToObjへのベクトルの内積を計算しています。

    ToObjをFromObjの前方から後ろの方に移動させると以下のようになります。

    Vector3.Dotの実行結果

    Vector3.Dotを使うと例えば敵キャラクターの前方にいる主人公キャラクターだけを追いかけさせるような機能を作る時に、敵の前方と敵から見た主人公の方向の内積を求めて主人公が敵の視覚内にいるかどうかを知らべる事が出来ます。

    得られた内積が0より上の時は敵の横から前方、0より下の時は敵の横から後方という事になります。

    Vector3.Cross

    Vector3.Crossを見ていきます。

    Vector3.Crossはlhsベクトルとrhsベクトルの外積を計算出来ます。

    2つのベクトルの外積を計算すると2つのベクトルと垂直なベクトル(Vector3)が得られます。

    上のスクリプトではBaseObjからFromObjの単位ベクトルとBaseObjからToObjの単位ベクトルの外積を求めBaseObjからそのベクトルへ線を引いています。

    Vector3.Crossを使った実行結果

    終わりに

    方向と角度を使ったメソッドは種類が結構ある割にどれも似たような感じで使い分けが難しいですね。

    実際にサンプルを使って操作をすると少しわかってくるかと思いましたが、回転軸を変更したり、きっちり90度単位で角度を変更しないとなかなか分かり辛いですね。(´Д`)

    サンプルをグリグリ動かして試してみてください。

    参考サイト

    UnityスクリプトリファレンスーVector3.Angleー

    UnityスクリプトリファレンスーVector3.SignedAngleー

    UnityスクリプトリファレンスーQuaternion.Angleー

    UnityスクリプトリファレンスーQuaternion.AngleAxisー

    UnityスクリプトリファレンスーQuaternion.FromToRotationー

    UnityスクリプトリファレンスーQuaternion.LookRotationー

    UnityスクリプトリファレンスーVector3.Dotー

    UnityスクリプトリファレンスーVector3.Crossー

    スポンサーリンク

    記事をシェアして頂ける方はこちら

    フォローして頂くとやる気が出ます