テラシュールブログ

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

【Unity】Navmeshで障害物を避けて移動するルートを事前に取得する

今回は経路探索AI(Navmesh)のルートだけを取得してみます。

NavmeshAgentを使えば、とりあえずゴールへ至ることは出来ますが、色々と調整が出来ない所があったり、とりあえずルートを知りたいといったケースでは必要ありません。
なので、パスだけを取得してみます。

経路を取得するAPIとして、NavMesh.CalculatePathが使えます。
初期値点、目標地点のVector3(座標)を設定し、最後にPathのインスタンスを渡してやると、渡したPathインスタンスにルートが入っているという仕組みです。

マニュアルにも書いてある通り、即時実行する点には注意が必要です。
要するに、非同期で計算してくれないので場合によっては大きな負荷になります。

f:id:tsubaki_t1:20161129233122j:plain

 

gist.github.com

ちなみにmaxPositionでpositionsの配列のサイズを先に決めていますが、コレを行いGetCornersNonAllocを使用することで、Allocを削減する事が期待出来ます。
ただしpositionsの配列の長さしか値が格納されないので、場合によってはパスが途中で止まる事も有りえます。

安全性を期待するならpath.cornersで取得するのが良さそうです。

取得したパスで速やかにキャラクターを移動させる

次に、取得したパスを使用して、キャラクターをキビキビと動かしてみます。

f:id:tsubaki_t1:20161129233538g:plain

 

やっている事は簡単で、Vector3.MoveTowardsで目標の方向に指定の速度で動かし、到着したら目標の座標を更新しているだけです。

gist.github.com

OffmeshLinkに乗っている事を把握出来ない

なお、こういったCalculatePathで経路だけを取得して利用する場合、OffmeshLinkに乗っている事を判定するisOnOffMeshLinkが使えません。そのため、OffmeshLinkを通過する際のアクション(例えば崖を下りたり段差を飛び越える等)は、他の手法で認識する必要があります。コライダーとか。

f:id:tsubaki_t1:20161129234728j:plain

その他

逆を言えば、OffmeshLinkで妙に加速するのを回避する手っ取り早い方法が、今回の「自前でパス取得して動かす」という話もあります。

(別にわざわざ同期型で取らなくとも、NavMeshAgent & updatePosition = falseでPathだけ計算してもらって、後は自分で移動させるといった方法もアリです。

gist.github.com