はじめに
今回はCorgi EngineのCPUの敵AIの実装について確認してみました。
AIを設定する上で、用意するマップの形も重要と感じました。
Advancedの方は調査時間がまだ取れておらず、後ほど追加するかもしれません。
AIスクリプトの使い方に設定方法を記載しています。
LegacyAI、AdvancedAIに各思考のパラメータについてまとめました。
使用アセット
Corgi Engine - 2D + 2.5D Platformer
作業環境
Unity 2019.4.16f1
- はじめに
- 敵AI設定の場所
- AIのスクリプト
- AIスクリプトの使い方
- LegacyAI
- AdvancedAI
- Advanced AI一覧
- AIAction
- AIDecision
- AIDecisionDetectTargetLine
- AIDecisionDetectTargetRadius
- AIDecisionDistanceToTarget
- AIDecisionGrounded
- AIDecisionHealth
- AIDecisionHit
- AIDecisionLineOfSightToTarget
- AIDecisionNextFrame
- AIDecisionRandom
- AIDecisionTargetFacingAI
- AIDecisionTargetIsAlive
- AIDecisionTargetIsNull
- AIDecisionTimeInState
- AIDecisionTimeSinceStart
- おわりに
敵AI設定の場所
Assets/CorgiEngine/Demos/Corgi3D/NewCorgi3Dのシーンで確認しました。
NewCorgi3D / Level / Enemies / Bear3D に敵がいます。
Bear3Dのプレハブを開くと、AIWalkというコンポーネントが設定されています。
これがAIの設定となります。
AIのスクリプト
CorgiEngineで用意されているAIはLegacyフォルダに入っている簡易的な思考と、状態を判断して行動を切り替えるAdvancedフォルダに入っている思考処理があります。
ただ歩いて崖を判定して判定等簡素な設定はLegacyフォルダのScriptを設定することで対応ができます。
Advancedの方は、設定は複雑になりますがHPが半分以下になったらダッシュを使用するようになる等、条件を見て行動を切り替えることができるようになっています。
AIスクリプトの使い方
コーギエンジンのAIスクリプトにはLegacy, Advancedの2種類で設定方法があります。
CorgiControllerのついているコンポーネントに思考コンポーネントを追加することで設定できます。
Legacy ... 簡単な思考設定。簡易な動きの場合はこちらが便利です。
AIWalk(歩き), AIFollow(追従), AIShootOnSight(射撃)の三つが用意されいます。思考するコンポーネントを追加すれば機能します。
Advanced ... AIBrainコンポーネントをベースに条件と行動を組み合わせて思考を設定します。詳細な動きが可能な分設定が多くなります。
Legacy AI の設定方法
必要な思考を追加すればOKです。
動かないCPUの場合、設定をしないといったことも選択肢となります。
移動を行う場合、AIWalkか、AIFollowを設定し
射撃攻撃が必要な場合は、AIShootOnSightを追加します。
移動が必要なく、射撃を行う場合はAIShootOnSightのみ設定します。
各思考の詳細はLegacyAIの項目をご確認ください。
Advanced AI の設定方法
Advanced AIでは、AIBrainにAIAction(行動)、AIDecision(条件)を設定し思考を行います。
AIAction, AIDecisionの詳細パラメータはAdvancedAIにまとめています。
ここでは「2秒停止」→ 「2秒歩行」を繰り返す設定にて設定の仕方を紹介します。
Assets/CorgiEngine/Demos/Corgi3D/Prefabs/AI/Bear3Dにて設定を行います。
①AIWalkのスクリプトを外す
②AIBrainのスクリプトを追加
③AIActionDoNothingを追加 ... 停止の行動
④AIActionPatrolを追加 ... 歩行の歩行
パラメータ設定を調整し、穴が見つけたら反転するようにしました。
⑤AIDecisionTime in Stateを追加
2秒で条件を満たすようにしました。
①AIBrainのStatesの+ボタンを遷移する状態の数である2回押します。
②Actions, Transitionsをそれぞれ1回づつ押します。
行動や、条件を複数設定する場合はその数に合わせます。
③State Nameの設定を行います。今回はWait(待機)、Walk(歩行)を設定します。
④WaitのActionsにはAIActionDoNothingをドラッグで設定
WalkのActionsにはAIPatrolをドラッグで設定
WaitのTransitionsにAIDecisionTime in Stateを設定し、TrueStateに「Walk」を設定
WalkのTransitionsにAIDecisionTime in Stateを設定し、TrueStateに「Wait」を設定
起動時は一番上の状態が実行され、対象の状態のActionsが実行され続けます。
実行中Transitionsの判定が行われ、条件を満たした(/満たしていない場合)に、遷移先の状態があれば、状態の変更が行われます。
今回の場合は下記状態が繰り返される形となっています。
①Wait状態で待機を行う
②2秒後の判定が満たされたタイミングでWalkへ
③Walk状態で歩行を行う
④2秒後の判定が満たされたタイミングでWaitへ
設定方法は以上となります。
LegacyAI
簡単な設定で思考の設定ができます。
単純な動作に対応しています。
Legacy
AIWalk
歩く動作の思考
・歩く
・(設定次第)壁にぶつかったら反転する。
・(設定次第)落下を避ける。
・MoveOnSight にてプレイヤーの後ろを歩いてくる仲間の設定も可能
※マップの床の高さに気を付けて設定が必要な場合があります。
WalkBehaviour ... 動作の仕方
Patrol:条件なく歩行
MoveOnSight:目標を「見ている」場合のみ歩行
Obstacle Detection
壁にぶつかった時にキャラの向きを変えるべきかどうか、穴を避けようとするかどうか設定
ChangeDirectionOnWall ... trueの場合、壁にぶつかったときに方向を反転
AvoidFalling ... trueの場合、落下を避けようとする
HoleDetectionOffset ... 穴の検出を考慮する距離
HoleDetectionRaycastLength ... 穴を検出をするためのキャラの大きさ
Move on Sight
動作がMove On Sightに設定されている場合の設定、「視野」距離の設定
ViewDistance ... AIがターゲットを見ることができる最大距離
StopDistance ... 移動を停止する目標からの水平距離。その距離と歩行距離の間で徐々に減速していきます。
MoveOnSightRayOffset ... レイキャストの原点に適用するオフセット(デフォルトはオブジェクトの位置)
MoveOnSightLayer ... ターゲット対象となるレイヤー
MoveOnSightObstaclesLayer ... 視界障害物対象となるレイヤー
Patrol, AvoidFalling = true の場合
Patrol, AvoidFalling = false の場合
Patrol, AvoidFalling = true, HoleDetectionOffset x = 2の場合
NG例 Patrol, AvoidFalling = true, HoleDetectionRaycastLength = 1の設定
床があるかどうかの判定で誤った判定をしてしまっている。
Patrol, AvoidFalling = true, HoleDetectionRaycastLength = 0.3
MoveOnSight, StopDistance = 1, MoveOnSightLayer = Playerを設定
MoveOnSight, AvoidFalling = false, StopDistance = 1, MoveOnSightLayer = Playerを設定
AIShootOnSight
CharacterHandleWeapon とセットで使用する。
プレイヤーが視界にいる間、武器を使用します。←プレイヤーが視界にいない場合、攻撃できません。
条件を見ず攻撃したい場合は、Advancedの設定を行う必要があります。
攻撃動作の思考
・正面にターゲットが入った場合、武器を使用します。
ShootDistance ... AIがプレイヤーに向けて撃つことができる最大距離
RaycastOriginOffset ... 視界の判定に使用するオフセット値
TargetLayerMask ... 攻撃対象のレイヤー
敵用の武器の作成
Bear3Dに装備できる武器を用意します。
Assets/CorgiEngine/Demos/Minimal/Prefabs/Wepons/RegularWepons にある
MinimalShotgun をコピーし MinimalShotgunEnemy としました。
Bear3D AI 向けに2点変更しています。
①ProjectaileWeapon の Position/WeponAttachmentOffset.y を 0.5
→Bear3Dは背が低いため発射と同時に床に当たってしまうことを防ぎます。
②WeaponAim の AimControlを Script
→キーボードやパットで入力で操作するわけではないため変更しました。
Bear3D に、AIShootOnSightを追加し、TargetLayerMaskにPlayerを設定
CharacterHandleWeaponのInitialWeaponに用意した、MinimalShotgunEnemyを設定
上下の認識検証
AIWalk 無効化, AIShootOnSight のShotDistance = 20
AIFollow
メインプレイヤーのキャラクターに追従させます。
対象キャラについているコンポーネントで追加動作
CharacterRun ... ターゲットから離れているときに走ろうとします。
CharacterJetpack ... 障害物の上をジェットパックをしようとします。
CharacterJump ... 障害物の上をジャンプしようとします。
Distances
RunDistance ... 走り出す距離。プレイヤーとの水平距離で判定
WalkDistance ... 歩き出す距離。プレイヤーとの水平距離で判定
StopDistance ... 移動を停止する距離。プレイヤーとの水平距離で判定
JetpackDistance ... ターゲットが上上空にある場合にジェットパッカー使用を開始する垂直方向距離
Bear3D にジャンプ能力付加
AIWalkを削除、AIFollow, CharacterJump を追加しました。
(パラメータは変更していません)
AdvancedAI
状態を判断し、行動を設定できるようになっています。
AIBrain に AIAction(行動) / AIDecision(条件)を設定し思考を組み立てます。
Advanced AI一覧
行動 / 条件 | 動画 |
---|---|
武器の切り替え |
|
待機 |
|
飛行 |
|
ターゲット方向へ飛行 |
|
ジャンプ |
|
フィードバック実行 |
|
ターゲットから離れる |
|
追跡 |
|
歩行 |
|
拡張機能付き歩行 |
|
射撃 |
|
思考切り替え |
|
スクリプト処理呼び出し |
|
直線で視野判定 |
|
円で視野判定 |
|
ターゲットとの距離で判定 |
|
地面に接触しているか判定 |
|
体力で判定 |
|
指定回数で判定 |
|
ターゲットとの間に遮るものがあるか判定 |
|
次のフレームtrue |
|
乱数で判定 |
|
ターゲットに見られているか判定 |
|
対象が生存しているか判定 |
|
対象がnullか判定 |
|
状態に入ってからの時間で判定 |
|
シーンに入ってからの時間で判定 |
AIAction
AIActionChangeWeapon
武器を切り替えます。状態に入った際に一度切り替わりが行われます。
HPが少なくなったら攻撃方法が変わるなどに使えそうです。
NewWeapon ... 切り替える武器
射撃状態に入ってから2秒後に武器を入れ変えるようにしました。
切り替えたタイミングでジャンプを入れています。
↑の動画で設定している項目になります。設定は多岐に渡るため重要なとこのみ載せています。ご不明な点がありましたらツイッターから問い合わせお願いします。
AIActionDash
CharacterDash とセットで使用する。
ダッシュ1度行います。
CharacterDashを付加し、AIActionPatrol 2秒後にダッシュした場合
...勢いよく飛んでいきます。。
CharacterDashの勢いを抑え、歩きの時間を調整しました。
徐々に位置がずれますね。。高低差が激しいところでのダッシュは調整が大変そうです。平坦なマップや、一発の突撃、ボス部屋での行動などうで使えそうです。
↑一つ上の動画のために設定したパラメータ、ポイントとして、AIDecsionTime in State を2つ追加し、歩行時は1.5秒、ダッシュ時は0.5秒で状態を切り替わるようにしています。
ダッシュ状態から切り替えない場合、ずっとダッシュを繰り返します。
動きが止まっているのは思考ではなく、キャラクター動作としての停止となります。
AIActionDoNothing
何もせず待機です。
プレイヤーが視界に入るまで待機などに使えそうです。
待機です。
AIActionFlyPatrol
CharacterFly, MMPath とセットで使用する。
ターゲットの方向に指定された最小距離まで飛行させる。(壁や穴にぶつかるまで飛ぶ)
MMPathによる飛行ルートの指定が必要です。
ChangeDirectionOnObstacle ... trueの場合、障害物に当たった時に向きを反転
2秒ごとに待機と飛行を繰り返します。MMPathの指定で右上に移動するようにしました。
↑の動画での設定主要部。
CharacterFlyはAlwaysFlying = trueで常に飛行状態にしています。
飛行状態ではない場合は動けません。
MMPathで飛行ルートの設定を行います。
AIActionFlyTowardsTarget
CharacterFly とセットで使用する。
ターゲットの設定が必要です。
キャラクターをターゲットの方向に指定された距離まで飛行させる。
MinimumDistance ... ターゲットとの距離
AIActionFlyTowardsTargetのMinimumDistance = 2の設定
AIActionFlyTowardsTargetのMinimumDistance = 0の設定
AIActionJump
CharacterJump とセットで使用する。
設定回数のジャンプを行います。
NumberOfJumps ... ジャンプ回数
待機、ジャンプを繰り返す設定
↑の動画で行った設定
AIActionMMFeedbacks
MMFeedbacksを再生します。
TargetFeedbacks ... 再生するMMFeedbacks
OnlyPlayWhenEnteringState ... falseの場合、フィードバックはPerformActionごとに再生(デフォルトでこの状態の間、毎フレーム再生される)
AIActionMoveAwayFromTarget
CharacterHorizontalMovementでターゲットから離れるように移動させます。
MinimumDistance ... ターゲットとの距離
AIActionMoveTowardsTarget
CharacterHorizontalMovementでターゲットの方向に移動させます。
ターゲットの設定が必要です。
MinimumDistance ... ターゲットとの距離
MinimumDistance = 1にて設定、壁の判定がなくつまっています。
↑の動画の主要部。ターゲットの設定はAIDecisionDetectTargetRadiusにて行っています。
AIActionPatrol
壁や穴にぶつかるまで移動します。
Obstacle Detection
ChangeDirectionOnWall ... trueの場合、壁に当たった時、向きを反転
AvoidFalling ... trueの場合、落下を避ける
HoleDetectionOffset ... 穴の検出を考慮する距離
HoleDetectionRaycastLength ... 穴を検出をするためのキャラの大きさ
AvoidFalling = true, HoleDetectionOffset.x = 1, HoleDetectionRaycastLength = 1
AvoidFalling = false
AIActionPatrolWithinBounds
AIActionPatrol を継承。キャラクターが超えられない左右の境界線を定義できる。
Obstacle Detection
ChangeDirectionOnWall ... trueの場合、壁に当たった時、向きを反転
AvoidFalling ... trueの場合、落下を避ける
HoleDetectionOffset ... 穴の検出を考慮する距離
HoleDetectionRaycastLength ... 穴を検出をするためのキャラの大きさ
Bounds
BoundsMethod ... 境界の判定方法
BasedOnOriginPosition ... 配置位置を基準
BasedOnStateEnterPosition ... 状態に入った時の位置を基準
BoundsExtentsLeft ... 左側の最大距離
BoundsExtentsRight ... 右側の最大距離
BoundsMethod = BasedOnOriginPosition, BoundsExtentsLeft = 0,
BoundsExtentsRight = 2 の設定で、2秒ごとに待機、移動を繰り返す。
AIActionShoot
CharacterHandleWeapon とセットで使用する。
ターゲットの設定が必要です。
使用できる武器は ProjectileWeapon が対象です。
武器を使って撃つ行動。武器がオートの場合、その状態を抜けるまで撃つことができ
セミオートでは1回撃ちます。武器にWeaponAimコンポーネントが付いている場合は、キャラクターをターゲットの左右に向けて照準を合わせます。
FaceTarget ... trueの場合、射撃時にターゲットを左右に向けます
AimAtTarget ... trueの場合、射撃時にターゲットを狙います
TargetOffset ... 照準時にターゲットの位置に適用されるオフセット
セミオート銃で確認、ターゲットの設定にはAIDecisionDetectTargetRadiusを使用しました。セミート銃の場合は1状態につき1発しか発砲しないようです。
↑の動画の設定はこちらです。使用した武器は AIShootOnSight の説明で使用したものです。
武器の設定をオートに切り替えました。
Shoot状態である限り撃ち続ける挙動となります。
条件をみて別状態にし解除する必要がありそうです。
オート設定はProjectileWeaponのTriggerModeで設定ができます。
AIActionSwapBrain
実行時にAIBrainを入れ替える。
NewAIBrain ... 入れ替える思考
AIActionUnityEvents
このアクションは、UnityEventのトリガーに使用されます。
TargetEvent ... 実行されるUnityEvent
OnlyPlayWhenEnteringState ... falseの場合、UnityイベントはPerformActionごとに実行されます(デフォルトではこの状態にある間はすべてのフレームでトリガーされます)
AIDecision
AIDecisionDetectTargetLine
TargetLayerレイヤーマスク上のオブジェクトが視線に入った場合にtrueを返す。
また、対象をターゲットとして設定する。
この場合、視線は実際の線になります(レイキャスト)。
また、レイの原点のオフセットと、それをブロックする障害物レイヤーのマスクを指定することもできます。
DetectMethod ... 検出方法
DetectionDirection ... 検出方向(Front 前方, Back 後方, Both 前後)
RayWidth ... キャストするレイの幅 (WideRay モードのみの場合)
DetectionDistance ... 射程距離
DetectionOriginOffset ... レイに適用するオフセット
TargetLayer ... ターゲットを検索したいレイヤー
ObstaclesLayer ... 障害物が設定されているレイヤーを指定
DetectMethod = Ray, DetectionDistance = 10, TargetLayer = Playerの場合、正面に入ったタイミングでtrueを返す。
DetectMethod = Ray, DetectionDistance = 10, TargetLayer = Player,
Obstacles = Platforms ← 壁ブロックのレイヤー
壁で視界を遮る設定を設定した場合。壁越しには判定されない
DetectMethod = Ray, DetectionDistance = 10, TargetLayer = Player,
Obstacles = Nothing
壁で視界を遮る設定をしなかった場合、壁越しも判定が行われる。
AIDecisionDetectTargetRadius
TargetLayerのオブジェクトが半径内にあればtrueを返す。
対象をターゲットとして設定する。
Radius ... 検索する半径
DetectionOriginOffset ... 探索円の中心
TargetLayer ... ターゲット対象のレイヤー
AIDecisionDistanceToTarget
ターゲットが指定範囲内であればtrueを返す。
ComparisonMode ... 距離の比較に使用するメソッド
Distance ... 判定距離
AIDecisionGrounded
地面に接地している場合trueを返す。
GroundedBufferDelay ... 地面にいる時間(秒単位)、この指定分判定を無視する
AIDecisionHealth
ライフ条件が満たされた場合true返します。
TrueIfHealthIs ... 比較方法
HealthValue ... 比較する値
OnlyOnce ... この判定は一度だけか
AIDecisionHit
指定回数条件が満たされた場合trueを返す。
NumberOfHits ... true を返すのに必要なヒット数
AIDecisionLineOfSightToTarget
このAIとターゲットの間に遮るもののない場合trueを返す。
ObstacleLayerMask ... 視界を遮る障害物として考慮するレイヤーマ
LineOfSightOffset ... 適用するオフセット
追跡の設定でプレイヤーとの間に壁がある場合ジャンプするように設定
AIDecisionNextFrame
この決定がオンになっている状態に入るとtrueを返す。
ジャンプした後、もとの状態に戻すように使用
ジャンプを行ったら元の状態に戻し、次の判定待ちとしています。
AIDecisionRandom
乱数を判定して、結果がオッズ値以下であれば真を返します。
TotalChance ... 試行値
Odds ... 判定するオッズ
AIDecisionTargetFacingAI
ターゲットがこのキャラクターに向いている場合trueを返す。
AIDecisionTargetIsAlive
ターゲットが生存している場合trueを返す。
AIDecisionTargetIsNull
ターゲットの設定がnullの場合trueを返す。
AIDecisionTimeInState
Brainがこの決定の状態になってから指定された時間(秒単位でminとmaxの間でランダムに選ばれた値)が経過した後に真を返します。何か他のことをしてからX秒後に何かをするときに使います。
AfterTimeMin ... 真を返すまでの最小持続時間を秒単位で指定します。
AfterTimeMax ... 真に戻るまでの最大持続時間を秒単位で指定します。
AfterTimeMin = 1, AfterTimeMax = 1を設定した場合、1秒でtrueとなります。
AfterTimeMin = 1, AfterTimeMax = 3を設定した場合、対象の行動に移った際に1秒~3秒の間でランダムに決まり。その時間後trueとなります。
AIDecisionTimeSinceStart
シーンがロードされてから指定された期間 (秒単位) が経過した後に true を返す。
AfterTime ... 真を返すまでの時間 (秒単位)
おわりに
AI向けのアセットは色々ありますが、CorgiEngineに入っている仕組みでもそれなりのことは出来そうだと感じました。すごく凝ったものを作る場合は別の手法を含め検討の必要がありますが、一度CorgiEngineの仕組みを使ってみようと思います。
今後も記事アップしていきたいと思います。