執筆バージョン: Unreal Engine 4.12
改訂バージョン: Unreal Engine 4.19 |
今回はEQSという機能を使って群れを動かすのをやってみようと思います。
この機能は4.12ではまだ実験的機能として提供されている段階なので、記事の内容は将来的に使えなくなる可能性があります。
EQSとは、複数の選択肢の中から条件に合わせた、最も良いActorや場所(Vector)などを求めてくれる機能です。
条件にはキャラクターから見えるか、キャラクターの正面にあるか、近いか、などの条件が複数設定できます。
EQSの公式ドキュメントはこちら
Environment Query System
https://docs.unrealengine.com/ja/InteractiveExperiences/ArtificialIntelligence/EQS/EQSOverview/index.html
Behavior Treeはこちらを参考にしてください
ビヘイビアツリー
https://docs.unrealengine.com/ja/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/BehaviorTreesOverview/index.html
1.EQSの機能をOnにする
「編集 > エディタの環境設定」からエディタの環境設定を開き、「一般 > 実験段階」のAI内にあるEnvironment Query SystemのチェックボックスをONにするとEQSが使えるようになる。
![eqson](https://historia.co.jp/wp/wp-content/uploads/2016/06/eqson-300x160.jpg)
2.Behavior Treeの準備
コンテンツブラウザ上で右クリックをし、AIの項目から「ビヘイビアツリー」と「ブラックボード」を作成する。
AIで動かすキャラをCharacterを親にして作成、さらにAIControllerを親にしてブループリントを作成する。
![ai](https://historia.co.jp/wp/wp-content/uploads/2016/06/ai-300x300.jpg)
Characterのブループリントを開き、デフォルト値のPawnの中にあるAIControllerClassに先ほど作成したAIControllerのクラスを設定。
![aiconsete](https://historia.co.jp/wp/wp-content/uploads/2016/06/aiconsete-300x155.jpg)
次にAIControllerのブループリントを開きEventGraphのBeginPlayからUseBlackboardとRunBehaviorTreeノードをつなぎ、それぞれに先ほど作ったアセットを設定。
![runbihavi](https://historia.co.jp/wp/wp-content/uploads/2016/06/runbihavi.jpg)
これでBehaviorTreeの機能を使う準備ができました。
3.EQSの準備
コンテンツブラウザから右クリックでAIの項目にある「環境クエリ」を選択します。これがEQSの本体となります。
![envquery](https://historia.co.jp/wp/wp-content/uploads/2016/06/envquery.jpg)
4.EQSで探すActorを作成
今回はネコちゃんが餌に群がるようなQIを作りたいので、エサとなるブループリントをActor継承で作成します。
StarterContentから適当に拝借し、こんなブループリントになりました。
![food](https://historia.co.jp/wp/wp-content/uploads/2016/06/food-300x195.jpg)
CollisionはコリジョンプリセットをOverlapAllDynamicに設定しています。
5.EQSの作成
環境クエリのアセットをダブルクリックで開きます。
ダブルクリックで開くと「ルート」のみ表示された状態です。
まずは、右クリックから”Generator”を作成します。詳しい種類については、公式のリファレンスをご覧ください。 https://docs.unrealengine.com/ja/InteractiveExperiences/ArtificialIntelligence/EQS/EQSNodeReference/index.html
この中からActor of Classを選択します。
Searched Actor Classに先ほどのBP_Foodを設定します。半径には5000としておきます。
これで範囲内のBP_Foodクラスを返すEQSとなります。
このままでは、発見したBP_Foodクラスに優劣がつかないのでActorOfClassノードを右クリックして「テストを追加」から条件を付けていきます。
一つ目はDistanceを設定します。
これは距離により優劣をつける条件です。
パラメータは以下のようにします。
![](https://historia.co.jp/wp/wp-content/uploads/2016/06/EQSdetails.png)
これで距離の近いものほど選ばれやすくなります。
二つ目の条件にPathExistを選択します。
これは、対象までの移動経路が確保できるかどうかを評価します。
これで、到達できない位置にいるActorを省くことができます。
パラメータは以下の通りです。
![](https://historia.co.jp/wp/wp-content/uploads/2016/06/PathExist.png)
これでEQSは完成です。
![eqsfkix](https://historia.co.jp/wp/wp-content/uploads/2016/06/eqsfkix-300x169.jpg)
6.Behavior TreeでEQSを使う
まず、ブラックボードを開き「新規キー」でObjectを作成します。
![bboard](https://historia.co.jp/wp/wp-content/uploads/2016/06/bboard.jpg)
BaseClassにはActorを設定します。ここでは名前をFoodとします。
EQSは最も良いとみなした結果をActorか場所(Vector)で求め、BlackBoardのキーに返してくれます。そのためBaseClassにはActorかVectorを設定してください。
次にビヘイビアツリーを開きます。
BlackboardAssetには先ほどのブラックボードを設定します。
SimpleParallelノードを配置し、SimpleParallelノードを右クリックで「サービスを追加… > Run EQS」を選択します。
パラメータは以下の通りです。
![runeqsparam](https://historia.co.jp/wp/wp-content/uploads/2016/06/runeqsparam.jpg)
狙ったFoodが存在するかどうかを新規タスクを作って監視します。
上の新規タスクから「BTTask_BlueprintBase」を選択し、タスクを作成します。名前はExistとしました。
BlackboardKeySelector変数を作成し、編集可能にしておきます。
![existeqsvariable](https://historia.co.jp/wp/wp-content/uploads/2016/06/existeqsvariable.jpg)
コードは以下の通りです。
![existeqs](https://historia.co.jp/wp/wp-content/uploads/2016/06/existeqs.jpg)
対象のActorがなかった場合、FinishExecuteにて失敗を返します。
このタスクと、BehaviorTreeのデフォルトのタスクである「MoveTo」を使い以下のようにBehaviorTreeを作成しました。
![bteqs](https://historia.co.jp/wp/wp-content/uploads/2016/06/bteqs.jpg)
ExistとMoveToのタスクはそれぞれ対象となるActorを設定できるので、それぞれにブラックボードで用意したFoodを設定します。
7.NavMeshボリュームを配置する
EQSで設定したAIを動かすため、Modes (モード) -> Volume (ボリューム) -> Nav Mesh Bounds Volumeをマップへドラッグして配置します。
![](https://historia.co.jp/wp/wp-content/uploads/2016/06/NavMeshBoundsVolume.png)
AI Characterを移動させたい領域を囲むように配置してください。
![](https://historia.co.jp/wp/wp-content/uploads/2016/06/NavMeshUsed.png)
以上で一番良いご飯に向かうネコちゃんのAIの完成です。
![manyneko](https://historia.co.jp/wp/wp-content/uploads/2016/06/manyneko.jpg)
右クリックで餌を置く。
おなかが減ると小さくなっていき消える。
満腹になると3つに分裂する。
などの要素を入れるとこんな感じになりました。