4連休にした
月曜日に有休を取得して4連休となったは良いものの、時間を持て余してサッカーゲームFIFA20でプレミアリーグを1シーズン過ごした皆さんこんにちは。「休みは休むためにあるんだから別に良い」と心の中で言い訳してたら最終日の夕方になってた。
公転
それほど頻繁ではないのですが、ゲームを制作しているとオブジェクトを「別のオブジェクトを中心にして」周るような移動をさせたいケースが出てきます。公転運動ってやつですね。
Unityでは標準でTransformに公転移動のメソッドが用意されています。
RotateAround(Vector3 中心座標, Vector3 回転軸, float 回転角度)
中心座標にはWorld座標を指定します。
回転軸はVector3で指定しますが、Y軸周りに回すならVector3.up、Z軸周りに回すならVector3.forwardを指定すれば良いです。
回転角度にはdegreeの値で指定します。
これをUpdate関数内で実行すれば指定した回転軸周りを回り続けてくれます。
こんな感じ、上の動画ではRotateAroundの公転と同時にtransform.LookAtを使用してカーソルの向きが中心のオブジェクトを向くようにしています。
// 公転原点オブジェクトのWorld座標取得 Vector3 orbitOrigin = OriginObj.transform.position; // 公転 transform.RotateAround(orbitOrigin, Vector3.up, Angle*Time.deltatime); // 公転原点オブジェクトの方を向く transform.LookAt(OriginObj.transform);
このようにオブジェクトを公転させるだけなら簡単に実装できますが、公転しているオブジェクトをカメラで追従させる場合はちょっと工夫が必要です。
カメラで追従する
通常、アクションゲームやTPSなどではPlayerの後方(上方)にカメラが設置されていて、Playerの移動に合わせてカメラも移動していきます。
この追従処理の簡単な実装方法として、最初にカメラの座標と目標となるオブジェクトの座標の差分(ベクトルの差分)を求めて、
目標オブジェクトが移動するたびに、目標オブジェクトの座標にベクトルの差分を加えてカメラの座標を求める方法があります。
しかしこの方法はあくまで目標オブジェクトが平面上を平行移動する場合のみで、今回のように目標オブジェクトが公転するような場合ではカメラの座標を求めることができません。
何故なら、最初に求めたベクトルの差分はWorld空間での座標系(World座標)でのベクトル差分ですが、公転するオブジェクトを中心に考えた場合、カメラがあるべき位置は公転原点を原点としたLocal空間での座標系(Local座標)での後方(上方)となるので、ベクトルの和算をする前に「ベクトルの差分」の座標を変換する必要があるからです。
90度ぐらい公転した後のカメラ位置、目標オブジェクトのほぼ真横にある。
座標の変換
このWorld空間、Local空間での座標の変換(ベクトルの変換)についてもUnityの標準でTransformVectorというメソッドが用意されています。
今回の場合は目標オブジェクトのLocal空間でのベクトル差分をWorld空間のベクトルに変換します。
Transform Target;
// ベクトル差分をWorld空間のベクトルに変換 Vector3 distance = Target.TransformVector(deltaVector);
これを目標オブジェクトの座標に加えたものがカメラの座標となります。
CameraObj.transform.position = Target.position + Target.TransformVector(deltaVector);
後は絶えずカメラが公転原点の方を向くように回転させておけば公転運動するオブジェクトを追従するカメラの動作処理が実装できます。
目標のオブジェクトの公転運動に合わせて、また、前後に移動してもそれに合わせてカメラが追従できていることが分かります。
ちなみに公転運動は原点となるオブジェクトが移動してもそれに合わせて公転することができます。
RotateAroundで簡単に公転運動が実装できることは分かりましたが、DOTweenには用意されてないんだよなぁ・・・。