23
13

More than 3 years have passed since last update.

【UE4】パトロールをする敵AIの作り方

Last updated at Posted at 2020-12-08

最初に

どうも、ろっさむです。

今回はUE4でパトロールを行う敵AIを作る手法についてまとめようと思います。

本記事では Behaviour Tree 関連や AIPerceptionに関する詳細な説明は省きますのでご了承下さい。
興味がある方は以下の記事を参照してください。

【UE4】味方AIの作り方!AIとは何かを学びながら、ブループリントで味方キャラクターを実装しよう

作り方

BTとBBの作成

まずは敵用のBTとBBを作成してください。

image.png

image.png

BT_Enemyの方ではBB_Enemyを設定しておいてください。

image.png

今回、BB内で必要となる情報はPlayerのActor情報と、移動地点のVector情報です。
予め設定しておきましょう。

New Keyを押下し、Key TypeObjectBase ClassActor にしてPlayerActorという名前のKeyを作成してください。

image.png

また、同様にNew Keyを押下し、Key TypeVectorにしてRoutePointという名前のKeyを作成してください。

image.png

これでBBの設定は終わりです。
次にBTの設定を行いましょう。

敵AIのBTの土台を構築

今回のAIでは敵がプレイヤーを発見しているかどうかで行動パターンが異なってきます。
ですので最初のコンポジットノードは Selectorに設定しておきましょう。
ノード名をわかりやすい任意の名前に変更しておいてください。

image.png

まずはパトロールを行うパターンを作っていきたいと思います。

コンポジットノードの Sequenceを追加して、Selectorから繋いでください。

image.png

パトロールを行っているということは、まだプレイヤーは未発見状態です。
ですので、BBの PlayerActorには何もSetされていないということになります。
デコレーターノードを使用してプレイヤーが未発見の状態の時のみ、この Sequenceノードを通るようにします。

image.png

このSequenceでは、敵は設定されている RoutePointを移動することになります。このRoutePointは後程設定するように処理を作成します。MoveToノードを追加して、Blackboard KeyRoutePointに設定しておいてください。また、 Acceptable Radiusもできるだけ小さい値にしておいてください。

image.png

設定後はSequenceに繋いでください。

image.png

次に、プレイヤーを発見した際に、プレイヤーを追従するパターンを作ります。

新しくSequenceを追加してわかりやすい任意の名前を設定した後、Selectorに繋いでください。

image.png

こちらのパターンは単純にプレイヤーを追うだけなので、MoveToノードを追加して Blackboard KeyPlayerActorに設定するだけです。Acceptable Radiusは任意の値に設定してください。

image.png

設定が完了後、Sequenceノードに繋いでください。
これで一旦土台は完成です。

image.png

使用している敵AIControllerのBeginPlayにてBTを走らせる処理を入れておきましょう。またここでBBの変数を作成し、BBの参照を持っておいてください。

image.png

敵に視覚情報を追加する

敵のAIController用BPを開いて、Add Componentから AIPerceptionを追加してください。

image.png

追加したら、AIPerceptionDetailsを確認し、Scenes Configの+ボタンを押下してAI Sight configを追加してください。
これで視覚の機能が備わったことになります。

Sight Radiusは敵を中心とする視覚範囲内の半径にプレイヤーが入ってきたら検知するために使用します。
Lose Sight Radiusはその逆で、この半径を超えると見失ったことになります。
この二つは任意の値に設定しておいてください。

また、Detection by Affiliationは全てにチェックマークをつけてください。プレイヤーかどうかの判断は今回はキャストで行います。

image.png

設定ができたら、OnPerceptionUpdatedOnTargetPerceptionUpdatedの二つのEventを追加します。前者はプレイヤーを発見した際に使用し、後者はプレイヤーを見失った際に使用します。

まずはOnPerceptionUpdatedを作っていきましょう。

「On Perception Updated」からは発見したアクター群の配列が出力されているため、一つ一つPlayerのBPであるかどうかを確認していく必要があります。ただし、Playerを見つけることができたらその後の処理は行う必要がないため、途中でループ処理を中断できる「ForEachLoopWithBreak」を呼び出します。

"Array Element"として出力されているActorがどのように発見されたか知ることができる「Get Actors Perception」という関数があります。この関数にActorを渡し、ターゲットとして自身のコンポーネントであるAIPerceptionを繋げます。

image.png

出力された"info"というデータを分解し、"Last Sensed Stimuli"という配列の0番目(つまり視覚)を取り出します。

image.png

これを更に分解し、要素の最後に存在している"Successfully Sensed"(感知が成功しているか)をブランチに繋ぎ成功していれば、次はプレイヤーを登録する処理に移っていきます。

image.png

感知されたActorがプレイヤーBPであれば、ブラックボードのキー「PlayerActor」に設定を行います。
image.png

設定後は、もう検索ループを掛ける必要がないので、ノードを先ほどの「ForEachLoopWithBreak」にある"Break"へと繋ぎます。

image.png

次に、プレイヤーを見失った場合の処理を作成しましょう。
OnTargetPerceptionUpdatedの実装に移ります。

こちらでは出力されている Simulus Successfully Sensedfalseであれば、BBからPlayerActorの参照を外すという処理だけを行っています。

image.png

これでAIController側での処理は完了です。

Splineを使用してパトロールルートを設定する。

Spline Componentを使用することでレベル上に曲線や直線を設定して、今回のAIのようなパトロールルートとして扱うことができます(もちろんそれ以外にもレベル作成周りとかでバリバリ使えます)。

まずはActorを継承したBPを作成して BP_EnemyPatrolRouteと名付けます。

image.png

ダブルクリックでBPを開き、Add Componentから Splineを選択します。

image.png

追加できたらレベル上に BP_EnemyPatrolRouteを配置します。配置すると、ぴょろっと点と線が表示されているかと思います。

image.png

この点が後々パトロールポイントとなります。点は移動させたり回転させることができます。
点を増やしていくことでルートを作成していきます。
ちなみにルート作成するのにあたって、点を右クリックすると表示される Spline Generation Panelが役立つかもしれません。

image.png

image.png

実際に使ってみるとよくわかるのですが、円や曲線、四角形などをぱっと簡単に作成してくれます。
また点の数や長さ、点の追加開始位置なども設定が可能です。

他にも点をもし上下で動かしてしまった場合などに、点を選択して右クリックするとFloorへスナッピングなどできます。

image.png

点をもりもり増やしてパトロール経路を作成しましょう....

image.png

こんな感じにしてみました。

次の段階に進みましょう。

敵BPに経路用のアクターを設定

パトロールの経路を作成した後は、敵側でそのパトロール経路を取得できるようにしましょう。

任意の敵BPを開いて、変数を追加してください。

名前をRouteActorにして、型を先ほどパトロール経路作成用のActor、BP_EnemyPatrolRouteに設定します。
また、レベル上に敵BPを配置した際にエディタ側から設定ができるように Instance Editableにチェックをつけておいてください。

image.png

設定ができたらコンパイルして、レベル上に敵BPをパトロール経路近くに配置してください。

配置したら Detailsから先ほどの変数RouteActorを検索し、レベル上に設置しているBP_EnemyPatrolRouteを設定してください。
image.png

これでレベル上での下準備は終わりです。

BT上でのサービスノードでパトロールポイントを更新する

先ほど作成したBT_Enemyを開いてください。
開いたら、上部メニューのNew Serviceを押下してBTService_BlueprintBaseを継承したサービスノードを新規で作ってください。

名前をBTS_UpdatePatrolPointとしておきます。

image.png

BTS_UpdatePatrolPointを開いてください。
FunctionsのoverrideからEvent Receive Tick AIというサービスノード自身がアクティブ状態の際のTickと、Event Receive Activation AIというサービスノードがアクティブになった際に呼び出されるメソッドを選択してください。

image.png

image.png

次に今回必要な変数を定義しておきます。
Integer型のCurrentPatrolPointという名前の変数を作成してください。

image.png

それから、BBの方で定義しているRoutePointに値を設定するために、BT側からKeyを登録するためのBlackboard Key型のRoutePointKeyという変数も作成してください。

image.png

ではまず、Event Receive Activation AIにて初期化処理から実装していきます。
ただ今回は初期化時にパトロールポイントをランダムに設定するための処理をしています。もし不必要な場合はこのイベント自体なくても大丈夫です。消しちゃってください。

まずは、Controlled Pawnから敵BPにキャストを行います。成功したらパトロール経路用に設定したRouteActorからSplineコンポーネントをgetしてください。getしたら、そのSplineで設定されている点の数が何個あるかを取得できるGetNumberOfSplinePointsを追加します。

image.png

この値をMAX値としてランダムなint型を生成するRandomIntegerを繋げ、出力された数値をCurrentPatrolPointに設定します。

image.png

これで初期化処理は完了です。

次はサービス自体のTick処理です。

初期化処理時と同様にControlled Pawnから敵BPにキャストを行います。成功したらパトロール経路用に設定したRouteActorからSplineコンポーネントをgetしてください。getしたら、Splintで設定した何番目の点の位置を取得するかというGetLocationSplinePointを追加してください。ここでのPointIndexにはCurrentPatrolPointを設定します。またCoordinateSpaceWorldを設定しておいてください。

image.png

取得したVector値をBlackboardのRoutePointに設定します。KeyにはRoutePointKeyを設定してください。

image.png

最後に次のパトロールポイントへ進むための準備をします。CurrentPatrolPointをインクリメントして、もしその結果がSpline上での最後のポイントであれば最初のポイントを設定するように0に初期化します。

image.png

これでサービスの処理は完了です。

image.png

BTに戻って、パトロール中のSequenceノードに追加してください。

image.png

仕上げとして、BTにて値が切り替わったら処理を中止するように変更

現在の状態でも動くには動きますが、パトロール場所へ移動中にプレイヤーを見かけても無視して移動が終わってから追いかけようとしたり、プレイヤーを見失うことができません。
これを可能にするために、デコレーターに細工をします。

Notify ObserverOn Value Changeにし、Observer abortsBothにしておきます。こうすることで、PlayerActorの値が変わった瞬間に現在実行しているタスクの処理は中断されROOtから判定し直しとなります。Bothは二つのSequenceどちらも中断の対象となるように設定する項目です。

image.png

これでBTは完了となります。

image.png

結果

実際に実行してみてください。以下のツイートが実装例となります。(Gifでは限界がありました)

23
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
13