ナビメッシュを使ってパス検索しつつ、プレイヤーを追いかけるだけのAIを作ろうとしたのですが、
「最低限何をすれば良いのか?」
…という情報は、調べても出てきませんでした。
調査しながら試行錯誤して、動作するものを作成。
そこから不要な部分を削ることで、
「何が必要なのか?それは何故必要なのか?」
…が分かりましたので、本稿で共有したいと思います。
本稿は初心者向けです。
C++ は使用せず、ブループリントを使用します。
動作環境
UE 5.4 と 5.3.2
Windows 11 Home
プロジェクトを作る
↓
ナビメッシュを作る
↓
ブラックボードを作る
↓
タスクを作る
↓
ビヘイビアツリーを作る
↓
AIController を作る
↓
キャラクターを作る
↓
動作確認
この順番で説明します。
「サードパーソン」でプロジェクトを作成します。
プロジェクトを作成すると、上図のようなスプラッシュ画面が表示されるので、消えるまで待ちます。
スプラッシュ画面が消えると、上図のようなエディタが起動します。
プロジェクト作成直後なら、ThirdPersonMap がレベルビューポートに表示された状態になっていると思います。
All > コンテンツ > ThirdPerson > Maps > ThirdPersonMap レベル
AIを使ってキャラクターを移動させる場合、以下の2つの方法があります。
1. ナビメッシュの中だけ移動させる。
2. ナビメッシュ関係なく指定した位置に移動させる。
今回は 1. を行うため、ナビメッシュを作る必要があります。
もし、「アウトライナー」の中に「NavMeshBoundsVolume」がある場合は、この手順は行わず、次へ進んでください。
「NavMeshBoundsVolume」がない場合は、上図の通りに「ナビメッシュバウンズボリューム」を選択します。
レベルビューポートにオレンジ色のワイヤーフレームキューブが追加され、「アウトライナー」に「NavMeshBoundsVolume」が追加されます。
※既に「NavMeshBoundsVolume」がある場合は、気にせず次へ進んでください。
アウトライナーの「NavMeshBoundsVolume」を左クリックで選択し、「位置」と「拡大・縮小」を変更します。
おおまかに上図のような状態になればOKです。
メニューの「ビルド」→「パスをビルド」を選択します。
これで ThirdPersonMap にナビメッシュが生成されます。
レベルビューポートの何もないところを左クリックして、キーボードの「P」キーを押し、上図のような緑色に塗られたナビメッシュが表示されるのを確認します。
AI にナビメッシュの中を移動させる場合、この緑色の中だけを移動します。
・マウスの左ボタンクリックが反応するか。
・キーボードの P キーが反応するか。
・UE エディタがフリーズしていないか。
・レベルビューポート内にある壁や床など、何らかのオブジェクトを選択していないか。
・アウトライナーにあるフォルダやオブジェクトを選択していないか。
・アウトライナーにある NavMeshBoundsVolume を削除し、ナビメッシュを作り直して表示されるか。
・UE エディタを再起動した後、表示されるか。
ブラックボードはAIが覚えておくためのデータです。
このデータは、AIが色々な状況判断をするときに使います。
今回必要になるデータは、追いかける対象(プレイヤー)がいる位置(座標)になります。
「コンテンツブラウザ」または「コンテンツドロワー」の「+追加」ボタンを左クリックして、AI > ブラックボード を選択します。
ブラックボードのアセットが作られるので、適当な名前を入力します。
今回は「BB_Test」にしました。
作成したブラックボードのアセットをダブルクリックすると、ブラックボードの編集ウィンドウが表示されます。
その中にある「新規キー」を左クリックして、候補の中から Vector を選びます。
ブラックボードに Vector 型のキーが追加されるので、名前を「PlayerLocation」に変更します。
タスクは AI の小さな行動目標です。
プレイヤーを追いかけるだけの AI には、以下のタスクが必要です。
1. プレイヤーの位置を覚える。
2. 覚えた位置に移動する(ナビメッシュ使用)。
このふたつのタスクのうち、2. は UE 側に用意されているので、自分で作る必要はありません。
作るのは 1. だけです。
「コンテンツブラウザ」または「コンテンツドロワー」の「+追加」ボタンを左クリックして、一覧から「ブループリントクラス」を選びます。
上図のように、「すべてのクラス」を左クリックすると、その下にテキストボックスが表示されるので、「task」と入力します。
テキストボックスの下に、task が含まれるクラスの候補が表示されるので、その中から「BTTask_BlueprintBase」を選びます。
ブループリントクラスのアセットが新規作成されるので、アセット名を入力します。
とりあえず、「BTTask_SetPlayerLocation」にしました。
作成したブループリントクラスのアセットをダブルクリックすると、ブループリントの編集画面が表示されます。
「マイブループリント」内、「変数」の右側にある「+」アイコンを左クリックします。
「NewVar」という名前の変数が追加されるので、名前の右側にある変数の型名「Boolean」を左クリックします。
(Boolean ではない場合があるかも知れませんが、デフォルトの型は使わないので何でも構いません。)
変数名の候補が表示されるので、テキストボックスに「black」と入力し、候補を絞ります。
候補を絞ると、上の方に「Blackboard Key Selector」が表示されるようになるので、それを選択します。
「NewVar」を左クリックすると、変数名を変更できるようになるので、「BlackboardKey」に変更します。
(変数名は任意です。NewVar のままでも構いません。)
設定が終わると、上図の状態になります。
このブループリント変数は、別のファイル(ビヘイビアツリーとブラックボード)からアクセスします。
デフォルトの状態では、別のファイルからアクセスできないので、アクセスできるようにします。
「外」というのは、このアセットの外部、このアセットではない別のファイルのことです。
上図のように目が開いた状態にします。
これで別のファイルから、この変数にアクセスできるようになります。
「コンパイル」ボタンを押してコンパイルします。
※ここで一度コンパイルしないと、追加した変数をブループリントで使うことができません。
上図のように、「イベントグラフ」の何もない所を「右クリック」します。
イベントグラフに配置できるノードの候補が表示されるので、テキストボックスに「event recei」と入力して候補を絞ります。
絞った候補の中から「Event Receive Execute AI」を選択します。
AI がこのタスクを処理するとき、このイベントから処理が始まります。
変数 BlackboardKey をイベントグラフにドラッグ&ドロップします。
候補から Get BlackboardKey を選択します。
イベントグラフに配置した BlackboardKey の右端にある青い丸 〇 を左マウスボタンを押しながら、何もないところにドラッグすると、イベントグラフに配置できるノードの候補が表示されます。
候補の AI カテゴリーにある Set Blackboard Value as Vector を選択します。
この値にプレイヤーの位置(座標)をセットすることで、AI はプレイヤーの位置を覚えることができます。
上図のように、ノードの右端・左端についている、横向きの三角形を左マウスボタンでドラッグして、接続したいノードの三角形にドロップします。
この線を繋ぐことで、イベントノードから処理が開始し、線が繋がっている順番にノードが処理されます。
この場合、Event Receive Execute AI ⇒ Set Blackboard Value as Vector の順番に処理されます。
あとは右クリックのイベントグラフに配置できるノードの候補から、上図にあるノードを選び、ブループリントの処理を作成します。
GetPlayerPawn
GetActorLocation
FinishExecute
ビヘイビアツリーは AI の行動を組み立てるフローチャートのようなものです。
ここまでで作成した「ブラックボード」と「タスク」は、ビヘイビアツリーで使うためのものです。
プレイヤーを追いかけるだけの AI には以下のふたつのタスクが必要です。
1. プレイヤーの位置を覚える。
2. 覚えた位置に移動する(ナビメッシュ使用)。
1. ⇒ 2. の順にタスクを処理して、2. のタスクが終わったら、また 1. に戻ります。
やるべきことはそれだけで、それを「ビヘイビアツリー」の仕組みに合わせて組み立てます。
「コンテンツブラウザ」か「コンテンツドロワー」の「+追加」ボタンを押して、AI > ビヘイビアツリー を選びます。
ビヘイビアツリーのアセットが作られるので、アセット名を入力します。
ここでは「BT_Test」にしました。
作成したアセットをダブルクリックすると、ビヘイビアツリーの編集ウィンドウが表示されます。
「詳細」ウィンドウの AI > BehaviorTree > Blackboard Asset に「BB_Test」が設定されていない場合は、設定します。
※既に設定されている場合は、この手順は不要なので、次のステップへ進んでください。
※BB_Test は「ブラックボードを作る」で作成したものです。
「Root」ノードの下部に、黒に近い灰色の矩形がくっついていますが、ここでマウスの左ボタンを押しっぱなしにして、そのまま「Root」ノードの外へドラッグします。
そうすることで、この矩形から白い矢印が伸びるので、何もないところにドロップします。
配置できるノードの候補が表示されるので、「Sequence」を選びます。
順番は自由に変更できます。
Selecter は複数のタスクの中から一つを選んで処理します。
Simple Parallel は2つのタスクを同時に進めます。
もう少し詳しく知りたい方には以下の記事がお勧めです。
ここで Sequence を選んだ理由は、冒頭で説明した以下の処理を行うためです。
1. ⇒ 2. の順にタスクを処理して、2. のタスクが終わったら、また 1. に戻ります。
なので、Sequence は2つのタスクを持つことになります。
「Sequence」ノードを配置するときと同じように操作して、ノードの候補から「BTTask Set Player Location」を選びます。
※「BTTask Set Player Location」は「タスクを作る」で作成したものです。
Sequence の下にタスクが追加されました。
これが冒頭で説明した 1. のタスクになります。
1. プレイヤーの位置を覚える。 2. 覚えた位置に移動する(ナビメッシュ使用)。
追加したタスクを左クリックして選択した状態にします。
タスクのフチがオレンジ色になっていれば、選択した状態になっています。
この状態で「詳細」を見ます。
デフォルト > Blackboard Key が SelfActor になっていたら、PlayerLocation に変更します。
これによって、このタスクはブラックボードの PlayerLocation に値をセットできるようになります。
SelfActor のままだと、タスクがうまく処理されません。
タスク 1. を作成したので、タスク 2. を作成します。
1. プレイヤーの位置を覚える。 2. 覚えた位置に移動する(ナビメッシュ使用)。
タスク 1. と同様に操作を行い、候補から Move To を選びます。
指定した位置に向かって、ナビメッシュの上を移動してくれます。
パス検索も勝手にやってくれます。
Move To ノードを左クリックして選択した状態にして、「詳細」のブラックボード > Blackboard Key > を「PlayerLocation」に変更します。
こうすることで、
BTTask_SetPlayerLocation タスクでプレイヤーの位置が PlayerLocation に入る。
↓
Move To タスクで PlayerLocation に入っている位置まで移動する。
という順番で処理が行われるようになります。
ここまでで、「プレイヤーを追いかけるだけの AI」の処理は完成しましたが、その AI を呼び出す方法がまだありません。
脳はあるけど、体がない状態です。
AI(ビヘイビアツリー)を呼び出すには、以下のものが必要です。
1. AI を使うキャラクター
2. AI とキャラクターを結びつけるコントローラー
ここでは、2. を作る方法について説明します。
「AI とキャラクターを結びつけるコントローラー」は、
そのまま「AI Controller(AI コントローラー)」と呼びます。
AI コントローラーもブループリントで作ることができます。
ブループリントを新規作成する方法は、ここまでのステップで既に説明しているので省略します。
ブループリントの親クラスは AIController にします。
アセット名は「BP_TestAIController」にしました。
「BP_TestAIController」をダブルクリックしてブループリントの編集ウィンドウを表示します。
「イベントグラフ」に切り替え、「Begin Play」と「Run Behavior Tree」ノードを繋げます。
「Run Behavior Tree」の BTAsset で作成したビヘイビアツリー(BT_Test)を選択します。
この AI コントローラーを、AI を走らせたいキャラクターに組み込むことで、ビヘイビアツリーが処理されるようになります。
AI コントローラーを組み込むキャラクターを作成します。
サードパーソンテンプレートには、ゲーム実行時のプレイヤーキャラクターが既に用意されているので、とりあえず、これを使います。
と言っても、そのまま使うわけではないので、順を追って説明します。
ブループリントを新規作成する方法は、ここまでのステップで既に説明しているので省略します。
ブループリントの親クラスは「BP_ThirdPersonCharacter」にします。
アセット名は「BP_TestCharacter」にしました。
「BP_TestCharacter」をダブルクリックして編集ウィンドウを開きます。
「詳細」 > ポーン > AI Controller Class を「BP_TestAIController」に変更します。
※「BP_TestAIController」は「AIController を作る」で作成したものです。
これで作成したビヘイビアツリーを処理する AI コントローラーをキャラクターに組み込むことができました。
あとは、このキャラクターをレベルに配置すれば動作を確認できるようになります。
作成した「BP_TestCharacter」をレベル内にドラッグ&ドロップします。
ドロップする位置は床がある場所ならどこでも構いません。
位置関係はこんな感じですが、図の通りにする必要はありません。
このカメラは親クラスの「BP_ThirdPersonCharacter」が持っているものなので削除できません。
カメラを持たないキャラクターを作りたい場合は、BP_ThirdPersonCharacter を複製して、カメラを削除し、それを親に設定します。
レベルビューポートの上部にある再生ボタンを押すことで、動作確認できます。
こちらはアイキャッチ画像で使用しているアニメーション GIF の加工元ロングバージョンです。
複雑なことは何もしていませんが、こんな AI を作れてしまいます。
今回は、プレイヤーの位置をブラックボードに保存する部分をタスクで実装しましたが、Environment Query System (EQS) でも同じことができます。
ただ、EQS は UE 5.4 の時点ではβ版なのでお勧めはしません。
本稿で使用している画像のいくつかは、以下のサイトからダウンロードしたものです。