TilemapでNavMesh(Agent)を利用する方法【Unity】
UnityではNavMeshを利用して、経路検索を簡単に行うことが出来ます。この機能は、Tilemapを使った2D上でも利用することが可能です。自分で利用するときに、結構迷ってしまったので、ここにやり方を残しておきます。で、最後まで書いてて、ソースファイルや実際に設定したものがないとわからないと思ったので、TilemapとNavMeshを利用したサンプルのプロジェクトリポジトリを作成しました。必要に応じてクローンなりダウンロードなり行って利用してください(バージョンは2019.4)
リポジトリ→https://github.com/everystudio/TilemapNavMesh
ダウンロード→https://github.com/everystudio/TilemapNavMesh/archive/master.zip
目次
まず前提としてですが、まだ公式にサポートはされていないことに注意してください。あと、この記事の内容では多少普通のNavMeshについての知識がある前提で話を進めます。今回の話の流れとしては以下の様に進めていきます
- 必要なソースファイルの入手
- 移動可能な範囲を示すタイルマップの準備
- NavMesh/NavMeshAgentなどを利用して移動する処理を実装
事前準備
・動くことが出来るタイルマップの準備
・NavMeshについての多少の知識
必要なソースファイルの入手
Tilemap上にNavMeshを利用するためには、いくつかソースファイルを追加する必要があります。必要になるソースファイルは以下のリンクから手に入れることが出来ます。
ソースファイル:https://github.com/Unity-Technologies/NavMeshComponents/tree/2019.3-2D
こちらNavMesh関連のコンポーネントが公開されているリポジトリなのですが、その中のBranch「2019.3-2D」にあります。
リポジトリをクローンもしくはダウンロードを行い、「NavMeshComponents」「Gizmo」の2つのフォルダを自分のプロジェクトにインポートしてください。Gizmoはなくても大丈夫だと思います。
移動可能な範囲を示すタイルマップの準備
ここに関しては、作る側によって多少差の出る部分だと思います。私の場合はすでに出来ているものに被せる形で実装を行ったため、新規のタイルマップを作成しました。
1.新たにTilemapを追加
ここで追加するTilemapは表示上一番上に見えることが編集しやすいと思います。準備が出来たら、移動可能な範囲に何でも良いので塗ってください。塗った部分が移動可能な範囲になります。自分の場合は白いタイルを塗りまくっています。こちらはゲーム開始時にTilemapRendererを非表示にするためゲーム内で見ることはありません。
2.作成した移動可能なTilemapにコンポーネントを追加
移動出来る範囲にタイルを敷き詰めたら、次は以下のコンポーネントを同Tilemapに追加してください
- TilemapCollider2D
- NavMeshSourceTag2D
NavMeshSourceTag2Dのスクリプトが見つからない場合、前項のソースファイルの追加がうまく行えていない可能性があります。コンポーネント自体は追加した状態のままで構いません。NavMeshSourceTag2DではAreaが指定できますが、こちらに関しては一旦0のままで作業を進めましょう。
ではいよいよNavMeshを作成して行きましょう。作成するにはNavMeshBuilder2Dが必要になります。
- シーン内に空のGameObjectを作成
- 作られたGameObjectにAddComponent「NavMeshBuilder2D」
コンポーネントが正しく取り付けられたら、インスペクターを確認してください。Bakeみたいなボタンがあれば正しく取り付けられています。
実際に使う場合はBakeOnEnableにチェックを入れる必要があります。
下準備も終わったところで実際にNavMeshを利用して行きましょう。NavMeshを作る以外の工程は基本的にいつものNavMeshと同じです
作るの自体はNavMeshBuilder2DのインスペクターにあるBakeを押すだけです。見てくれではすぐにわかりませんが、押したときの形でNavMeshが生成されます。下図は日の字型にTileを配置したもののNavMeshです。
NavMeshを視認するにはWindow>AI>Navigationというウィンドを選択している状態でのみ可能です(このあたりは通常のNavMeshと同様)。
経路の検索と線を表示してみる
ここまで来たらあとは経路検索を行って、どのようなルートが表示されるかを確認してみましょう。経路検索をする場合は、NavMesh.CalculatePathを使うことでどのようなルートが最短なのかを知ることが出来ます。あとはLineRendererなどを利用して経路を線で表示するとこんな感じ。
下図では、青から赤に向かって経路検索を行い、経路を黒い線で表示しています。途中灰色の四角はNavMeshObstacleを利用して、通せんぼを行っているため、中央の経路は選ばれません。
スタートの位置やObstacleの位置を変えるごとに経路が変わるため、見ていても楽しいですね。
どうやって移動させるかなどに関しては、NavMeshAgentを利用してもいいし、経路検索を行ったときに線を描画するためのポイント情報を利用しても可能です。
実際に移動処理を行う場合の注意など
移動させたりする時の注意
注意する点があるとすれば、NavMeshAgentを利用すると、NavMeshに対して垂直方向にAgentを立たせようとするため、2Dの画像などはうまく表示されなくなります。あくまで3D的に処理されてしまうため、このような現象が起こるそうです。あくまで2D状で表示するためにZ軸方向に垂直な面をNavMeshとして利用しているため、そのままNavMeshを利用するのは少し難しい。
そのため実際に移動させる場合には手動で行うか、別のものにNavMeshAgentで移動させて、その座標を追いかけるなど、少し工夫が必要です。
実際に使う場合
また環境にもよりますが、実際にゲームで利用する場合はコンポーネントがかなり邪魔になると思います。移動できる範囲にTilemapCollider2Dを利用しているため、既存のゲームにとって、キャラクターの行動を阻害する可能性があります。NavMeshは、開始時に生成されるため、ゲーム開始直後にTilemapCollider2Dは不要になります。なので、必要に応じてenable=falseなどを行ってゲーム内に干渉させないような処理も必要になるかもしれません。
そのため自分は行動範囲だけを処理するTilemapを追加して、ゲーム時にには取外し可能なように分けています。絵と連動しなくはなりますが、事故は防げるはず。
あとは環境によっても色々と異なってくると思うので、これを基盤にいろいろと改造してみてください。