Unity 星の上を歩く~完成編~

ここしばらく放置しておいた星の上を歩くスクリプトですが、ようやく完成しました。

 

今度はスクリプトと重力圏をコライダーで作った星があれば動く簡単なものになりました。

 

いやー長かった。

 

・・・しかしながら出来上がってみるとやっぱり単純なんですよね。

 

今までの苦労は何だったのかと思わされてしまう・・・。

 

とりあえずイーサンを改造してカプセルの上を歩いてもらいました。

 

www.youtube.com

 

本当はソースコードとか載せてみたいんですが、載せるソフトの使い方が分からなかったので、概念的なお話だけです。

 

まず面の上をキャラクターに歩いてもらうためには・・・というお話はこちらのページがとても参考になりました。

 

その16 オブジェクトを任意の平面に立たせる姿勢制御

 

基本的にはほぼこれだけと言っていいです。

・・・まあ、結局それを実現するのに回り道を色々してしまったんですが。

 

まず、キャラクターを歩かせたい星の上に配置します。もちろん接触判定が必要なので、コライダーとリジッドボディをつけます。

 

ジッドボディの回転はFreezeRotationのXYZ全てにチェックが必要です。そうしないと物理エンジンで勝手に回転します。(ちなみにイーサンのスクリプトではこれをスクリプト側でロード時にフリーズさせているようです) 

 

それからリジッドボディのUseGravityのチェックは外します。重力の方向は星の上ではキャラクターの位置によって違いますからね。

 

星の上に配置したら、キャラクターが最初に必要な処理は自分の立っている面の確認です。

 

これはStandardAssetsのThirdPersonCharacterにあるCheckGroundStatus()関数を利用すれば足元の面の法線方向と自分が接地しているかが分かります。

 

これで得た面の法線方向にキャラクターのtransform.upの方向を向ければ面の上に立てます。

 

ただし、そのままtransform.upに法線ベクトルを入れるとその次の工程が面倒臭くなります。

 

私はここで引っかかって泥沼にはまりました・・・。

 

キャラクターの上方向を決めて面上に立たせた後に、進行方向を決めるという処理が必要なんですが、これを上方向を先に決定すると旋回できなくなりました。

 

どうもローカル座標を特定のベクトルの向きに合わせるというだけだと全ての軸において一定の方向に決まるようで、Quaternion.FromToRotation()やtransform.upに直接入力しただけだと毎フレーム進行方向もリセットされてしまい旋回できなくなりました。

 

・・・もちろんやり方が悪かっただけかもしれませんが。

 

何にしても、もっと簡単な方法があったので、そっちの方がいいと思います。

 

Quaternion.LookRotation()という関数が用意されているので、これを使います。

これはキャラクターに向かせたい方向のベクトルを入れることで、その向きのクオータニオンを作ってくれる関数です。

 

つまり、上方向じゃなくて進行方向を決めましょうということです。

 

ただ、もちろんそのままだと今度は面の上に立たなくなってしまいます。

 

でも大丈夫。LookRotationは上方向の引数も持っていて上方向も決められるんです。

 

・・・ただし、進行方向に直角であることが条件ですが。

これが上手く利用できずに一度使ったのに放り投げてしまったんですよ。・・・あの時気付いていれば・・・!!

 

進行方向の決め方ですが、旋回の計算も全部やってから使えばいいんでしょうけど、分かりにくいので、まずは球体の上前方に進んだ時の動きを1フレーム分動かしたことを考えてみましょう。

 

球体なので、球体の中心に向かって重力が働いているとすると、一歩前に進むとその分中心に向かって落ちます。

そしてこの時、立っている面の法線方向も変わります。

 

そうすると、進む前の前方となるベクトルと進んだ後の前方となるベクトルは球体の中心に向かって落ちた分だけ角度が変わります。

 

ちょうどX軸でキャラクターの前方向に回した感じでしょうか。

 

今回、LookRotationで前方に指定しするのはこの一歩踏み出した後のベクトルになります。

 

その求め方は、Unityなら簡単で、進む前の前方のベクトルを進んだ後の面に投影すれば求まります。

 

これにはVector3.ProjectOnPlane()を使います。

これで進行方向も決まったので、LookRotationに求めた進行方向と面の法線方向を渡せば星の上に立てます。

 

後はもう簡単で、毎フレーム法線方向と反対方向に力(これが重力に当たります)を加えて、進みたい方向に動かせばいいというわけです。

 

旋回はtransform.RotateでY軸のとこだけ入れてやれば旋回できますしね。

 

・・・といっても、実は移動とかは少し考えてやらないと動かしにくいです。キャラクター基準にするかカメラ基準にするかとか、操作性を考えると実はもう少し改良を加える必要があります。

 

とりあえず、長くなったので今日はここまで。

ジャンプとかも改良しないといけないし、まだまだやることが山積みです。

 

でも、星の上を歩くスクリプトはようやく落ち着いた感じですね。