Unreal Engine 5を使ってみる その3(NPCのナビゲーション)
はじめに
今回はUnreal Engine5(UE5)でエージェントを動かしてみました。ゲームだとNPCにあたるものでしょうか。
UE5の資料を漁っていたのですが、AI(人工知能)の項目にあったので試してみました。
▼こちらのページです。
https://dev.epicgames.com/documentation/ja-jp/unreal-engine/artificial-intelligence-in-unreal-engine
▼今回はこちらの「基本のナビゲーション」のページを参考にしています。
上記のページではプレイヤーが操作できるThirdPersonCharacterを削除していたのですが、私は操作したかったので残しています。また、ブループリントを少し変更して動きを変えたり、Spawnさせたりしてみました。
▼以前の記事はこちら
ナビゲーションメッシュの配置
ナビゲーションメッシュを配置します。NPCが動く範囲を決めるときに必要な情報のようです。
▼ウィンドウから、「アクタを配置」を選択します。

▼NavMeshBoundsVolumeを選択します。

▼全体を覆うように拡大します。

▼キーボードのPキーを押すと、ナビゲーションメッシュが視覚化されます。

オフセットを調整すると見やすくなるということだったのですが、そんなに変わらないような気もします。
3DCADだと面から離れたところにオフセット平面を配置することがありますが、同じような感じですね。
▼「オフセットを描画」の値を変更して調整できます。

▼オフセット値が50の方が面から離れています。


他にも見やすくするための機能があるようです。
▼ポリゴンのエッジを描画するとこんな感じ。


▼タイルの境界を描画するとこんな感じ。


NPCを作成する
ThirdPersonCharacterをコピーして、ブループリントを編集します。
▼BP_Third Person Characterをコピーします。

▼Naviフォルダを作成して配置しました。

▼ダブルクリックすると、詳細が表示されます。

▼レベル内には30体配置しました。

プレイヤーとは見た目も変更しておきました。メッシュのSkeleton Mesh Assetで選択できます。
▼色も変更したほうが、違いが分かりやすいかも?

ブループリントの編集
MoveNPCという名前のカスタムイベントを作成し、NPCを動かすときに呼び出すようにします。プログラミングだと関数にするような感じですね。
▼ブループリント上で右クリックすると、ノードを検索できます。

▼カスタムイベントを追加し、MoveNPCという名前を付けました。

NPCは今いる位置からRadius(半径)1000のなかでランダムな位置に移動するようにします。
▼Radiusは1000にしました。

Random Locationを右クリックして、「変数へ昇格」を選択し、値をセットできるようにしています。
AI Move Toノードで、Locationに向かって動くようになります。処理が終わると再度MoveNPCを呼び出し、同じ処理を繰り返します。
▼DelayのDulationが長いと、少し動いて立ち止まるのを繰り返します。

▼全体のフローはこちら

▼最後に、イベントBeginPlayにMoveNPCを繋いで、開始時に呼び出します。

実際に動かしてみました。ちなみに、F8キーでアクタのコントロールから離れることができます。
▼NPCがナビゲーションメッシュから離れずに動いているのが分かるかと思います。台の上にいるNPCは降りてこないですね。
▼30体のNPCが動き回っています。

目標地点に向かって走らせてみる
今回は操作しているアクタに向かって走らせてみます。
Get Player PawnとGet Actor Locationで、プレイヤーの位置を取得します。その値を、AI Move Toに渡します。
▼Randomだった部分を置き換えています。

これだけでプレイヤーに向かって近づいてくるようになります。
▼プレイヤーから距離を取るようにしてもいいのかも?
▼集まってきました。

Spawnさせてみる
Spawnで調べるとSpawn AIFrom Classがあったので使ってみました。分かりやすいように、NPCの頭上からSpawnさせてみました。
▼エージェントのLocationに、z軸方向+500をしてSpawnさせています。

SpawnしたNPCがMoveNPCを呼び出さないと動かないのですが、イベントBeginPlayはPlay開始時にしか呼び出されないようでした。つまり、すでにPlayが始まった状態でSpawnしたNPCは動き出しません。
今回はNPCの頭上からSpawnするので、着地時にMoveNPCを呼び出すようにしてみました。
▼ちょうどイベントOn Landedというものがありました。

実際に動かしてみました。さすがに処理が重そうだったので、DelayのDurationは、5.0にしています。
▼上からNPCが降ってきます。
▼ぞろぞろ...

最後に
NPCのナビゲーションをすることができました。ノード自体はシンプルですね。
決められた範囲のみ動くのであれば、障害物を避けながらロボット掃除機のような動きもできそうです。ThirdPersonCharacterの見た目を置き換えたいですね。
▼NPCと音声会話できるプラグインもあるのだとか!面白そうですね。
https://www.gamespark.jp/article/2023/05/26/130299.html
▼後で知ったのですが、NPCどうしの衝突を避けることもできるようですね。