はじめに
この記事はK3 Advent Calendar 2024の7日目です。
https://adventar.org/calendars/10132
小金井祭2024で展示した3Dソウルライクアクションゲーム「Weapons」の敵AIの実装方法について話していきます。
「敵のAIが賢いのがすごい!]という感想を頂きましたが、実はそんなに複雑なことをやっていません。
簡単な実装でも結構賢い(ように見える)AIが作れるんだということを理解していただけると幸いです。
敵AIの行動指針
Weaponsの敵AIは、昨今話題のAIと違って学習を行うのではなく製作者が「こういう場合はこうしろ」という手順を指定して作るAIです。
よって、敵AIの行動の指針をまずは規定する必要があります。
以下のような行動指針をまずは考えました。
・何もないときは待機する
・プレイヤーを発見したら追いかける
・プレイヤーに十分近づいたら攻撃を開始する
・プレイヤーに攻撃されたら回避を行う
単純なルーチンですよね。
そして、この行動をUEのビヘイビアツリーで実行すると以下のようになります。
ビヘイビアツリーの挙動についての説明はネット上にあるため割愛しますが、大まかな流れはコメントに書いてある通りです。
定期的にプレイヤーとの距離と自分が攻撃されていないかを確認し、
①攻撃されていたら回避(最優先)
②プレイヤーを発見していて近くに居たら攻撃(次に優先)
③プレイヤーを発見していて近くに居なければ追いかける(その次に優先)
④何もなければ待機(最も優先度が低い)
これをやるコードになります。
ただ、このままだとプレイヤーの攻撃を全て的確に回避し、プレイヤーには慈悲の無い連撃を繰り出す最強のAIができてしまいます。
そうです。意外かもしれませんが、製作者が行動指針を決定するタイプのAIの場合、「愚かなAI」より「完璧なAI」を実現するほうが実は簡単なのです。
よって、「完璧なAI」にある程度の枷を付けて、「程よい賢さのAI」を作る作業をここから行っていきます。
AIに枷をつける
先ほどまでの敵AIの何が問題だったでしょうか。
④何もなければ待機
③プレイヤーを発見したら追いかける
ここは問題ないでしょう。むしろごく自然な行動と言えます。
①攻撃されていたら回避(最優先)
ここは問題です。人間と違って機械は正確な判断ができますので、プレイヤーの攻撃全てに対して的確に回避を行ってしまいます。攻撃が全く当たらない敵なんてクソゲーも良いところです。
②プレイヤーを発見していて近くに居たら攻撃
これに関しても短絡的です。近づいたら猛烈な連撃を浴びせられ、攻撃のチャンスがまるで無いようなAIとは戦う気になれません。ある程度「隙」をつくってあげる必要があります。
以上から、①、②の行動に対して一定の枷をかけてあげる必要があると分かります。
では、どのように枷をかけてあげれば良いでしょうか?
①に関しては簡単です。確実に回避されるのが問題なら、回避をしたりしなかったりすれば良い訳です。
そこで、回避を行う確率を設定してあげます。
こちらが、回避を行うタスクの詳細です。
回避を行うべきシチュエーションにおいて、敵アクタから回避確率を取得してランダムな値がそれ以下なら回避を行い、そうでなければ回避を行わないように設定します。
弱い敵の回避確率を低く設定し、強い敵の回避確率を高く設定すれば難易度調整にも利用することができます。
②に関しては、猛烈な連撃が問題な訳ですから、攻撃に対してクールタイムを設けることにします。
一度攻撃を行ったら、一定の期間攻撃を行わないように設定します。
ただ、クールタイムが一定では敵キャラがコンボ攻撃を行わなくなってしまったり、プレイヤーが敵の行動を読みやすくなって単調になってしまうので、クールタイムにもランダム性を持たせることにします。
こちらが、クールタイムを設定するタスクの詳細です。
敵アクタからクールタイムの範囲を取得し、そこに対して0~1のランダムな値を掛けることでクールタイムを設定します。クールタイムレンジが1秒で、ランダムな値が0.5なら0.5秒のクールタイムを設けるといった感じです。
これによって、連撃を行う際は行うし、隙ができる際はできるといった挙動が実現できます。
また、弱い敵はクールタイムレンジを大きくし、強い敵は小さくするというように難易度調整にも利用できます。
攻撃の部分について、クールタイムを入れるように改善したビヘイビアツリーがこちらになります。
Weaponsの敵AIについて行ったことは以上だけです。本当です。嘘みたいに単純ですよね?
まとめ
以上のように、まずは理想的な動きをするAIのルーチンを設定し、そこからランダム性を持った枷を付けてあげることでそれほどの労力を費やさずとも「程よい賢さ」を持ったAIをつくることが出来ます。
そして、そのランダム性に寄与するパラメータを簡単に調整可能にしてあげることで、難易度調整も同時に行えます。
さらに、Weaponsでは時間の都合上行えなかったですが、ランダムな値を取得するときの確率分布をいじってあげたり、状況に応じて違ったクールタイムや回避確率を持たせてあげたりなどさらに工夫をすることでより自然な挙動をするAIを作ることが出来ると思います。
①まず理想の動きをするAIのルーチンを考える
②そのAIに対してランダム性を持った枷を与えてあげる
こちらを意識すると、それほどの労力をかけずともある程度自然なAIを作ることができます。
是非みなさんの開発に活用してみてください!