ゲーム開発備忘録

ゲームプログラマー UE4・5向けの記事を書いておりますので見ていただけるとありがたいです。

【ゼロからアンリアルエンジン5】〔AI編〕⑧プレイヤーを見失ったら探すNPCを作る。

目次

 

はじめに

 

注意

UE5.0.3の現在の情報です。

今後のアップデートによりUIや機能が変更される可能性があることをあらかじめご理解ください。

 

今回はプレイヤーを見失ったら最後に見た場所まで移動して探すNPCを作ります。



 

前回

namiton.hatenablog.jp

 

 

解説

⓪スムーズな回転を実装する

以前紹介させていただいたPavilion DV7さんの記事を参考に実装します。

qiita.com

 

▼CharacterMovementコンポーネント

RotationRateは180にしました。

▼クラスのデフォルト

 

ビヘイビアツリーに組み込むのでBTT_CustomMoveToというタスクを使用します。

Acceptance Distを100にして判定を甘くしている以外はそのまま利用させていただきます。

 

BTT_CustomMoveToは位置情報を元に移動するタスクなのでアクターを追いかける設定にしているMoveToタスクとはそのまま運用できないので修正します。

 

BTT_SetActionPointの修正

アクタキーからLocationKeyに変更します。

 

これでアクタへ移動するために移動先のアクタを渡していたのを、位置座標で指定できるようにしました。

 

音が鳴った時の挙動はそもそもLocationに向かうように運用していたので、そのまま入れ替えるだけで使えます。

 

プレイヤーを追いかける部分はこれまで通りMovetoで運用します。

 

▼全体像

 

実行してみましょう。

経路探索の表示とAIがいい感じに移動していたら成功です。

 

①見失ったキーの追加

BB_NPCを開きます。

bool型のキーLostPlayerKeyを作成します。

 

②コントローラーからキーの設定

BP_CustomAIControllerを開きます。

プレイヤーを見つけた分岐からLostPlayerKeyに見失ったらTrueにします。

 

③見失った位置を登録するタスクの作成

プレイヤーを最後に見た場所を設定するタスクをつくります。

名前はBTT_SetLostPlayerPositionにしました。

 

LocationKeyにプレイヤーの位置をセットするだけの簡単なタスクです。

④BTTClearKeyの改良

LostPlayerKeyをFalseにするためのタスクが必要ですが同じようなタスクを大量に作ると管理が大変なので同じタスクを使いまわせるようにします。

 

型に依存しないクリアを行うにはClearBackboardValueを指定します。

 

⑤ビヘイビアツリーに組み込み

 

まず聞こえたり見つけたりするよりも優先度はどちらも低いのでセレクターでまとめておきます。

Sequenceにデコレーターを追加してLostPlayerKeyで分岐を行います。

プレイヤーを探していることが分かるようにアイコンと色を設定します。

あとはプレイヤーの位置をセットして、ロストした位置に移動します。移動が完了したらLostPlayerKeyをクリア=falseにして再びこのSequenceが呼ばれないようにします。

 

実行してみましょう。
プレイヤーを見失ったらアイコンが変化して最後に見た場所に移動します。

移動中に再び視界内に入ったら追いかけます。

 

⑥+α もうちょい探すタスクを作る

最後に見た場所まで来てもプレイヤーは既にどこかに行ってしまっていることが多いでしょう。そこで見失った位置から一定の範囲内をランダムに移動できるようにします。

 

タスク名はBTT_SetRandomPositionとしました。

 

一定の距離からランダムな位置を取得するのは以下でできるのですが、もう少し高度な判定をしてみましょう。

 

以下の図のようにNPCを背にした範囲に移動してもプレイヤーがいる可能性が低いとします。その場合、このノードだけでは欲しい位置を取得することができません。

 

そこで内積を使うことで”いい感じの位置”になるまで再試行します。

EQSなどの機能でも実装できますが、今回は計算で行ってみたいと思います。

 

ココからは確認なので見るだけでも大丈夫です。

まず、ランダムな位置を300個作ります。

 

アクターの前ベクトルとランダム位置とNPCのベクトルを内積で計算して、使いやすいようにラジアンと度の変換を行います。InRangeでソートして結果を見てみましょう。 

 

このように前ベクトルから90度の範囲で分割されます。

 

MaxAngleを30にすると前方60度の範囲で分割できます。

 

ついでに最小範囲を除外しておきます。

 

これを使ってより優れた結果を厳選します。

こうして出来上がったタスクがこちらになります。

ビヘイビアツリーに組み込みます。



⑦スタック防止処理を入れる

NPCがスタックして到達できない場合の処理を入れます。

 

Move系のタスクにデコレーターのTimeLimitを追加します。

 

TimeLimitはノードに入ってから指定した時間を過ぎると失敗します。

Move系に入れることで20秒内に目的地に到着できなかったら失敗扱いになります。

失敗したら新しい目的地が設定されて移動を開始します。

 

▼全体像

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやTwitterのフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。