2019/10/12

UE4のナビメッシュで簡単な優先順位をつける

blog-post-40-content

GIF Description

UnrealEngine4にはいろいろと便利な機能が備わっています。
そのうちの一つが 『ナビメッシュ』 です。

これがあることによって、UE4におけるAI実装はかなり敷居が低くなっています。

ただ、ナビメッシュを使ったAIを実装しているとどうしてもぶち当たる壁があります。 それこそが 『移動の優先順位』 です。

例えば、『地点Aから地点Bに向かって人間を歩かせたい』というとき、
①直進するだけでBに着くがダメージ床だらけの道
②迂回する必要があるが安全にBに着く普通の道
の二つの選択肢がナビメッシュ上のAIに与えられた場合、
何の設定も行っていないと速攻で①のルートを選びます。

理由は簡単で、ナビメッシュ上のAIは目的地に向かって最短のルートを進もうとするからです。
ただし、これだと 違和感バリバリ ですよね。
普通の人間が安全な道があるのに、危険な道を進みだすのはおかしいですもんね。

このような状態を防ぐための機能がUE4には最初から備わっています。
それこそが 『Nav Modifier Volume』 です。

『Nav Modifier Volume』を利用することによって、
簡単な移動の優先順位をつけることができます。

以下の手順で試しに設定していきます。
(1~4までは初歩的な移動AI実装なので、
優先順位について知りたいだけなら5から読み出しても大丈夫です)

ちなみに、UE4のバージョンは4.17.2、
最初のテンプレートは ThirdPersonテンプレート を使用しています。
(グレイマンが使えるならなんでもいいです。後からコンテンツで追加してもOK。)


1.ナビメッシュで動かすためのキャラクターを作る

まずはブループリントを二つ作ります。
一つはAIキャラの制御に使う AIコントローラ です。
コンテンツブラウザで右クリック、『ブループリント クラス』を選択し、
『AIController』を親クラスに設定して作成します。
名前はわかりやすく、『BP_AI_Controller』とでも付けておきます。
今回はこれだけでAIコントローラの実装は完了です。
中身は無くても問題ありません。

blog-post-40-content1

もう一つは AIで動くキャラクター です。
先ほどと同じようにブループリントの作成を行います。
今回の親クラスは『Character』を設定します。
名前はとりあえず『BP_AI_Man』とします。
作成したらAIキャラのブループリントエディタを開きます。

blog-post-40-content2

ノードなどの設定は不要ですが、幾つかの項目を変更します。
まずはMeshを選択し、詳細ウィンドウのMeshから、
キャラクターのスケルタルメッシュを設定します。

ThirdPersonテンプレートを選択しているなら、
最初からグレイマンのスケルタルメッシュがあるため、そちらを利用します。

また、このままでは向きがおかしいほか、浮いてしまっているため、
トランスフォームの位置を『0,0,-90』、回転を『0,0,-90』に変更します。

アニメーションの設定も一応しておきます。
Anim Classに『ThirdPerson_AnimBP』と設定すればOKです。

blog-post-40-content3

最後に先ほど作成したAIコントローラも設定します。 コンポーネントウィンドウで『BP_AI_Man』を選択し、 詳細ウィンドウの『AI Controller Class』を作成したAIコントローラに変更します。

blog-post-40-content10

これで、キャラクターとコントローラの設定は完了です。


2.マップを編集する

blog-post-40-content4

ThirdPersonテンプレートを選択している場合、 画像のようなマップが最初から用意されています。

3人称視点のアクションのチェックにはピッタリなマップですが、 今回のAIのテストでは邪魔なだけですので、 階段やブロックなどを消してしまいましょう。

blog-post-40-content5

一通り消し終えたら、今度は必要なものを配置します。

モードウィンドウから 『ターゲットポイント』 を選択してマップに配置します。 今回は 『-500,950,130』の位置 に配置しました。

続いて、モードウィンドウから 『Nav Mesh Bounds Volume』 を配置します。 位置は『0,0,100』、サイズは『5000,5000,200』 を設定します。 (とりあえずマップ全体を覆えればOK) そして、ツールバーのビルドから 『パスのビルド』 を実行します。 Pキーを押して、全体が緑色に変われば問題なしです。 当然ですが、これを忘れるとAIはうんともすんともいいません。

blog-post-40-content6

最後に、どこでもいいのでAIで動くキャラクターを配置します。


3.レベルブループリントを編集する

グレイマンをターゲットポイントに向かって移動させる 処理を実装します。

ツールバーからレベルブループリントを開き、画像のようにノードを組みます。

blog-post-40-content7

ちなみに、ターゲットポイントとAIキャラクターのリファレンスは レベルで対象を選択した状態で レベルブループリントにて右クリックを行うことで取得できます。

(本当ならビヘイビアツリーを利用するところですが、 今回の目的はただ移動させるだけなのでこの方法を使います)

試しにプレイしてみて、 AIキャラクターがターゲットポイントに向かって移動すればOKです。


4.2つのポイントを交互に移動するように設定する

先ほどまでの要領で、もう一つターゲットポイントを作成し、 以下のようにノードを組みます。

blog-post-40-content8

色々と問題がある 組み方ですが、とりあえず動かす分には問題ありません。 なお、二つ目のターゲットポイントの位置は 『-500,-950,130』 を設定しています。

プレイさせてみると、AIキャラクターが 二つのポイント間を交互に移動するようになるはずです。


5.壁を作る

さて、ここからが 本題の優先順位の話 になります。 先ほど作った2ポイント間移動のマップにいくつかキューブを追加し、 画像のようなマップにしてみました。

blog-post-40-content9

この状態でのAIの移動ルートは大きく分けて3つになります。 左、右、中央ですね。

この状態でプレイすると、もちろんAIは 最短である中央のルート を進みます。 ですが、何らかの理由で左か右のどちらかを進ませたいという場合もあるでしょう。

ということで、ここで登場するのが冒頭で軽く名前を出した 『Nav Modifier Volume』 になります。

『Nav Modifier Volume』は通常のナビメッシュと同じようにモードウィンドウから作成でき、 詳細ウィンドウのAreaClassを変更することで、 AIから見た エリアの優先順位を他よりも下げる ことができます。

blog-post-40-content

例えば、中央のルートを『NavArea_Obstacle』に設定してプレイを始めると 中央のルートの優先順位が下がり、AIは左か右に迂回するようになります。

blog-post-40-content11

もしも、全てのルートが『NavArea_Obstacle』に設定されている場合は、 AIは通常通り中央の 最短ルート を通ろうとします。

NavArea_Obstacleは『移動することが可能だが他より優先度が低い』ということになります。

『Nav Modifier Volume』にはこれ以外に、
優先度が通常のままである『NavArea_Default』
ナビメッシュ自体を無効化する『NavArea_Null』
絶対に移動できない『NavArea_LowHeight』
という種類があります。

(NullとLowHeightの違いはよくわかりません。NavMeshの有無くらい?)

これを利用することによって、 AIの 移動ルートの簡単な誘導 くらいなら行えます。

GIF Description

注意点

『Nav Modifier Volume』を配置した際に NavArea_Nullによりナビメッシュが削られ、 他のAreaClassに設定しても削られたまま、 パスビルトをしてもそのままということがよく起こります。

そのような時には『Nav Modifier Volume』のAreaClassを変更してから エディタの再起動をしてビルド をすると、正常にナビメッシュが表示されます。

おまけ

『Nav Modifier Volume』は 『Nav Modifier Component』 として アクタなどにアタッチさせることも可能です。 これにより、AIが 自主的に避ける障害物 などの実装も容易にできます。 (ただし、動的なナビメッシュ更新をONにする必要があります)

冒頭でも紹介した通り、この方法でできるのはあくまで簡易的な誘導のみです。 より詳細な移動ルートの設定を行いたい場合は、 個別に移動可能エリアを設定できる SupportAgent の利用がほぼほぼ必須になると思います。

また、いつかそれについても記事が書けるときが来ればいいかなと思います。

それでは、ありがとうございました。