このガイドに進むには、事前に「Behavior Tree クイックスタート ガイド」を確認しているか、Unreal Engine 4 のブループリントと Behavior Tree についてあらかじめ理解している必要があります。
Environment Query System (EQS) をBehavior Trees で使用すると、さまざまな テストで環境をポーリングし、それらのテストの結果に基づいて処理方法を決定できます。EQS のユースケースの例としては、AI キャラクターにプレイヤーから離れたカバー位置を見つけさせたり、レベル内で最も近い体力や弾薬を見つけさせたりすることが挙げられます。
Environment Query は、いくつかの異なる要素で構成されています。Environment Query は、Behavior Tree から呼び出すことができます。その後、実際の Environment Query は ジェネレータ を使用して、コンテキスト を参照し、テストを使用することで、最も大きくウェイト付けされた結果を Behavior Tree に提供します。
このガイドでは、プレイヤーが見えるまでランダムに環境を動き回る AI を作成します。プレイヤーが見えたら、AI は EQS システムを使用して、その距離を維持しながら、見晴らしの利く最も良い地点のある環境内の場所を見つけます。これは複数の種類の遠隔攻撃を実行する AI キャラクターがいる状況で役に立ちます。このような場合、以下の例に示すように、AI がプレイヤーとの距離を保ちながら、プレイヤーが見える状態を保持しようとするためです。
このガイドを修了すると、次のシステムの基本について理解することができます。
-
ブループリント ビジュアル スクリプティング
-
AI コントローラー
-
ブラックボード
-
Behavior Trees
-
Environmental Query System (EQS)
-
EQS のコンテキスト
-
AI デバッグ ツール
1 - 必要なプロジェクト設定
このステップでは、AI に必要な複数のアセットを使用するプロジェクトを設定し、EQS システムを有効にします。
このガイドでは、新規の「サード パーソン ブループリント」テンプレート プロジェクトを使用します。
-
プロジェクト内で [Project Settings] > [AI System] > [EQS] セクションへ進み、[Allow Controllers as EQSQuerier (コントローラーを EQS の Querier として使用することを許可)] を有効にします。
EQS システムが有効になっている場合、EQS 関連のアセットを作成してアクセスできます。
-
「Content」>「ThirdPerson」>「[Blueprints」 フォルダで、「AI」という新しいフォルダに BP_ThirdPersonCharacter をコピーします。
-
「AI」フォルダで、[+Add] > [Create Advanced Asset (高度なアセットの作成)] > [Artificial Intelligence (人工知能)] オプションから次の 3 つの AI アセットを作成します。
- BB_Enemy という名前の ブラックボード
- BT_Enemy という名前の Behavior Tree
- EQS_FindPlayer という名前の Environment Query
-
AIController タイプの新しい ブループリント クラス を作成し、そのクラスを AIC_Enemy という名前にします。
-
EnvQueryContext_BlueprintBase タイプの新しい ブループリント クラス を作成し、そのクラスを EQC_PlayerContext という名前にします。
コンテキスト は、さまざまなテストを適用する際の基準として EQS システムで使用できます。「EQS、指定のコンテキストにどれだけ接近しているか」などのテストを実行できます。このガイドのすぐ後で、テストを実行するときに、このアセットを使用して、プレーヤー キャラクターをコンテキストとして提供します。
2 - Environment Query のコンテキスト
このステップでは、このガイドの後半のテストで使用するプレイヤー キャラクターの EQS システムのコンテキストを設定します。
-
EQC_PlayerContext アセットを開き、[My Blueprint (マイ ブループリント)] パネルで、Provide Single Actor 関数をオーバーライドします。
個々の アクタ または 位置、および一連の アクタ または一連の 位置 をコンテキストとして指定できます。
-
Provide Single Actor 関数で、[Resulting Actor (結果アクタ)] として、Get Player Character を呼び出します。
これにより、実行時にコンテキストとしてプレイヤー キャラクターを取得できます。
このケースではブループリントを取り上げていますが、コンテキストの作成方法としては C++ を使用する方がより最適化されています。
3 - EQS の設定
このステップでは、EQS エディタに移動して、プレイヤー キャラクターが見える位置を見つけるためのテストを設定します。
-
EQS_FindPlayer 内で、グラフ内の Root ノードをドラッグして、Points: Grid ノードを追加します。
コンテキストに関連する アイテム を作成するために使用する ジェネレータ にはいくつかのタイプがあります。これらのアイテムはテスト (コンテキスト Y からアイテム X までの距離はどれくらいかなど) で使用されます。アイテムは、テストの結果からを絞り込み、スコアリングされるため、アイテムを使用すると、「一番良い」(最高または最低のスコア) 選択肢を特定できます。
この例では、プレイヤー キャラクターが見える位置に配置される AI の周りのグリッド上に一連のポイントが生成されます。
-
[Details (詳細)] パネルで、[GridHalfSize] を [800] に、[Space Between (ポイント間のスペース)] を [150.0] に変更します。
これらの設定は、テスト対象の使用可能なポイント数とそれらのポイント間の距離を定義するために使用されます。パフォーマンス上の理由から、これを管理しやすいサイズに維持することをお勧めします。グリッドが大き過ぎるとゲームのパフォーマンスに影響が出始める可能性があるためです。
[Generate Around (周りに生成)] フィールドを使用して、グリッドを配置する必要がある場所 (この場合、Querier または AI キャラクターの周り) を特定できます。作成したプレイヤー コンテキストを使用するように [Generate Around (周りに生成)] を設定した場合にも機能しますが、プレイヤーがすでに見えている場合は、AI をプレイヤーの近くのグリッド上のポイントまで移動させる必要はありません。
[Projection Data (投影データ)] オプションには、グリッドの生成方法を決定するためのその他のフィールドがあります。この例では、そのようなフィールドをデフォルトのままにできますが、必要に応じて、後で設定を調整することができます。
-
SimpleGrid ノードを右クリックして、[Add Test (テストの追加)] で [Trace] を選択します。
Trace テストを使用すると、グリッド上のポイントで、プレイヤー キャラクターを見ることができるかどうかを特定できます。
ジェネレータにテストを追加する順序は重要ではありません。テストでは最初にフィルタリングを行ってソートし (後続のテストで処理するアイテムをできる限り減らすように)、さらに負荷でフィルタリングします (そのため、Distance (距離) フィルタは Line of Sight (見ることができる) フィルタの前に実行されます)。
-
右クリックして、Distance タイプの別のテストを追加します。
Trace テストでプレイヤー キャラクターを見ることができるポイントが返されたら、Distance テストで、プレイヤー キャラクターへの近さに基づいてそれらのポイントをスコアリングします。
-
Trace テストを選択して、[Details (詳細)] パネルで次のオプションを設定します
- [Test Purpose (テスト目的)] = [Filter Only (フィルタのみ)]
- [Context (コンテキスト)] = [EQC_PlayerContext]
- [Bool Match (ブーリアン一致)] = オフ
ここでは、見えるかどうかに関する Trace テストの基準ポイント (コンテキスト) としてプレイヤー キャラクターを提供しています。[Bool Match (ブーリアン一致)] オプションをオフにすることで、プレイヤー キャラクターを見ることができないポイントを除外するように指示しています。
-
Distance テストを選択して、[Details (詳細) ] パネルで、[Test Purpose (テスト目的)] を [Score Only (スコアのみ)] に、[Scoring Factor (スコアリング係数)] を [-1.0] に変更します。
Distance テストの目的は、返されたアイテムをスコアリングすることです。また、スコアリング係数 -1.0 ではプレーヤー キャラクターにより近いポイントをスコアリングします。これを 1.0 のままにすると、プレーヤーから最も離れたポイントが返され、最も離れたポイントに到達しようとして、AI がプレーヤー キャラクターの側を走って通り過ぎる可能性があります。
その他にも、スコアを最小値または最大値に固定するオプション、[Scoring Equation (スコアリング式)] を変更するオプション ([Scoring Factor (スコアリング係数)] を掛ける前に正規化スコアに適用される曲線方程式を変更する)、[Normalization Type (正規化タイプ)] を定義するオプション、またはスコアの正規化使用する [Reference Value (基準値)] の割り当てを行うオプションなどのスコアリング オプションがあります。この例では、これらすべてのオプションをデフォルト設定のままにします。
4 - ブラックボードと Behavior Tree の設定
このステップでは、ブラックボード キーを設定して、Behavior Tree のブランチをレイアウトします。
-
BB_Enemy ブラックボード アセットで、次の 3 つのキーを作成します。
- HasLineOfSight という名前の ブーリアン
- MoveToLocation という名前の ベクター
- [Base Class (基本クラス)] が TargetActor という名前の [Actor (アクタ)] に設定されている オブジェクト
これらのキーは、Behavior Tree のブランチ間で更新または移動をするために使用されます。
-
BT_Enemy Behavior Treeを開き、Selectors、Sequences および Wait タスク ノードを使用して次のグラフを作成します。
画像をクリックしてフルサイズで表示
この例には、3 つの主要なブランチがあります。一番左のブランチは Selector ノード (In Combat という名称) を使用して、2 つの Sequence ノード (1 つは Attack で、もう 1 つは Move into Position) を切り替えます。AI が [In Combat] ブランチを実行していない場合は、[Patrolling] という名称の次のブランチを実行します。何らかの理由で、AI が戦闘中でもパトロール中でもない場合は、別のブランチに移動を試みる前にフェイル セーフ タスクを待機します (待機は 1 秒に設定しています)。
5 - Behavior Tree:パトロールの設定
このステップでは、Behavior Tree のパトロール ブランチを設定します。
-
Patrolling Sequence ノードから、Move To タスク ([MoveToLocation] に設定) と [Wait タスク (5 +/- 1 秒に設定) を追加します。
これで、AI はブラックボード キー MoveToLocation に移動して、指定の時間待機するように指示されます。ただし、引き続き MoveToLocation のベクター値を定義する必要があります。
-
ツールバーで [New Task (新規タスク)] を作成してから、コンテンツ ドロワー でそのタスクに BTT_RandomLocation という名前を付けます。
- BTT_RandomLocation で、次のブループリント グラフを再作成します。
Event Receive Execute AI ノードを使用して、[Controlled Pawn (制御されたポーン)] から、[Get Actor Location] に接続し、その戻り値を Get Random Reachable Point in Radius 関数の [Origin (原点)] として使用します ([Radius (半径)] として 1000 を設定)。
Branch の [Conditions (条件)] として、GetRandomReachablePointInRadius ノードの [Return Value (戻り値)] を使用します。True ピンでは、[Random Location (ランダムな位置)] 値と [Key (キー)] が MoveToLocation という名称の Blackboard Key Selector 変数である Set Blackboard Value as Vector を使用します。
False ピンでは、[Value (値)] として [Get Actor Location] を使用している Set Blackboard Value as Vector を使用します。これは、ランダムなポイントが見つからなかった場合に、新しい位置を見つけようとする前にキャラクターが存在する位置を取得します。タスクの最後では、両方の実行ワイヤが [Success (成功)] がオンになっている Finish Execute ノードに接続します。
Behavior Tree でタスクとしてこれを追加する前に、[MoveToLocation] の値を設定できる必要があります。そのため、[My Blueprint (マイ ブループリント)] パネルの目のアイコンをクリックして、この値が [Instance Editable (編集可能インスタンス)] に設定されていることを確認してください。
-
Behavior Tree で、Patrolling 配下の最初のノードとして、BTT_RandomLocation タスク ([Details (詳細)] パネル で MoveToLocation を設定) を追加します。
6 - Behavior Tree:In Combat の設定
このステップでは、EQS_FindPlayer クエリを含む、In Combat ブランチに関連付けられているタスクを設定します。EQS_FindPlayer クエリは、プレイヤー キャラクターが視野に入る位置を見つけるために使用されます。
-
In Combat Selector を右クリックして、次のように設定されている [Blackboard (ブラックボード)] タイプの [Decorator (デコレーター)] を追加します。
- [Observer aborts (オブザーバーによる中断)] が [Lower Priority (低優先度)] に設定されている
- [Blackboard Key (ブラックボード キー)] が [TargetActor] に設定されている
この設定では、TargetActor が設定されたら、優先度の低いタスクを中断して、In Combat ブランチを実行します。
-
Attack Sequence を右クリックして、次のように設定されている [Blackboard (ブラックボード)] タイプの [Decorator (デコレーター)] を追加します。
- Notify Observer (オブザーバーに通知) が On Value Change (値の変更時) に設定されている
- Observer aborts (オブザーバーによる中断) が Lower Priority (低優先度) に設定されている
- Blackboard Key (ブラックボード キー) が HasLineOfSight に設定されている
この設定では、HasLineOfSight が設定されている場合、Attack ブランチを実行するように指示しています。HasLineOfSight が設定されていない場合は、HasLineOfSight が再度設定されるまで、他のブランチを実行します。
-
Attack ノードから、[Rotate to face BB entry] (TargetActor に設定) を追加します。
これにより、「Attack」ブランチの間、AI が TargetActor に向かって方向転換します。この例では、AI に提供する攻撃はないものの、必要に応じて、後で攻撃などを追加できます。
-
Move Into Position ノードで、Run EQSQuery ノードを使用します。
Run EQSQuery ノードを使用すると、割り当てられたブラックボード キーを更新する EQS Query を実行できます。
-
Run EQSQuery ノードの [Details (詳細)] パネルで、[Blackboard Key (ブラックボード キー)] を [MoveToLocation ] に、[Query Template (クエリ テンプレート)] を [EQS_FindPlayer] に設定します。
-
Run EQS Query に続いて、MoveTo (MoveToLocation に設定) および Rotate to face BB entry (TargetActor** に設定) を追加します。
Behavior Tree が EQS Query を実行して [Blackboard Key (ブラックボード キー)] の [MoveToLocation] を更新し、AI がその位置に移動して、TargetActor (プレイヤー キャラクター) の方に向くように方向転換します。
全体の Behavior Tree は、次のようになります。
画像をクリックしてフルサイズで表示
7 - AI コントローラーの設定
このステップでは、AI コントローラーを設定して Behavior Tree を実行し、AI が AI Perception を使用して、プレイヤー キャラクターを確認する方法を提供します。
- AIC_Enemy ブループリントで、Event On Possess を追加して、Run Behavior Tree (BT_Enemy に設定) に接続します。

-
次のように [AI Sight config (AI の視野設定)] が設定されている AIPerception コンポーネントを追加します。
- [Senses Config (感知設定)] で [AI Sight config (AI の視野設定)] を追加する
- [Detect Neutrals (中立を検出)] を オンにする
この設定により、AI は他のアクタを感知し、アクタが Perception システムで認識されたときにイベントを開始することができます。現在、デフォルトでは、プレイヤーには所属が割り当てられておらず、所属は C++ コードを使用して割り当てたもののみである場合があります。この状況を回避するために、Perception システムで中立を検出できるようにしています。アクタのタグ付けを使用すると、「プレイヤー」としてタグ付けされたアクタだけを認識できます。
- AIPerception コンポーネントでは、[Events (イベント)] で On Target Perception Updated を追加して、Perceived Actor という名称の変数に Actor ピンを昇格します。
画像をクリックしてフルサイズで表示
AI が何かを認識すると、そのアクタは変数として格納され、後でブラックボードを更新するために使用されます。
- 次の条件で 2 つの Branch ノードを追加します。
画像をクリックしてフルサイズで表示
- 1 番目のブランチ 条件 は Actor Has Tag に設定されています。[Tag (タグ)] は [Player (プレイヤー)] であり、[Target (ターゲット)] は Perception Updated の Actor (アクタ)] に接続されています。
- 2 番目のブランチ 条件 は、Perception Updated イベントの [Stimulus (刺激)] のピンから [Successfully Sensed (正常に感知)] に設定されています。
この例では、認識されたアクタにプレイヤーのタグがある場合、ブランチにより、そのアクタが正常に感知されているかどうかを引き続き確認します。アクタのタグがない場合 (おそらく他の敵) は、ブランチではこの処理を進めません。
-
第 2 ブランチの False ピンから、以下に示す 3 つのノードを追加します。
ここでは、Set Timer by Event ノード (8.0 に設定) があり、[Return Value (戻り値)] が LostSightTimer という変数に昇格されています。次に、作成した LostSight という名前のカスタム イベントを イベント デリゲート として割り当てます。
-
[My Blueprint (マイ ブループリント) ] パネルで UpdateSightKey と UpdateTargetKey という 2 つの関数を作成します。
これら 2 つの関数を使用して、Behavior Tree で決定を行うために使用されるブラックボード キーを更新します。
-
UpdateSightKey で、HasLineOfSight という名前の [Boolean (ブーリアン)] 入力を追加します。
-
UpdateSightKey で右クリックして Blackboard 変数を取得して、[Key Name (キー名)] を [HasLineOfSight] を使用する Set Value as Bool に接続します。
これで、この関数を使用してブーリアン値経由でブラックボード キーに渡し、HasLineOfSIght キーを更新できます。
-
UpdateTargetKey で、TargetActor という名前の [Actor (アクタ)] 入力を追加します。
-
UpdateTargetKey で右クリックして Blackboard 変数を取得して、[Key Name (キー名)] を TargetActor を使用する Set Value as Object に接続します。
UpdateSightKey 関数と同様に、これを使用すると、通過するすべてのアクタでブラックボード キー TargetActor が更新されます。
-
次のように、UpdateSightKey 関数および UpdateTargetActor 関数を False 条件に追加します。
AI Perception でプレイヤーのタグを持つアクタを正常に感知されない場合、false 条件によりタイマーが開始され (後でタイマーをハンドルに格納する)、ブラックボード キー HasLineOfSight が false に更新されます。指定された時間 (8.0 秒) が経過すると、カスタム イベント LostSight が実行され、TargetActor ブラックボード キーがクリアされます (つまり、プレイヤーがターゲットでなくなり、プレイヤーを見失ったことを意味します)。
タイマーの [Time (時間)] 値を調整することで、AI がプレイヤー キャラクターの追跡を「あきらめる」までの時間を微調整できます。
-
第 2 ブランチの True ピンでは、LostSIghtTimer および Clear and Invalidate Timer by Handle を使用します。
これにより、プレイヤー キャラクターを見失った時に使用するタイマーが停止され、リセットされます。
-
UpdateSightKey (オン に設定されている) と UpdateTargetKey (Perceived Actor に設定) を追加します。
全体的なグラフは次のようになります。
画像をクリックしてフルサイズで表示
これで、AI コントローラーが設定され、Behavior Tree が実行され、AI Perception システムでプレイヤーのタグを持つアクタが認識されたときに基づいてブラックボード キーが更新されます。
8 - 最終設定
このステップでは、敵の AI キャラクターのブループリントを設定し、AI が認識できるようにタグ プレーヤーをプレイヤー キャラクターのブループリントに追加して、AI が環境の周囲を移動する方法を認識し、視野を簡単に分けることができるように Nav Mesh Bounds Volume といくつかのメッシュを追加します。
- BP_Enemy を開き、[Details (詳細)] パネルで [Use Controller Rotation Yaw (コントローラーのヨー回転を使用する)] をオンにして、[AI Controller Class (AI コントローラー クラス)] を[AIC_Enemy] に設定します。
画像をクリックしてフルサイズで表示
AI が Behavior Tree 内で回転タスクを実行するには、[Controller Rotation Yaw (コントローラーのヨー回転)] をオンにする必要があります。また、ロジックを含むAI コントローラーのカスタム クラスを割り当て、Behavior Tree を実行します。オプションで、プレーヤー キャラクター (および Camera コンポーネント) からコピーしたすべてのスクリプトを削除しました。AI キャラクターには必要ないためです。
-
[Mode (モード) ] パネルから、Nav Mesh Bounds Volume をレベルに追加し、レベルをカプセル化するようにスケーリングします。
P キーを押すと、移動可能なパスを緑で表示するデバッグ グリッドのオン/オフを切り替えることができます。ゲームプレイ中に、コンソール コマンド show Navigation true (Nav Mesh を表示する) または false (Nav Mesh を非表示にする) で、Nav Mesh の表示を切り替えることができます。
-
レベルの ThirdPersonCharacter を右クリックして、[Edit ThirdPersonCharacter (サードパーソンキャラクタの編集)] を選択します。
-
[Details (詳細)] パネルで、「Tag」を検索して、[Player (プレイヤー)] という名前の [Tag (タグ)] を追加します。
AIC_Enemy ブループリント内では、AI Perception システムがアクタを認識すると、ブランチが True と評価されるように、このアクタにプレイヤーのタグがあります。
-
レベル内で、視野を遮るための追加のカバー ポイントを提供するために、複数のバージョンの [Cube Mesh (キューブ メッシュ) ] をスケールアップして追加します。
- ツールバーの [Play (プレイ)] ボタンをクリックしてレベルで再生します。
9 - 最終結果
エディタでプレイしている間、AI はプレイヤーが見えるまでランダムに巡回します。プレイヤーが見えたら、AI は方向転換してプレイヤーの方を向き、プレイヤーを見失ったら新しい場所に移動しようとします。AI は EQS を使用して、プレーヤーが視野に入るものの、離れた距離を保つことができる場所を見つけます。新しい位置に移動している間に再びプレイヤーを見失ったら、下のビデオに示されているように、AI は時々追跡をあきらめて、巡回に戻ります。
AI デバッグ ツール を使用すると、(Behavior Tree や認知情報に加えて) アクティブな EQS Query を表示できます。実行時に AI デバッグを有効にするには、' (アポストロフィ) キーを押してから 1 (一般的な AI デバッグ)、2 (Behavior Tree)、3 (EQS) または 4 (AI Perception) を選択します。以下では、AI デバッグを有効にして EQS デバッグ ツールを表示しています。
EQS デバッグ ツールが実行されている間、それらのスコア値と一緒にグリッド テストのポイントが表示されます。また、選択され、Winner というテキストが表示されるポイントも確認できます。これらのツールは、どのポイントが評価されているのか、およびスコア値に基づいてあるポイントが別のポイントよりも選択される理由を確認するのに役立ちます。
EQS デバッグ ツールの使用に加えて、エディタで EQS Query をデバッグするために使用できる EQS Testing Pawn という名前の特別なタイプのポーンがあります。この Pawn を作成するには、EQS Testing Pawn クラスの新しいブループリント クラスを作成します。

現在の設定では、EQS テストで評価するコンテキストとしてプレーヤー キャラクターを使用します。ゲームが実行されていない間にテストするには、EQS_PlayerContext ブループリントを少し修正して、Provide Actors Set 関数をオーバーライドする必要があります。

Resulting Actors Set を提供する ThirdPersonCharacter に設定された Get All Actors of Class を使用できます。

EQS Testing Pawn をレベルに追加するときは、[Details (詳細)] パネルで [Query Template (クエリ テンプレート)] (EQS_FindPlayer クエリに設定) を割り当てることができます。

これにより、次に示すように、エディタでテストの結果を確認できます。
また、EQS データは参照可能な VisLog を使用して記録されます。詳細については、「Visual Logger (ビジュアル ロガー)」を参照してください。