プレイヤー追跡中に新たに優先順位の高いActorが現われたら?

今回は、敵キャラクターに対して追跡の優先順位を設定し、プレイヤーを追跡中でも別のActorを発見したら、そちらに吸い寄せられるというAI処理を実装していきます。

完成イメージとしては、こんな感じです。

プレイヤーには敵キャラクターを誘導する為の白い球をスポーンする能力を持たせました。

敵キャラクターがプレイヤーを追跡中でも、この白い球が現われると、そちらに吸い寄せられていくのが分かると思います。(ただし、白い球は一定時間経過すると天に召されてしまいます。)

まずはAIコントローラーをブラッシュアップします。

“AI_AICharacter”をブラッシュアップします。

今まではプレイヤーを見つけた場合のみ追跡対象としていましたが、今回はプレイヤーだけでなく、白い球も追跡対象となる為、追跡対象の識別の為にタグを付けておいて、そのタグがあるActorを追跡するようにしてみましょう。

変更点はとても簡単で、以下の通りです。元々はプレイヤーキャラクターか否かを条件判定していましたが、今回は対象のActorが特定のタグを持っているか判定するように変更しただけです。

さらに”AI_AICharacter”のブラッシュアップを続けます。

今までは”OnPerceptionUpdate”の中で、ブラックボードの変数を制御していましたが、これらの処理を全てビヘイビアツリーのサービスに移行したいと思います。理由は、ビヘイビアツリー側でプレイヤーを追跡するのか、白い球を追跡するのかを制御したいからです。

つまり、”OnPerceptionUpdate”の処理では、「敵キャラクターの視界に何が入っている?」だけを管理すれば良いので、FindActorsというActor型の配列を定義し、”OnPerceptionUpdate”の結果に従って、現在視界に入っている全てのキャラクターを配列に格納していく処理を実装します。

これで、”AI_AICharacter”の修正は完了です。

白い球のBPを作成します

プレイヤーがスポーンする白い球を作成しましょう。名前は”BP_PlayerDummy”でPawnを継承して作成しました。

DefaultSceneRootをSphereコンポーネントに置き換え、詳細パネルから物理系の処理を有効にします。Sphereコンポーネントを選択した状態で、詳細パネルの”Ignore Radial Impulse”/”Ignore Radial Force”/”Simulate Physics”にチェックを入れ、コリジョンプリセットは”PhysicsActor”を選択してください。

イベントグラフは、以下のようにします。これは、プレイヤーが白い球をスポーンしてから5秒後に天に召されるだけの処理です。

敵キャラクターに見つけてもらう為のタグを付ける

プレイヤーと白い球それぞれに、敵に見つけてもらう為のタグと、優先順位をコントールする為のタグを付与します。(今回はサンプルの為に、優先順位もタグで実装していますが、本来であればキャラクターの基底クラス等で優先順位用の変数等を用意しておくべきです)

プレイヤーには、”ChaseTarget”と”ChasePriorityLow”というタグを付与します。

白い球には、”ChaseTarget”と”ChasePriorityHigh”というタグを付与します。

これで、タグの付与が完了しました。

プレイヤーが白い球を打ち出すロジック

プレイヤーが白い球を打ち出すロジックを作成します。

プロジェクト設定から白い球を打ち出す為のインプット定義を追加し、インプットアクション定義は以下のようにします。ロジック自体は凄く単純で、プレイヤーの正面にBP_PlayerDummyをスポーンさせて前方に転がしてあげているだけです。

敵プレイヤーがどっちを優先して追跡するか用のフラグ定義

“BP_AICharacter”を開き、変数”IsChasePriorityHigh”を追加し、インスタンス編集可とします。

このフラグがTrueならタグに”ChasePriorityHigh”が付与されているターゲットを優先的に追跡し、falseの場合は”ChasePriorityLow”が付与されているターゲットを優先的に追跡するようにします。

ビヘイビアツリーのサービス作成

“AI_AICharacter”のブラッシュアップの中で、元々のロジックをビヘイビアツリーのサービスに移行すると断言しましたので、そのサービスを新規に作成します。

名前は”BTS_Main”としました。

“Receive Activation AI”ノードでは、敵キャラクターのAIコントローラー(つまり”AI_AICharacter”)を変数に確保するだけの処理を実装しました。

次に”Receive Tick AI”を実装します。9割方は元々”AI_AICharacter”に実装してあったロジックのコピペとなります。唯一の違いはブラックボードの”ChaseTarget”に何を格納するのかを判断する為の自作関数”Get Top Priority Chase Target”を呼び出している点になります。

元々はプレイヤーを発見したら、ChaseTargetにプレイヤーを格納していただけの処理でしたが、今回の改修で、敵キャラクターの視界に入っているターゲットの中から、敵キャラクターの優先順位フラグに従って、適切なターゲットをChaseTargetに格納する必要がある為、この判定処理の為に関数”Get Top Priority Chase Target”を用意しました。

具体的なロジックは以下の通りで、敵キャラクターの”IsChasePriorityHigh”フラグを参照しながら、視界に入っている全てのActorから、優先順位の高いAcrtorを1つ抜き出しているだけです。

これで、ビヘイビアツリーサービスの作成は完了です。

ビヘイビアツリーからBTS_Mainを呼び出す

上記で作成したBTS_Mainは、敵キャラクターが巡回か追跡かを判断し、追跡の場合は優先順位の高いターゲットをブラックボードに書き込むという処理となっています。これは、処理の先頭で呼び出すべき内容になる為、ビヘイビアツリーがこんな感じになりました。

これで完成!と言いたいが・・・

これで完成と言いたいところですが、このままだと不具合があります。

現在、プレイヤーの追跡には”Move To”というビヘイビアツリーのタスクを使っていますが、これは目的地まで到達したか、確実に到達できない場合にしか次の処理に移ってくれません。

今回の機能は「プレイヤーを追跡中に白い球を見つけた場合は、プレイヤーの追跡をやめて白い球を追跡開始する」という流れの為、「プレイヤーの追跡をやめて」という処理が行えないのです。

この処理を実現するには、デコレーターを使って処理を途中で追跡を終わらせるか、いつでも追跡相手を切り換えられるビヘイビアツリータスクを新規に作成する必要があります。

いつでも追跡相手を切り換えられるタスク

ということで、BTT_ChaseTargetというビヘイビアツリータスクを新たに作成しました。

ロジックは凄く単純で、以下の通りです。

ビヘイビアツリーに組み込んで完成!

上記で作成した”BTT_ChaseTarget”をビヘイビアツリーに組み込みます。

これで完成!!

レベル上に2人の敵キャラクターを配置して、それぞれを以下のような性格に設定しました。

  • 1人は追跡スピードが速くて、白い球を優先して追いかける
  • 1人は追跡スピードが遅くて、プレイヤーを優先して追いかける

早速、プレイしてみた感じが、こんな風になります。

同じビヘイビアツリーを使いながら、敵キャラクターのフラグ設定だけで、これだけ異なる特性の実装を行うことが出来ました。

今のところ、ターゲットを見失うと、すぐに諦めてしまう点が現実っぽくないので、余裕がある方はビヘイビアツリータスクやビヘイビアツリーサービスを駆使して、リアリティのある敵キャラクターを作ってみるのも面白いと思います。

No responses yet

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です