正確にキャラクタを配置するための Height Mesh ビルディング
加算読み込みを使用して複数の NavMesh を読み込む

ナビゲーションエリアとコスト

Navigation Areas は、ある特定のエリアを通るときの難かしさの度合いを定義します。コストの低いエリアは、経路探索の際に好まれて選択されます。また、各 NavMesh エージェントには、エージェントが移動するエリアを特定する Area Mask があります。

上の図で、エリアタイプが 2つの一般的な事例に使用されています。

  • Water エリアは、より高いコストを割り当てることで、歩くのに負荷がかかるようにしてあります。これにより、浅瀬を歩くとき歩行が遅くなるというシナリオに対応しています。
  • Door エリアは、特定のキャラクターだけしかアクセスできないようになっています。それによって、人間はドアを通り抜けることができますが、ゾンビにはそれができないというシナリオを実現しています。

エリアタイプは NavMesh ベイクに含まれるすべてのオブジェクトに割り当てられることができ、そのうえに、各 OffMesh Link にエリアタイプを指定するためのプロパティーがあります。

経路検索のコスト

簡単に言えば、コストによって、経路を見つけるときにパスファインダーがどのエリアを好むかを制御することができます。例えば、エリアのコストを 3.0 に設定すると、そのエリアを移動するには他のルートの 3倍以上長くかかると考えられます。

コストの仕組みについて完全に理解するために、パスファインダーの仕組みを見てみましょう。

経路検索中にたどったノードとリンク
経路検索中にたどったノードとリンク

Unity は NavMesh の最短経路を計算するために、A* アルゴリズムを使用しています。A* アルゴリズムは、接続したノードをグラフ上で動かすことを考えます。このアルゴリズムでは、経路の開始点にもっとも近いノードから始め、目的地に到達するまで、つながったノードをたどります。

Unity のナビゲーションはポリゴンのメッシュで表示されているので、パスファインダーが行う最初の事は、各ポリゴンにノードの位置を示す点を配置することです。最短経路は、これらのノード間で計算されます。

上の図の黄色の点や線は、ノードとリンクがどのように NavMesh 上に配置されているかについて示しており、 A* アルゴリズムでは、ノードとリンクはその配置の順序で走査されます。

2つのノード間を移動するためのコストは、移動する距離とリンク下のポリゴンのエリアタイプに関連づけられたコスト、つまり、 distance * cost に依存します。実際には、エリアのコストが 2.0 であれば、このようなポリゴンを横切る距離は、実際の 2倍の長さであるようなものだということを意味します。A* アルゴリズムでは、すべてのコストが 1.0 よりも大きくなければなりません。

結果として求めた経路に生じるコストの影響は、特により長い経路の場合に、調整が難しくなります。コストにアプローチする最良の方法は、ヒントとして扱うことです。たとえば、エージェントにあまり頻繁に Off-Mesh Link を使用させたくない場合、Off-Mesh Link のコストを増加します。しかし、エージェントが歩道の上を好んで歩くように挙動を調整するようなことは困難です。

パスファインダーは必ずしも最短経路を選択するわけではないということが、あるレベルで発生するかもしれません。この理由は、ノードの配置にあります。大きい開放的なエリアが小さい障害物の隣にあり、結果として、大きなポリゴンと小さなポリゴンが含まれるナビゲーションメッシュになるシナリオで、このようなことが目立ちます。このような場合、大きなポリゴン上のノードは、大きなポリゴンのどこにでも配置することができるため、パスファインダーの視点からは、それが回り道のように見えることがあるためです。

エリアタイプ ごとの コスト は、Areas タブでグローバルに設定できます。または、スクリプトを使用して、エージェントごとにそれらをオーバーライドすることができます。

エリアタイプ

エリアタイプは、Navigation ウィンドウAreas タブで指定されています。29のカスタムタイプと、3つのビルトインタイプ WalkableNot WalkableJump があります。

  • Walkable - は一般的なエリアタイプで、歩くことができるエリアであることを指定します。
  • Not Walkable は、経路検索を防げる一般的なエリアタイプです。NavMesh を使わずに、特定のオブジェクトを障害物として指定したい場合に便利です。
  • Jump は、自動的に作成された Off-Mesh Link すべてに割り当てられるエリアタイプです。

異なるエリアタイプのいくつかのオブジェクトが重なる場合、結果として生じる NavMesh エリアタイプは、たいてい、最も高いインデックスのものになります。ただし、例外があり、Not Walkable に常に優先権があります。これは、エリアを遮断する必要がある場合に役に立ちます。

エリアマスク

各エージェントには、ナビゲート可能なエリアを示す Area Mask を設定できます。エリアマスクは、エージェントのプロパティーで設定することができます。または、ランタイムにスクリプトを使ってビットマスクを操作することもできます。

特定のタイプのキャラクターだけがあるエリアを歩くことができるようにしたい場合には、エリアマスクは役に立ちます。例えば、ゾンビを回避するゲームでは、各ドアの下のエリアを、Door エリアタイプに指定し、ゾンビキャラクターの Area Mask で、Door エリアのチェックをはずし、無効にします。

参考文献

正確にキャラクタを配置するための Height Mesh ビルディング
加算読み込みを使用して複数の NavMesh を読み込む