ここ2ヶ月ほど、Unityで本格的な3DアクションゲームやFPSを作るための下準備として「敵の自動移動処理」をコツコツ作ってきました。
この自動移動処理を実現するにあたってはUnityの「NavMeshAgent」という機能を使っているのですが、困ったことにこのNavMeshAgentは標準では「ジャンプ」をしてくれません。そこで自前でジャンプ処理を作りました。
今回はそのジャンプ処理を作るにあたって工夫した点や、処理の流れについて書いていきます。
ちなみに完成イメージは次の動画の通りです。
※この記事で使用しているUnityのバージョン:2019.1
NavMeshAgentとは?
まず、NavMeshAgentとは「Unityでキャラクターを自動的に移動させるための機能」です。キャラクターの自動移動処理は経路探索などの難しい処理を行う必要があり、初心者が自前で実装するのは困難ですが、このNavMeshAgentを使えば比較的簡単に自動移動を実現することができます。
NavMeshAgentの使い方などについては姉妹サイトのページ「ナビメッシュエージェント(NavMeshAgent)の使い方」をご覧ください。ここでは基本的な使い方が分かっているものとして説明していきます。
NavMeshAgentの問題点
さて、このNavMeshAgentは自動移動処理を簡単に扱えるという点では便利ですが、この記事の執筆時点では実用的な問題もあるのが事実です。
とりわけ重大なのがジャンプが実装されていないということでしょう。NavMeshAgentは穴などを通過することはできますが、その際は下の動画のように滑るように移動してしまいます。
まあ空中浮遊しているキャラクターならこれでも気にならないと思います。しかし、地上を歩く大部分のキャラクターの場合はいくらなんでも不自然すぎます。そこで仕方なく自前でジャンプ処理を作ることになったというわけです。
Rigidbodyでジャンプさせる!
ではどうやってジャンプさせるのか?ということですが、結論を書いてしまうと
オフメッシュリンクに乗ったときだけNavMeshAgentを停止させて、Rigidbodyでジャンプさせる
という方法を採用することにしました(※オフメッシュリンクは上の動画の黒丸と矢印の部分です)。
ジャンプ処理の流れ
今回作ったジャンプ処理の手順は次の通りです。
- オフメッシュリンクに乗ったことを検知(NavMeshAgent.isOnOffMeshLinkで取得可能)
- ジャンプフラグON
- ジャンプ角度の計算
…「【Unity】Rigidbodyを使い、放物線を描き、目標の地点へ – うら干物書き」が参考になります。 - エージェント停止(NavMeshAgent.isStopped)
- ジャンプ実行(Rigidbody.AddForce)
- 接地フラグがONになるまで待つ(WaitUntil)。ただし、一定時間が経過したら強制的に次に進む
- オフメッシュリンクの処理終了(NavMeshAgent.CompleteOffMeshLink)
- エージェントをRigidbodyの位置にワープ(NavMeshAgent.Warp)。Rigidbodyでジャンプしてもエージェントの位置はそのままなので、強制的に移動させる必要がある。
- エージェント再開
- ジャンプフラグOFF
工夫したところ・実装のポイント
- なぜかは不明ですが着地時の接地判定が上手くいかないことがあり、上記6番から先に進まないことがあったので、一定時間が経過したら強制的に次に進む処理も入れました。
- NavMeshAgent.isOnOffMeshLinkはオフメッシュリンクの円に乗った瞬間にtrueになるようです(円の真ん中からジャンプ処理が始まるのかと思いましたが違いました)。そこで、ジャンプの角度計算に使う始点にはオフメッシュリンクに乗った瞬間の座標を使います。
- ジャンプ中に敵同士がぶつかると落ちてしまうので、レイヤー設定で敵同士の当たり判定をなくしておくのが良いです。
NavMeshAgentは謎だらけ
以上、ごく簡単ではありますがNavMeshAgentをジャンプさせる方法について書きました。具体的なコードは長すぎて載せられないので参考になるかどうかは分かりませんが、何かしらヒントにでもなれば幸いです。
ところでジャンプ処理を作っていてわかったのはNavMeshAgentには謎が多いということです。挙動として謎な部分が多く、公式リファレンスを見ても説明がほとんどない部分も多かったのでとても苦労しました。
NavMeshAgentは便利な機能ではありますが、ジャンプはないし謎も多くて自前の処理を組みづらい、というのでは何だかなぁ…と思います。Unityさんにはその辺をもう少し何とかしていただきたいですね。