概要
この記事では、Unreal Engine 5 のBlueprint(BP)で、下図の Environment Query System (EQS) を利用するにあたっての、筆者が考えるEQSの基本情報と、注意点を紹介させていただきます。
(※AIのBehaviorTreeでEQSを使用する方法に関しては、こちらの記事では紹介いたしません。)
この記事の主な対象者
- Blueprint(BP)の作り方の基礎を習得されている、初心者の方
- EQSにあまり触れたことのない方
目次
- 前提知識
- 代表的なGenerator
- EQSの点数付けによる点数計算
- EQSの実行方法
- EQS内のパラメータを外部から変更する方法
- EQSのデバッグ方法
- 地形に合わせた位置にItemを作成する方法
- 参考文献
前提知識
EQSを利用することで、特定の条件を満たす場所の座標の取得や、付近の場所に対して特定の採点方式に基づいた点数付け、特定の条件を満たす付近のアクタの取得などができます。そのようなことができるEQSを利用するにあたって、下記のようなものを利用します。
Querier
EQSを実行する際に使用する下図のノード「Run EQSQuery」において、引数でEQSに渡すオブジェクトを指します。
EQSでは「Aを基準とした、Bまでの距離がX以下かどうか見る」というように、様々な条件を指定することができるのですが、その条件設定の際の「A」や「B」などのオブジェクト設定項目に、Querierを設定することができます。(EQSでは「A」や「B」に設定するものは「Context」と呼ばれており、「Querier」はその一つとして利用できます。)
筆者個人としては、Querierには基本的には「Run EQSQuery」を実行したオブジェクト自体、もしくはそのオブジェクトが保持しているオブジェクトを渡して、それ以外の汎用的に使用するオブジェクト(プレイヤーのアクタ など)は、カスタムContext(下記サイト参照)を作成してEQSでContextとして使用できるようにすると良いと考えています。
Item
EQSでは「特定の条件を満たす場所の取得」や「付近の場所の点数付け」ができると上に記載させていただいたのですが、「Item」はその条件を満たす場所の候補とする場所や、点数付けをする場所のことを指します。
EQSでは指定した範囲のすべての座標が、条件を見たり、点数付けをする場所となるわけではなく「Item」と呼ばれるオブジェクトが作成される場所が、条件を見たり点数付けをする場所となります。
実際には、下図のようにItemが生成されます。
「Item」の生成する数や密度は、下記の「Generator」の中で指定することができます。
Generator
EQSの検索対象の場所を決定づけるものです。EQSにおける、検索対象とする場所「Item」の詳細設定や、検索対象とするアクタの種類の設定などができます。
EQSの中で、デフォルトで使用できるGeneratorにはいくつかの種類があるのですが、この記事の下の方で、筆者が代表的と考えるGeneratorを紹介させていただきます。
テスト
「AからBまでの距離がどれくらいか」や、「ナビメッシュ上におけるAからBまでのパスがあるか」といった、EQSにおける候補の場所に対する条件チェックや、点数付けに使用する処理のことを「テスト」と呼びます。
この記事を読んでいただくにあたって、前提知識として必要な知識は以上となります。
代表的なGenerator
筆者が個人的に、使用することが多くありそうと感じた2種類のGeneratorを紹介させていただきます。
Donut: ○○周りにアイテムを作成
○○を起点とした一定距離範囲内において、特定の条件を満たす場所を探したり、特定の条件下で一番適している場所を探したりする際に使用します。
(例:敵の一定距離範囲内における、プレイヤーが到達可能な位置(ナビメッシュが生成されている場所)で、敵が向いている方向の前方±60度の角度の場所を取得した後に、その場所に向けて、敵からメテオのような弾を発射する など)
Generatorの詳細設定では、下図のようなことを設定できます。(変数名を囲っている色と、その下の図で使用する色を紐づけています。)
上のような設定をすると、下図のようになります。
ActorsOfClass: ○○周辺にクラス△△のアクタ一式を生成
○○を起点とした一定距離範囲内にいる、クラス△△のアクタの中で、特定の条件を満たすアクタを探したり、特定の条件下で一番適しているアクタを探したりする際に使用します。
(例:Playerから一定距離範囲内において、特定のGameplayTagを持っていて、かつナビメッシュ上においてプレイヤーに到達可能な位置にいる「BP_Test」クラスのアクタを取得する など)
筆者個人としては、常に自身の付近に探索対象のものがあるかとかを見るわけではないとき(例えば、何かのスキルを使用した瞬間のときだけ何かの探索をするとき など)に、コリジョンのコンポーネントをオンオフしつつBPの特定の処理を行ったりするのではなく、EQSのこのGeneratorを使用すると良いのかなと考えています。
下の動画では、プレイヤーを起点とし、色のついているキューブのBPを検索対象としたEQSを実行しています。EQSを実行した際に、画面左上に「Run EQS」と表示し、検索対象のBPがEQSの検索範囲内にいると、レベル上におけるそのBPの名前を出力するようにしています。(EQSの検索範囲をわかりやすくするために、プレイヤーにEQSの検索範囲と同じ範囲の球のコンポーネントを付けています。)
Generatorの詳細設定には、下記のように設定をします。
変数名 | 変数の設定内容 |
---|---|
Searched Actor Class | 検索対象のクラスを設定します。 |
Generate Only Actors in Radius | チェックを入れていると、「検索の中心」からの「Search Radius」範囲内にある「Searched Actor Class」クラスのアクタだけでなく、レベル全体の「Searched Actor Class」クラスのアクタが検索対象となります。 |
Search Radius | 「検索の中心」からの検索対象範囲の半径(3D)を設定します。 |
検索の中心 | 検索の起点とするContextを設定します。 |
※注意
このGeneratorは、「Generate Only Actors in Radius」という項目のチェックを外すことで、レベルに配置されているアクタすべてを検索対象とできることから、おそらく高頻度で行うことを想定していないGeneratorであると考えられますので、Tickなどで呼ばないようにした方が良いと筆者は考えます。
EQSの点数付けによる点数計算
EQSでは、テストの設定項目「Test Purpose」を「Score Only」か「Filter And Score」と設定したテストのみが、点数付けをするテストとなり、Generatorに設定した採点付け対象テストの加算点数が、EQSで見る各場所の点数となります。(乗算でないことに注意します。)
各テストにおける、デフォルトの採点点数の範囲は「0.0」~「1.0」ですが、各テストの設定項目「スコア」で採点範囲の設定ができ、各テストの重要度を決定づけることができます。(例:近くの場所よりも、カメラの視界内にある場所の方を優先して探してほしいため、カメラのより中央に映っている場所の点数を高くするテストの点数上限を「10」にする など。)
(設定項目「スコア」の内容は、テストによって異なります。下図はテスト「Dot」の「スコア」の項目です。)
EQSの実行方法
EQSをBPから実行する際は、下図のノード「Run EQSQuery」を使用します。
「Query Template」には実行するEQSを、「Run Mode」には、取得したい場所の種類に合わせたModeを設定するようにします。
Run Mode の種類 | 取得する場所 |
---|---|
All Mathching | 設定したFilterのテストの条件をすべて満たしている場所 |
Single Best Item | 設定したFilterのテストの条件をすべて満たし、かつ点数(スコア)が一番高い場所 |
Single Random Item from Best 〇% | 設定したFilterのテストの条件をすべて満たし、かつ点数(スコア)が上位〇%の場所の中から、ランダムで選ばれた1つの場所 |
EQSの実行処理の完了を検知できるようにするために、「Run EQSQuery」ノードの後ろには、「OnQueryFinished」イベントへのバインド処理を書きます。
完了検知のイベントのパラメータで受け取れる「Query Status」で、EQSが成功したか失敗したかがわかります。基本的には「Success」と「Failed」を使用します。Filterのテストで、1つも条件を満たす場所が見つけられなかった際などは「Failed」のStatusが渡されます。
EQSの実行結果の場所は「Get Query Results as Locations」ノード、アクタは「Get Query Results as Actors」ノードで受け取ることができます。GeneratorでItemを作成して適した場所を探す際は「Get Query Results as Locations」ノード、「ActorsOfClass」Generatorなどを使用して対象のアクタを探す場合は「Get Query Results as Actors」ノードを使用します。
基本的なEQSの実行方法は以上です。
EQS内のパラメータを外部から変更する方法
外部(BPなど)から値を変更できるEQS内のパラメータには、「Data Binding」という設定項目が付いており、この項目を利用することで外部から値を変更できるようになります。
外部から値を変更できるようにするために「Data Binding」の項目に「クエリパラメータ」を設定します。「Data Binding」の項目に「クエリパラメータ」を設定すると、「Param Name」という項目が表示されます。この「Param Name」が、外部から値を変更する際のキーとなります。(項目「Param Name」の値は自由に変更して問題ないですが、この記事ではデフォルトで作成された値をそのまま使用します。)
外部からEQS内の値を変更するタイミングは、EQSの実行命令直後(同フレーム)です。BP側からEQSの値を変更するグ遺体的なタイミングは、この記事の上の方で説明させていただいた「EQSの実行方法」における「Run EQSQuery」ノードの後ろです。(「OnQueryFinished」イベントへのバインド処理の前後どちらでも問題ないです。)
「Run EQSQuery」ノードの後ろに、EQS内の値を変更できる「Set Named Param」ノードを追加します。「Set Named Param」ノードの、引数「Param Name」には、EQS内の「Data Binding」の「Param Name」の値を設定し、引数「Value」には、そのEQS内のパラメータに設定したい値を設定します。
以上の方法で、EQS内の値を変更することができます。
EQSのデバッグ方法
エディタ上でレベルを編集している際のデバッグ方法と、ゲームプレイ中のデバッグ方法の2種類のデバッグ方法を紹介させていただきます。
※この記事では、EQS内のパラメータを外部から変更する処理の確認をされたい場合のゲームプレイ中のデバッグ方法は説明しておりません。この記事で紹介しているデバッグ方法を利用されたい場合は、一時的にパラメータを外部から変更する処理を抜いて固定の値を入れて、デバッグしていただけないでしょうか。
エディタ上でレベルを編集している際のデバッグ方法
デバッグ対象のEQSのファイルをクリックして選択状態にした後、エディタのレベル編集画面にドラッグ&ドロップします。
EQSのファイルをレベルにドラッグ&ドロップすると、「EQSTestingPawn(C++上はAEQSTestingPawn)」というクラスのアクタがレベルに作成されるとともに、EQSの実行結果が可視化されます。青色の球体がFilterのテストで無効化されたItemで、それ以外の色の球体がScoreのテストによって点数付けされたItemです。青色の球体の上の文字はItemが無効化されたFilterのテスト名、それ以外の色の球体の上の数字はそのItemの点数を表しています。
(上のような表示にするために、筆者のテスト用EQSの設定および、ナビメッシュは下図のようにしていました。)
EQSのテストをしたい場所に、作成された「EQSTestingPawn」のアクタを移動させると、EQSの実行結果を確認できます。
以上が、エディタ上でレベルを編集している際の、EQSのデバッグ方法です。
ゲームプレイ中のデバッグ方法
※注意点
ゲームプレイ中にデバッグ表示するためには、C++の実装が必要となります。下記には、C++を用いた実装方法を紹介させていただきます。
EQSの実行結果のデバッグ表示(下図の色が付いた球表示)をするには、下記の対応をしていく必要があります。
【ゲームプレイ中に、EQSのデバッグ表示を行うために必要な対応】
1. C++上で、クラス「AEQSTestingPawn」を継承したクラスを作成する
2. 手順1で作成したクラスに、EQSの実行結果のデバッグ表示を更新させる処理を実装する
3. 手順1、2で作成したクラスを継承したBPを作成し、レベルに配置する
4. ゲームプレイを開始し、デバッグ表示をするための操作を行う
1. C++上で、クラス「AEQSTestingPawn」を継承したクラスを作成する
まず、「AEQSTesginPawn」をC++上で利用できるようにするために、「[プロジェクト名].Build.cs」ファイルの中の、「PublicDependencyModuleNames.AddRange」と書かれているところに「AIModule」を追加します。
その後に、「AEQSTestingPawn」を継承したクラスを、通常のC++のクラス作成方法と同じ方法(Unrealエディタのツールバーからの作成や、C++のファイルがあるフォルダ上での右クリックからの作成 など)で作成します。
以上で、手順1「C++上で、クラス「AEQSTestingPawn」を継承したクラスを作成する」は完了です。
2. 手順1で作成したクラスに、EQSの実行結果のデバッグ表示を更新させる処理を実装する
デフォルトの状態(「AEQSTestingPawn」クラスに実装されている状態)のままでは、デバッグ表示されるEQSの実行はゲーム開始時にしか行われません。そのため、デバッグ表示されるEQSの実行処理を一定期間毎に呼び出すようにします。
この記事では、Tick毎に呼び出すようにします。(毎フレーム呼び出されると処理負荷的にあまりよくないため、手順3でTickの頻度を調整するようにします。)
具体的には、下記のように関数「TickActor」をオーバーライドします。(関数「RunEQSQuery」は、親クラス「AEQSTestingPawn」で定義されている関数です。)
void ADebugEQSTestingPawn::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
{
// AEQSTestingPawn の QueryTemplate にセットされたEQSを実行する
// AEQSTestingPawn::TickActor の中で、EQSのデバッグ表示更新処理を行っているため、
// AEQSTestingPawn::TickActor を呼ぶ前に AEQSTestingPawn::RunEQS を呼ぶ必要がある
RunEQSQuery();
// 親クラス「AEQSTestingPawn」を呼び出し、デバッグ表示の更新をする
Super::TickActor(DeltaTime, TickType, ThisTickFunction);
}
以上で、手順2「手順1で作成したクラスに、EQSの実行結果のデバッグ表示を更新させる処理を実装する」は完了です。
おまけ
もし、TickActor内で関数「UKismetSystemLibrary::PrintString」を呼び出したいのでしたら、「Super::TickActor」の前に呼ぶようにしたほうが良いと思います。筆者の環境では、「Super::TickActor」の前に「UKismetSystemLibrary::PrintString」を呼び出すと、EQSのデバッグ表示がされなくなりました・・・。
3. 手順1、2で作成したクラスを継承したBPを作成し、レベルに配置する
最初に、手順1、2で作成したクラス(この記事では「ADebugEQSTestingPawn」)のBPを作成します。
手順1、2で作成したクラス「ADebugEQSTestingPawn」は、デフォルトではTick処理が有効化されていないため、作成したBP内の詳細パネルの「EQS」>「Tick During Game」の項目(下図赤枠)にチェックを入れ、Tick処理が有効化します。
また、EQSが毎フレーム実行されるのは処理負荷的に好ましくないため、Tickの呼び出し頻度を毎フレームではない状態にします。この記事では、1.0 秒毎にTickが呼び出されるようにします。(デバッグの際は多少処理負荷が重くなっても、毎フレームの状態を確認されたいとのことでしたら、Tickを毎フレーム呼び出すようにしても大丈夫です。)
次に、EQSの実行結果を確認したい場所に、作成したBPのアクタを配置します。
最後に、配置したアクタを選択状態にし、詳細パネルの「EQS」>「Query Template」に、デバッグ表示をさせたいEQSを設定します。
以上で、手順3「手順1、2で作成したクラスを継承したBPを作成し、レベルに配置する」は完了です。
4. ゲームプレイを開始し、デバッグ表示をするための操作を行う
ゲームプレイを開始した後に、アウトライナー上で手順3でレベルに配置したアクタを選択します。アクタを選択すると、下の動画のように、EQSのデバッグ表示が確認できるとともに、Tick毎に表示が更新されていることが確認できるようになります。
(下の動画の環境では、手順3で作成したBP内に、Tick毎(1.0 秒毎)にアクタの座標を移動する処理を書いているため、下の動画ではEQSのデバッグ表示が移動しています。)
以上で、手順4「ゲームプレイを開始し、デバッグ表示をするための操作を行う」は完了であるとともに、「ゲームプレイ中に、EQSのデバッグ表示を行うために必要な対応」は完了です。
地形に合わせた位置にItemを作成する方法
デフォルトのままの設定にしておくと、Generatorによって作成されるItemは、下図ようにGeneratorの設定項目「中央」に設定したContextのZ座標と同じZ座標に配置されます。(下図だと、赤いブロックの中にItemが埋まっています。)
地形に合わせた位置にItemを作成するために、Generatorの設定項目「Projection Data」を利用します。
「Projection Data」の詳細設定項目の1つ、「Trace Mode」には、Itemを生成する「地形」として扱うものの種類を設定します。
Trace Mode の種類 | 「地形」として扱うもの |
---|---|
Navigation | ナビメッシュ |
Geometry by Channel | 指定したトレースチャンネルとブロックの関係にあるもの |
Geometry by Profile | 指定したトレースプリセット(プロファイル)とブロックの関係にあるもの |
この記事では、例として「Trace Mode」を「Geometry by Channel」とし、地形にピッタリ沿わせたZ座標にItemを生成するようにします。
筆者のテストマップの床や赤色のキューブのメッシュは、トレースチャンネル「Visibility」とブロックの関係にあるため、下図のような設定にし、Itemを生成する場所としてテストマップの床や赤色のキューブのメッシュを認識するようにします。
上図のような設定をすることで、筆者のテストマップ上では、下図のように地形に沿った位置にItemが作成されます。
以上が、地形に合わせた位置にItemを作成する方法となります。
※注意点
「Projection Data」の詳細設定項目の「Project Up」と「Project Down」によって、設定したトレースチャンネルとブロックの関係にある場所を探す高さの範囲を設定できます。具体的には、この記事の例だと、Generatorの設定項目「中央」に設定したContextのZ座標を Z としたとき、(Z - ProjectionDown)~(Z + ProjectionUp)のZ座標の範囲だけ、指定したトレースチャンネルとブロックの関係にある場所を探すようになります。
「Projection Up」や「Projection Down」に大きすぎる値を設定すると、問題になることがあります。例えば、EQSを2階建ての建物の中で実行するとし、下図のように、探索範囲が2階に届いてしまっているような「Projection Up」の値を設定しているとします。
下図のように設定していると、Itemが2階で作成されるようになり、EQSの実行した階層である1階とは別階層の2階を、EQSの実行結果の場所と返すようになってしまいます。このような、想定していないZ座標にItemが作成されないように注意しましょう。(筆者は過去に小屋の中でEQSを使用し、屋根の上にItemが作られて頭を抱えました・・・。)
この記事のテストマップで上の状況を試すと、下図のようになります。
以上で今回の記事の内容は終了です。
最後まで読んでいただき、ありがとうございました。
参考文献
Epic Games, EQS ノードのリファレンス:コンテキスト | Unreal Engine 5.6 ドキュメンテーション, https://dev.epicgames.com/documentation/ja-jp/unreal-engine/eqs-node-reference-contexts-in-unreal-engine, (参照 2025-08-31)