UE5で敵を巡回させたい(ビヘイビアツリー)

※素人による記事の為、間違いがある可能性があります
※個人用備忘録ですが、何かご指摘ございましたらコメント頂けたらと思います

AI関連記事紹介


目標:下記を満たすAIを作る
・決まったルート巡回している
・プレイヤーを見つけると追ってくる
・見失うと巡回に戻る

公式のビヘイビアツリーチュートリアルを参考



AI周りの準備

・適当な場所にNPC関連を入れるフォルダを作成


・プレイヤーを作ったフォルダにコピーして、リネーム

名前はBP_ENAとしました


・フォルダ内にAIcontroller Behaviour tree Blackboardを作成


・BehaviourTreeとBlackboardを作成


・それぞれ
AIC_ENA
BT_ENA
BB_ENA

とリネーム


・Blackboardにキーを追加
 Player     プレイヤーとかその味方を格納
 PatrolLocation 巡回する地点
  ※公式チュートリアルではBool値で「Playerを見つけたかどうか」
  のブラックボードキーを作成していますが、無くてもいけます。


・NavmeshBoundsVolumeを配置、スケールをレベルに合わせる


・BehaviourTree を開いて任意の Blackboard が適用されているか確認
(BBが複数あると意図しないのが勝手に設定される事がある)


・AIcontrollerを開いて下記のように組みます

※なぜEvent begin playでは無く Event On Possess(AIcontrollerがCharacterを持った時のイベント)だったのかは詳しくは下記リンク参考


・AIPerceptionを追加、SenseConfigから視覚を追加


・基本中立のやつしかいないので、Neutralをオン

詳しくは別記事を参考↓


・準備は完了


Characterの準備

敵AIブループリントを開く
イベントグラフ内は全て削除


・カメラなどいらないコンポーネントは削除


・Max walk speedを120にしておきます。

画像の数値間違ってますね・・・


・Auto possess AI (下に説明あり)を設定
・AIcontrollerを指定する

・Auto possess AI  AIcontrollerがCharacterを持つタイミングを選べます

Placed in world      エディタで配置された時
Spawned         ノードでSpawnされた時
Placed in world or Spawned 上二つどっちも(これにしておく)

参考(リンク先の真ん中ちょい下)


プレイヤーBPを開く
Player タグを追加(tagと検索した方が早い)


・UE5グレイマンのアニメーションBPを開きます


・デフォルトのままだとNPCがアニメーションなくなるので画像のようにします。

詳しくは下記リンク↓



ビヘイビアツリーでロジックを組む

ビヘイビアツリーでは「コンポジット」ノードで流れを管理します

Selector   子ノードを左から順番に実行し成功したら終了
Sepuence  子ノードを左から順番に実行し失敗するまで続ける
SimplePrallel 2つのタスクを同時に実行


・Selectorで大きな分岐を作って、Sepuenceでタスクを実行させます
 なので以下の様に組んでリネームもします。

ビヘイビアツリーは右上の〇数字の順番で実行されます


・タスクノードを追加する
具体的に何をするのかあらかじめ用意されているのがタスクです

・Waitを追加、時間を1秒に。Rotate~はBlackboardkeyにPlayerを設定する


・ここで一旦敵キャラクターBPを開き、Use Controller Yaw をオンにしておきます(BTのRotate toタスクを使う時は必ずここをオンにする)


・新規カスタムタスクを2つ作成
BTT_SpeedUp
BTT_FindPatrolPoint
にリネーム


・下記の様にタスクを組みます
ChasePlayerのMove toを選択
BlackboardKeyをPlayerに


Patrol下のMove toの BlackboardKey は PatrolLocation を
Patrol下のWaitは WaitTime4秒 の RandomDeviationを1秒に
 (そうする事で±1秒ランダムで変化)


これでビヘイビアツリーは一旦完了


タスク SpeedUp を組む

ここではタスクSpeedUpから敵の速度を変える仕組みを作ります

 ビヘイビアツリーのタスク内で直接サブオブジェクト(キャラクター)
 のプロパティを変更するのは好ましくない(公式チュートリアル参考)
 らしいので、敵キャラクターBP内で関数を作成して
 タスクからFloat値を渡せるようにします。

・敵キャラクターBPの BP_ENA を開き、下記の様に設定


・Max walk speedと検索してノード追加、後は画像の通り

コンパイルして保存


・BTT_speedupタスクを開き、イベント Receive Execute AI を作成

Receive Abort AI  Decoratorによって中止されたときに呼ばれます
Receive Execute AI 
Taskが開始されるときに呼ばれます
Receive Tick AI   
Task実行中に呼ばれます
※AIがつかないイベントはAIcontroller以外によって実行された時用(?)


・下記の様に組む

ChaseSpeedのInstanceEditableをオンにしてBTから編集可能にする


・ビヘイビアツリー内でChaseSpeedが変更可能になっているか確認
 これでタスクを開かなくても速度を変更できます。




タスク Find Patrol Point を組む

ここでは巡回するルート地点を取得するロジックをタスクFindPatrolPointとして組んでいきます。
目標イメージ:PS1のメタルギアソリッドみたいに十字に巡回する敵
参考↓


まず巡回ルート地点をブループリントの変数として作ります

・右クリック > ブループリント > Actor で新規ブループリント作成
BP_PatrolRoute にリネーム


・BP_PatrolRoute 内で Vctor の配列変数を作成

Show3DWidgetをオンにするとビューポート上で見える


・BP_PatrolRouteを適当な位置にD&D、さっき作った配列変数を+で追加


・1つ目はそのまま、2つ目はパラメーターいじって移動させて選択できるようにし、任意の位置にビューポート上で直接動かします。


・画像のようにしました。

※3を0と同じ位置にする事によって一旦定位置に戻る事を表現してるのは
プログラム的には稚拙だが楽さが勝ったのだ。


・巡廻速度を設定します
 FindPatrolPointタスクを開き、Patrolspeed変数を作り、目ボタンをオン
 BP_ENAで作ったUpdateWalkSpeed関数を呼びます


・巡回地点の位置情報を得る為に、配列変数を取得します
 Patrol Route Array変数を取得したいが、別アクターの変数なので
 Get Actor of Class で BP_PatrolPoint を取得します


・PatrolRouteArrayから巡回地点の位置情報を取得してブラックボードキーに渡せるようにします。
①のGETで配列の何番目かの指定(integerによる)をしています
②の TransfomLocation は Tピン と Locationピン を足した値をワールド座標に変換してくれるので、巡回地点のワールド座標が取得できます。
③でブラックボードキー変数を作成して一旦位置情報を保管します(後でBT上でBBキーと結びつける)


・取り出す配列に1を足していき、最大になったら0に戻す処理を作ります
integer変数を作成PatrolIndexとリネーム、配列の何番目かを指定します
①で毎実行毎に1足します
②で配列のいくつあるのか取得します
③で配列のMAXよりは現在小さいかどうか判定します
 ※配列が0~5まであるとしたら LENGTH は6を返す為
  6番目は存在しない為、6を含めないように < を使用
④SelectInt は true であれば A を返し、false であれば B を返すので
⑤で配列の最後になったら0をPatrolIndexに入れて最初の地点に戻します。


・最終的にこんな感じになります


・ブラックボードキーに巡回地点の位置情報を渡します。


FindPatrolPointタスクは完了


他にも色々な位置の取得方法がありまつ



Playerを見つけるロジックを組む


・敵NPCの AIcontroller を開き
 On Target Perception Updated イベントを作成

On Perception Updated    知覚が働いてる時のイベント
                知覚したActorを返す
On Target Perception Updated 上と同じ、相手の情報を色々返す
On Component Activated    知覚がアクティブになった時
On Component Deactivated  知覚が非アクティブになった時

公式を参考


・Playerかどうか判定する
 ①Break AIstimulusで色々取得できるが、感知に成功したかどうか取得した

因みに①は小さくできる


・PlayerじゃなかったらブラックボードキーPlayerを空にする
set timer~~は○○秒まって実行できるノードです
①プレイヤーを見失ってから諦めるまでの時間を設定
②カスタムイベントを作成、適当にリネーム
③はブラックボードキーの名前

Set timerノードの解説は以下の記事で


・Playerだったら ブラックボードキーPlayerを設定
①は変数に昇格してもいい
②は先ほど作ったののコピペ
③でAIperceptionから取得したPlayerを設定

・こんな感じになる



プレイヤーを見つけたらChasePlayerを実行

ビヘイビアツリーでChasePlayerをプレイヤーを見つけた時だけ実行できるようにします。

・Blackboardデコレーターを追加する
ChasePlayerを選択 > 右クリック > デコレーター追加


・ブラックボードキーPlayerに値が設定されてれば実行させるようにする
Blackboardデコレーターはブラックボードキーに値が設定されてるかどうかを条件式にできます。
今回は「ブラックボードキーPlayerに値が設定されてれば実行」させたいので、画像の様にします。


詳しい説明はこちら


これで終わりです、Playして確認してみてください!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!疲れた!!!!!!


この記事が気に入ったらサポートをしてみませんか?