LoginSignup
18
12

More than 1 year has passed since last update.

Unity - 経路探索第二の選択肢、A* Pathfinding Projectを導入してみる

Posted at

Unityでは標準で経路探索を行うための強力な機能が、NavMeshで提供されています。
それなりのケースではNavMeshで十分なのですが、ちょっと凝ったことをしようとするとできない場合があります。

自分の場合は、「味方キャラは侵入をできないが、自キャラはなんの問題もなく通過できるエリアを動的に作りたい」というやりたいことに対して、NavMeshだと実現するのが難しそうだったので、A* Pathfinding Projectというアセットを導入しました。

今回の記事では、A* Pathfinding Project(フリー版と一部Pro版)の導入について書きたいと思います。
前述の自分がやりたかった機能まで説明すると込み入るので、NavMeshと同等の部分を実現するところまで説明したいと思います!
(経路探索がよくわからない人は、最初にUnity標準のNavMeshを触ることをおすすめします!)

環境
Unity 2021.1.1.2f1
A* Pathfinding Project Free版・Pro版 4.2.15

↑こんなことがA* Pathfinding Projectでできます。(が、今回の記事はこれの前段までの紹介にとどめています)

A* Pathfinding Projectとは

アセットストア:https://assetstore.unity.com/packages/tools/ai/a-pathfinding-project-pro-87744
Free版:https://arongranberg.com/astar/download

  • 経路探索が行えるアセット
  • 経路の定義に使用できるグラフの種類が豊富(Unity標準のNavMeshでは、メッシュを使用するもの一択)
    • Unity標準と同等のNavMeshGraph
    • Gridで定義するGridGraph
    • 点で経路を決定するPointGraph などなど
  • Free版も存在するが、AI同士の衝突回避が使用できない(これに目をつむればFree版でも結構色々できる)
    • ここからFree版とPro版、NavMeshの機能比較が見られます
  • ドキュメントもそれなりに豊富に用意されています(全部英語ですが)
  • 軽量に動作し、mobileでも問題なく動きます(もちろんフィールドが広すぎないことは前提ですが)
    • ランタイムでの経路再スキャンもある程度軽量なので、mobileでもいけそうです

導入してみる

では早速導入してみましょう。
Free版を使用して、対象を追いかけるAIを作ってみようと思います。

Free版のインポート

まずは適当にUnityプロジェクトを作成、Free版が配布されているサイトからDLします。
unitypackageがダウンロードされるので(パッケージマネージャではないです)、ファイルをクリックしてインポートしましょう。
image.png
余裕がある人は、「ExampleScenes」に入っているサンプルを見てみると参考になります。

適当にフィールドを作成

経路探索させるには当然ながら歩けるフィールドがないとダメですよね。
今回は、Unity標準のPlaneやCubeなどを使ってフィールドを雑に作ります。

ここで、重要なのがコライダーがアタッチされているオブジェクトを使用することです。
(Unity標準のPlaneやCubeなどは最初からコライダーが設定されています)
これから作成するGridGraphはコライダーの存在で経路を判別するようなので、コライダーが存在しないとそこは通れる経路になってしまいます。

image.png
こんな感じにしてみました。...センスとかはないので期待しないようにしてください。
中央にあるCubeを長くしたものは障害物の扱いのつもりで置きました。

ここで、ついでに各オブジェクトにレイヤーの設定をしておきましょう。
地面にGround、障害物にObstaclesと設定しました。
経路探索のコンポーネントに、レイヤーを指定するときに使用します。
image.png
image.png
image.png

Pathfinderコンポーネントの設定

次に、経路探索を行うためのコアのコンポーネントを設定していきます。
適当に空のオブジェクトを作成、Pathfinderコンポーネントを追加します。
(AddComponentするときはPathfinderと出ますが、本当の名前はAStarPathです)
image.png
インスペクターに各種項目が表示されるのでGraphsを展開、Add New GraphのGrid Graphを選択します。(今回はGrid Graphを使用します)
image.png
ボタンを押すと、ずらずらと設定項目が表示されます。(表示されない時は、さらにメニューを展開してください)

今回はこんな感じで設定しました↓
初期設定から変えたのは、Width(nodes)Depth(nodes)DiameterObstacle Layer MaskMask(Height Testingの設定)です。
image.png
この状態で、シーンタブもしくはインスペクターのPathfinderコンポーネント下部のScanボタンを押すと以下のように経路が設定されます。
青い部分が歩ける経路、赤い点が歩けない場所(経路と障害物の境界)です。
(色がつかない人は、Show Graphsにチェックを入れるもしくは、SettingsのDebug - Graph ColoringをSolid Colorにすると出るかもしれません)
image.png

主要な設定項目について簡単に解説します。

Shape
ノードの形状。大体はGridで良さそうですが、用途によりHexagonalとかにしても良いかもです。
Gridだと四角に区切られて経路が決定するので、斜めに配置してある障害物に対して若干ムラが出てしまう時に使うと...いいのかも...です(あんまり良い使い方がわかってないです)

Width(nodes), Depth(nodes)
ノードのそれぞれの方向の数です。
経路を作りたいフィールドの広さに合わせて、増減させましょう。
当然ですが、ノードが増えれば増えるほど経路のスキャンが重くなりますのでご注意を。

Node Size
グリッドを作るノード一つの大きさです。
大きくすれば計算負荷は小さくなりますが、経路と障害物の境界が大まかになったり、移動経路がバラけづらくなります。

Center, Rotation
ノードが配置される中央の点と、回転です。

Collision Testing
歩ける範囲の検知を行うかどうかです。
経路探索を行う時は基本オンで良さそうです。

Diameter, Height/Length
歩くオブジェクトの大きさと高さの定義です。

Obstacle Layer Mask
障害物としてみなすレイヤー設定。
今回は、先ほど追加したObstaclesレイヤーを指定しています。
必要に応じて複数選択できます。

Height Testing
高い位置に登ることができるかどうかの判定を行うかどうかの設定です。
オフにすると、高い場所もそのまま経路として判断されるようになります。
これも通常はオンのままで使うのが良さそうです。

Mask(Height Testingの設定)
Height Testingに使用するレイヤーマスクです。
今回は先ほど追加したGroundレイヤーを指定しています。

経路探索を行うAIの設定

経路が設定できたので、次は経路を歩くAIの設定を行いましょう。
Unity標準のNavMeshのNavMeshAgentにあたるものを設定していきます。

これまた適当に3Dオブジェクトを用意します。
そのオブジェクトにAIPathをアタッチします。
image.png
AIPathをアタッチすると、自動的にSeekerコンポーネントもアタッチされます。
image.png
↑設定はこんな感じです。今回はMax SpeedGravityぐらいしか変えていません。

よく使いそうな項目を簡単に解説します。

Radius, Height
AIの半径と高さです。
オブジェクトの大きさに合わせて設定しましょう。

Can Search, Can Move
経路探索を行えるか、移動できるかのフラグです。
Can Moveをオフにすれば(もちろんスクリプトからも可能)、移動を強制的に停止することができます。

Max Speed, Rotation Speed
最大移動速度と、回転速度です。

Slow Down Distance
目的地の手前どれくらいの距離で、減速するかの設定です。
減速がいらない場合は0にしましょう。

End Reached Distance
目的地の手前どれくらいで移動を終えるかの設定です。

Constrain Inside Graph
グラフ内に移動を制限する設定です。
基本的にAIは、設定された経路しか歩かないのですが、衝突回避のために押し出されて経路外に出てしまうことがあるようです。
この時に、このオプションが有効化されていると、経路内から出ないようにしてくれるようです。
また、自前で移動を行う際(AIPathのMove()メソッドによる移動)に、このオプションを設定しておくと経路外に出てしまうことがなくなります。

Gravity
重力を使用するかどうかの設定です。
基本的には使わなくて良さそうなので、自分はオフにしています。

目標を追跡するための設定

AIの経路探索設定までできたので、そのAIが目標を追いかけるようにする設定を追加しましょう。
スクリプトで追いかける目標を設定する場合は、AIPath.destinationに目標の座標を設定すればOKです。

今回は、最初から用意されているAIDestinationSetterを使用して、インスペクター上から目標を設定できるようにします。
先ほどAIPathを設定したオブジェクトに、AIDestinationSetterをアタッチします。
image.png
そして、追跡目標として適当なオブジェクトを作成して(今回はSphereを使いました)、AIDestinationSetterのTargetに設定します。
image.png

追跡!

これで目標を追跡するための設定は終わったので、実行してみましょう。
シーンビューで、追跡目標にしたオブジェクトを動かすと、AIも移動しますね。
ezgif.com-video-to-gif.gif

衝突回避の設定

さて、目標の追跡まではできました。
一見いい感じに動いていますが、AIが二体以上いる場合に同じ目標に対して追跡させると、見事に重なり合います。
これは、衝突回避の機能が有効になっていないからです。
ezgif.com-video-to-gif-2.gif
↑こんな感じに、重なって移動してしまいます(緑色AIと青色AIが重なっています。わかりづらくてすみません...)。

ということで、衝突回避の機能をつけてあげようと思いますが、ここからは有料版が必要です。
以降の内容はアセットストアのA* Pathfinding Project Proがすでに導入済み前提で進めます。
(衝突回避を有料版onlyにする...商売上手ですね!)

衝突回避コアコンポーネントの追加

まずはPro版の導入ですが、アセットの購入後にパッケージマネージャからインポートするだけでOKです。
自分はFree版から上書きインストールしましたが、特に問題はなさそうです。

では、衝突回避に必須なコアコンポーネントRVOSimulatorを追加していきます。
空のオブジェクトを作成、RVOSimulatorをアタッチします。
image.png
こちらのコンポーネントは、デフォルト設定のままでも十分使用できるので、今回は設定は特にいじりません。

AIに衝突回避コンポーネント追加

最後に、AIにRVOControllerをアタッチしましょう。
image.png
すでにAIPathがアタッチされているので、RadiusHeightCenterはAIPathの値が使用されると書いてありますね。

この状態で実行してみましょう!
ezgif.com-video-to-gif.gif
無事二つのAIが重なり合うことなく、目標を追いかけていますね。

gifの最後に、目標到達後に青いAIが目標地点をぐるぐる回り始めますが、これは緑のAIが目標地点にいていつまで経っても目標地点に到達できないためです。
これを防ぐには、AIPathのEnd Reached Distanceをもう少し大きく設定して、目標地点の手前で移動を終えるようにするのが一つの手段だと思います。

まとめ

結構長くなってしまいましたが、これでA* Pathfinding Projectによる最低限の経路探索ができるようになりました。
正直、ここまでのことならUnity標準のNavMeshでも問題なくできるのですが、ここからA* Pathfinding Project独自の設定を入れていくところがある種本番ですね...!

また余裕のある時に、ページ冒頭のtweetのようなペナルティエリア設定などの紹介ができればいいなと思います。

18
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
12