今回はAgentControllerとBehaviourTreeを使用して、プレイヤーを追いかけるAIエージェントの作り方について解説します。
Contents
事前知識
このチュートリアルには以下の知識が必要です。
- C#の基礎
- Unityマニュアル「スクリプト」
- ビヘイビアツリーの基礎
動作環境
このチュートリアルは、以下の環境で作成しております。
Unity | 2019.4.39f1 |
Arbor | 3.9.0 |
異なるバージョンを使用する場合は説明と異なる箇所があるかと思いますのが適宜読み替えてください。
チュートリアル用プロジェクトの準備
プロジェクトの作成
まずは、チュートリアル用にプロジェクトを作成してください。
プロジェクト名 | ArborTutorial05 |
テンプレート | 3D |
インポートするアセット |
|
プロジェクトの作成やArborのインポートについては「Arborを使用するための準備」を参照してください。
今回はStandard AssetsのCharactersも使用しますので、忘れずインポートしてください。
Standard Assets
Standard AssetsはAsset Storeからダウンロードします。
Unity公式がリリースしている無料アセットです。費用はかかりません。
- アセットストアで「Standard Assets (for Unity 2018.4) 」ページを開く。
- 「マイアセットに追加する」ボタンが表示されている場合はこのボタンをクリック。
- Unityに戻り、メニューから「Window > Package Manager」を選択。
- パッケージスコープドロップダウン(ツールバー左から2番目のドロップダウン)を「My Assets」に変更。
- 検索バーに「Standard Assets」と入力し、「Standard Assets (for Unity 2018.4) 」を選択。
- ダウンロードしていなければ、「Download」ボタンをクリック。
- 「Import」ボタンをクリック。
- Import Unity Packageダイアログでは全てのアセットを選択した状態で「Import」ボタンをクリック。
SimpleActivatorMenu.csを削除
インポートすると「Assets / Standard Assets / Utility / SimpleActivatorMenu.cs」でコンパイルエラーが発生します。
今回このスクリプトは使用しないため、SimpleActivatorMenu.csを削除してください。
シーンの作成
3Dマップの配置
まずは、3Dマップを配置します。
- Projectウィンドウから「Assets / Plugins / Arbor / Examples / Common / Prefabs / FloorObjectsプレハブ」をドラッグ。
- Hierarchyウィンドウへドロップ。
シーンの保存
一度シーンを保存します。
- Projectウィンドウで「Assets/Scenes」フォルダがない場合は作成。
- 上部メニューの「File > Save As」を選択。
- Scenesフォルダに「AgentScene.unity」という名前で保存。
NavMeshをベイクします。
- 上部メニューの「Window > AI > Navigation」を選択し、Navigationウィンドウを表示。
- Navigationウィンドウの「Bakeタブ」を選択。
- 「Bakeボタン」をクリック。
- シーンを上書き保存。
プレイヤーの作成
プレイヤーの配置
プレイヤーはStandard AssetsのThirdPersonControllerプレハブをそのまま使います。
- Projectウィンドウから「Assets/ Standard Assets / Characters / ThirdPersonCharacter / Prefabs / ThirdPersonControllerプレハブ」をドラッグ。
- Hierarchyウィンドウへドロップ。
- GameObject名をPlayerに変更。
- Transformを以下のように変更。
Position | -5, 0, -5 |
カメラの設定
カメラがPlayerを注視するようにします。
- MainCameraオブジェクトを選択。
- Transformを以下のように変更。
Position | 0, 10, -30 |
- Cameraを以下のように変更。
Field of View | 40 |
- 「Add Component」ボタンをクリック。
- コンポーネント選択ウィンドウから「Arbor > ArborFSM」を選択。
- 「Open Editor」ボタンをクリックしArbor Editorを開く。
- グラフ上を右クリック。
- メニューから「ステート作成」を選択。
- ステート名を「Look At Player」に変更して確定。
- Look At Playerステートの設定アイコンをクリック。
- メニューから「挙動追加」を選択。
- 挙動選択ウィンドウから「GameObject > LookAtGameObject」を選択。
- LookAtGameObjectを以下のように変更。
Target | Player オブジェクト |
Apply Late Update | チェック |
エージェントの作成
エージェント用キャラクターの配置
キャラクターを配置します。
- Projectウィンドウから「Assets/Standard Assets/Characters/ThirdPersonCharacter/Models/Ethanモデル」をドラッグ。
- Hierarchyウィンドウへドロップ。
- Transfromを以下のように変更。
Position | 5, 0, 5 |
- Animatorを以下のように変更。
Controller | Assets / Standard Assets / Characters / ThirdPersonCharacter / Animator / ThirdPersonAnimatorController |
- 「Add Component」ボタンをクリック。
- コンポーネント選択ウィンドウから「Navigation > NavMeshAgent」を選択。
AgentController
AgentControllerとは、NavMeshAgentでの移動とAnimatorの制御を行うArborに組み込まれているコンポーネントです。
ArborFSMやBehaviourTree上で、Agent系スクリプトを使用することで移動させることができます。
詳細は「AgentController」を参照してください。
AgentControllerの追加
- HierarchyウィンドウでEthanオブジェクトを選択。
- Inspectorウィンドウの「Add Component」ボタンをクリック。
- コンポーネント選択ウィンドウから「Arbor > Navigation > AgentController」を選択。
AgentControllerの設定
AgentControllerの設定をInspectorで行っていきます。
- AgentControllerを以下のように変更。
Agent | EthanオブジェクトのNavMeshAgent |
Animator | EthanオブジェクトのAnimator |
Speed Parameter | Forwardパラメータ |
Speed Damp Time | 0.1 |
Turn Parameter | Turnパラメータ |
Turn Damp Time | 0.1 |
AIの作成
エージェントのAIを作成していきます。
BehaviourTreeの追加
- Ethanオブジェクトを選択していない場合は、Hierarchyウィンドウで選択しておく。
- 「Add Component」ボタンをクリック。
- コンポーネント選択ウィンドウから「Arbor > BehaviourTree」を選択。
Waypointを巡回するアクション
Waypointを巡回するアクションを追加します。
Waypointの作成
まずは、シーンにWaypointを追加します。
Waypointはシーンに配置した経路ポイントを管理するコンポーネントです。
詳細は「Waypoint」を参照してください。
- Hierarchyの+ボタンをクリック。
- メニューから「Arbor > Waypoint」を選択。
- Waypointオブジェクトの子に空のGameObjectを4つ作成。
- 名前をそれぞれ「Point1」「Point2」「Point3」「Point4」に変更。
- 各Pointオブジェクトのアイコンをラベルタイプに変更。
- WaypointのPointsにPoint1~4を設定。
- Point1のTransformを以下のように設定
Position | 10, 0, 10 |
- Point2のTransformを以下のように設定
Position | -10, 0, 10 |
- Point3のTransformを以下のように設定
Position | -10, 0, -10 |
- Point4のTransformを以下のように設定
Position | 10, 0, -10 |
シーンウィンドウで上から見ると以下のようになります。
AgentMoveOnWaypointアクションの追加
AgentMoveOnWaypointアクションはWaypointに沿ってAgentを移動させるアクションです。
詳細は「AgentMoveOnWaypoint」を参照してください。
- HierarchyウィンドウでEthanオブジェクトを選択。
- BehaviourTreeの「Open Editor」ボタンをクリックしArborEditorを開く。
- Rootノードの下部にあるスロットをドラッグし、Rootノードの下側でドロップ。
- メニューから「アクション作成」を選択。
- アクション選択ウィンドウから「Agent > AgentMoveOnWaypoint」を選択。
- 名前はそのままで確定。
AgentMoveOnWaypointの設定
- AgentMoveOnWaypointを以下のように変更。
Speed | 0.5 |
Waypoint | Waypointオブジェクト |
Type | Cycle |
Stopping Distance | 0.5 |
実行確認
実行して確認してみましょう。
プレイヤーの位置に関係なくEthanは決まったルートを巡回し続けます。
Playerに近づくアクション
Playerがある程度近くにいる場合は接近させましょう。
Selectorコンポジットの追加
Selectorは「成功」を返す子ノードを見つけるまで左から順に子ノードを実行するコンポジットです。
詳細は「Selector」を参照してください。
- AgentMoveOnWaypointアクションをRootノードの右下に移動。
- Rootノードの下部にあるスロットをドラッグし、Rootノードの下側でドロップ。
- メニューから「コンポジット作成」を選択。
- コンポジット選択ウィンドウから「Selector」を選択。
SelectorをAgentMoveOnWaypointに接続
- Selectorノードの下部にあるスロットをドラッグ
- AgentMoveOnWaypointノードの上部スロットに接続。
AgentMoveToTransformアクションの追加
AgentMoveToTransformはAgentをTargetに近づくように移動させるアクションです。
詳細は「AgentMoveToTransform」を参照してください。
- Selectorノードの下部にあるスロットをドラッグし、AgentMoveOnWaypointノードよりも左側でドロップ。
- メニューから「アクション作成」を選択。
- アクション選択ウィンドウから「Agent > AgentMoveToTransform」を選択。
AgentMoveToTransformの設定
- AgentMoveToTransformを以下のように変更。
Speed | 0.6 |
Target Transform | Playerオブジェクト |
Stopping Distance | 2 |
距離判定デコレータの作成
今回はすでにあるデコレータを使用せず、スクリプトも自作して距離判定を行ってみましょう。
- ProjectウィンドウでAssetsフォルダを選択。
- +ボタンをクリック。
- メニューから「Arbor > BehaviourTree > Decorator C# Script」を選択。
- スクリプト名を「MyDistanceCheck」にして決定。
- メニューから選択すると自動的に名前入力モードになります。
その状態で名前を入力して確定してください。 - デフォルト名のまま一度確定してしまったり、名前を間違って後から変更した場合はクラス名も変更する必要があります。
コードの修正箇所がわからない場合は、一度スクリプトを削除して作り直してください。
- メニューから選択すると自動的に名前入力モードになります。
- MyDistanceCheckファイルをコードエディタで開く。
- 以下コードを入力。
内容を簡単に説明すると以下のようなコードとなっています。
- _Targetに相手のTransformを指定。
- _Distanceに判定する距離を指定。
- OnConditionCheckメソッドで、自身のtransformと_Targetとの距離を計算し、_Distance以下であればtrueを返す。
MyDistanceCheckによる距離判定
距離によりAgentMoveTransitionノードを実行させるためMyDistanceCheckを設定しましょう。
- AgentMoveToTransformノードの設定アイコンをクリック。
- メニューから「デコレータ追加」を選択。
- デコレータ選択ウィンドウから「Scripts > MyDistanceCheck」を選択。
- MyDistanceCheckを以下のように変更。
Abort Flags(Nothingになっているドロップダウン) | Everyting |
Target | Playerオブジェクト |
Distance | 10 |
実行確認
実行して確認してみましょう。
- プレイヤーを操作してEthanオブジェクトの10m以内に近づくとEthanもプレイヤーに近づいてきます。
- 逆にプレイヤーが10メートルを離れると巡回に戻ります。
このように、ノードは左から順に実行され、デコレータは実行可能か判定を行い中断や割り込みを制御するものと覚えると良いでしょう。
次のステップ
今回はAgentControllerとBehaviourTreeを使用してPlayerに近づくAIを作成しました。
実際のゲームでは、Playerにある程度近づいたあと攻撃するなどさらにアクションを取るケースがほとんどです。
「Ethanをより良いAIにするにはどう作ったらいいか」をあなたへの課題として、このチュートリアルを終わります。
攻撃アクションのヒント
- AgentMoveToTransformはStoppingDistanceまで近づくと「成功」として実行終了します。
- 子ノードが「成功」を返す限り左から順に子ノードを実行するには「Sequencer」を使用します。
- コンポジットノードにもデコレータを追加でき、AbortFlagsにSelfフラグが付いている場合は、デコレータの条件が一致する限り子ノードを実行します。
- アクションに「SubStateMachine」を用いれば子ステートマシンを実行させることができます。
- ArborFSMでは「EndStateMachine」を用いれば親グラフに結果を返せます。
- ステートマシンによる攻撃の作り方は「2DSTGの敵を作ろう」が参考になるでしょう。
例えば以下のような感じです。- 弾丸用のプレハブを用意する。
- 子ステートマシンでは一定間隔で「InstantiateGameObject」を使って弾丸を発射する。
- Ethanには攻撃モーションがないので必要であれば別途用意しておく必要があります。
- ヒット&ダメージ判定はここでは説明を省きます。Unity Learnなどを参考にしてください。
- 弾丸発射やヒット判定などはUnity自体にも慣れていない場合は複雑で難しいかもしれません。
まずは仮でAttackというActionBehaviourスクリプトを作成してログを出すだけなど、できるところからやってみてください。
ActionBehaviourスクリプトについては「ActionBehaviourスクリプトの書き方」を参考にしてください。