AI Planner入門


# はじめに。

本記事ではUnity Labsにて開発中のゲームAIライブラリ **AI Planner** について記載していきます。

2020年11月28日に行われたオンライン勉強会にてこのライブラリについて紹介をする機会を頂きましたが、これから挑戦する人のガイドとなるように登壇で話しました内容に補足を加えて整理をしておきたいと思います。

[ろっさむさん](https://qiita.com/4_mio_11)主催で行われたこのイベントについてはイベントページをご覧ください。
*[【オンライン開催】Game AI Tech #1](https://edge.connpass.com/event/192733/)*
[<img src="https://connpass-tokyo.s3.amazonaws.com/thumbs/a6/79/a679566b536ff72f5ca04c0ced5ee2d8.png" width=500>](https://edge.connpass.com/event/192733/)

登壇時のスライドも公開していますので本記事と合わせて参照頂ければと思います。
*[AI Planner入門 - Road of kanzen ni rikaishita.](https://docs.google.com/presentation/d/12FF8yWWD5rs76H6AV0jNs46vjBm9I2_W_YoU2_WFDzg/edit#slide=id.p)*
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/9fd4114c-8a64-9a3e-2f41-cc0e586f4909.png" width=500>](https://docs.google.com/presentation/d/12FF8yWWD5rs76H6AV0jNs46vjBm9I2_W_YoU2_WFDzg/edit#slide=id.p)
 

# AI Plannerとは。

（前述のとおり）AI PlannerはUnity公式で開発中のゲームAIライブラリで、「ゴール指向プランニング」であること「DOTSベース」であることが大きな特徴となっています。

- 公式マニュアル
*[About AI Planner](https://docs.unity3d.com/Packages/com.unity.ai.planner@0.2/manual/index.html)*

### Changelog

20202年11月3日にアップデートより【 0.2.4-preview.3 】となりクラス名や利用方法などの変更が入ったほか、Unityの必須バージョンも2019.2から2020.1.2fに上がっています。

- *[Changelog](https://docs.unity3d.com/Packages/com.unity.ai.planner@0.2/changelog/CHANGELOG.html)*

### Unite講演

日本では殆ど紹介されていない印象ですが海外では2017年から3年連続でUniteにてセッションがあったりします。

- (Unite Austin 2017) *[Unity Labs Behavioral AI Research](https://www.youtube.com/watch?v=78nhJNPS0vA)*
- (Unite Los Angeles 2018) *[AI for behavior: Advanced research for intelligent decision making]
(https://www.youtube.com/watch?v=ZdN8dDa0ff4)*
- (Unite Copenhagen 2019) *[How to generate game character behaviors using AI and ML - Unite Copenhagen](https://www.youtube.com/watch?v=2M3ytOo7LQQ)*

### PackageManager提供の新機能で遊ぼう 〜AI Planner編〜

また日本語で見られる数少ない資料としてユニティ・テクノロジーズ・ジャパン公式セミナー配信であるUnityステーションでAI Plannerを取り上げている回があります。

- *[PackageManager提供の新機能で遊ぼう 〜AI Planner編〜（6月25日号）](https://www.youtube.com/watch?v=DqWzad-FIZk)*

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/465d93f7-c436-aa02-80ab-73aa0880e185.png" width=500>


プランニングの概要からセットアップまで動画で説明されており、AI Plannerについて知りたい方は最初に見ておくとセットアップのイメージが付くと思います。

但し使用しているバージョンが【 0.2.3 】なので最新バージョンとは操作方法が一部違うところがありますので注意してください。

### 公式のサンプル

公式のサンプルは3種類ありAI Plannerの可能性を感じさせるのに十分な出来となってます。

- EscapeRoom
３つの駒が協力して部屋を脱出

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/870289fd-98da-0180-1c0a-4f99067cab13.png" width=500>

- Match3
色を合わせて消す2Dパズル

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/4027f99a-1179-e92f-78c7-dd6fd2d31158.png" width=500>

- VacuumRobot
ル〇バ似のロボットがごみ集め

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/cc7b3eb3-4c09-1888-e3f9-4c1e03c89c9d.png" width=500>


こちらも使用しているバージョンが【 0.2.3 】となります。
AI Plannerを使ってどのようなことが出来るのか知るのには大変有用なのですが現行のバージョンと設定の仕方が違うため、参考とする場合は注意が必要です。

現行バージョンに対応したサンプルですが、Unity Forumのコメントでは"Coming soon!"とのことなので期待して待ちたいと思います。

# どんなAIなのか

AI Plannerは「ゴール指向プランニング」なゲームAIです。
一言でゴール指向プランニングと言っても色々な種類があるのですが、AI Plannerは比較的シンプルな仕組みである「フォワードプランニング」を採用しているようです。

フォワードプランニングは選択肢（アクション）の全組合せを想定して、その中から目的（ゴール）を達成しているパターンを見つける方式です。

ゴールまでの様々な実行パターンを生成しつつ、報酬（Reward）を基に適切なものを決定して実行します。
ここ（パターンの生成）にDOTSベースであることが役立っているようです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/ec29ac06-7314-d5ee-78e5-d375c727e68c.png" width=800>

# 作ってみた。

最新バージョン【 0.2.4preview 】での設定と動作確認を兼ねて簡単なプロジェクトを用意しました。
GitHubにて公開していますので学習などにご利用ください。

- *[AiPlannerNyumon](https://github.com/q1j/AiPlannerNyumon)*

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/97f6caeb-2d5a-2c96-a38d-5566cdbeaff1.png" width=500>

# もう少し詳しく。

先ほどのサンプルプロジェクトを例にAI Plannerを動作させるのに必要なファイルやコンポーネントについて紹介します。

## AI Planner をセットアップすることは Decision Controller を正しく設定すること

「解決する領域」「選択肢（アクション）」「ゴール」を決めることでAI Plannerは計画を立案と実行を行うことが可能となります。
その際に必要な情報は **Decision Controller** というコンポーネントに集約していくことになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/39712ebe-e75c-210a-00ff-fb118be10e34.png" width=800>


このコンポーネントを正しく設定するのには幾つかのファイルが必要となっています。

1. Trait Definition　（GameObjectに設定する特性）
1. Action Definition　（選択肢・アクション）
1. Action Callback Method　（アクションをシーンに反映するスクリプト）
1. Termination Definition　（プランの終了条件）
1. Problem Definition　（問題領域の定義）

それぞれの役割について説明していきます。

### 1. Trait Definition

シーン上のGameObjectに付加する**特性**の定義ファイルです。
AI Planner に認識される＝ プランニングの対象となります。

### 2. Action Definition

Traitを操作する選択肢である **Action** のルールの定義ファイルです。
どのような条件のときにどのような操作を行うかを設定します。

- Preconditions（実行条件）
- Effects（Traitの操作内容）
- Reward（報酬）

### 3. Action Callback Method

AI Plannerが Action を実行時する際に呼び出すコールバックメソッドをC#にて定義します。
シーン上のGameObjectを操作するのが主な利用方法になります。

#### ２つのAction

Action Definition と Action Callback Method の役割の違いと関係性は大まかに言うと以下の様になります。

- Action Definition は AI Plannerがプランを作成して実行する為の選択肢を定義、Traitの状態を変更する
- Action Callback Method は AI Planner実行されたActionに合わせてシーン上のオブジェクトを変更するメソッド（C#）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/512eca83-718d-18b2-fa36-71db95c7274a.png" width=800>

### 4. Termination Definition

プランの終了条件（Criteria＝基準）を設定する定義ファイルです。
AI Plannerは定義された終了条件を満たすと、その時点でプランの実行終了します。

- Criterai（Planの終了条件・クライテリア）

### 5. Problem Definition

プランを立てる際の条件を設定する定義ファイルです。
選択肢として使用するActionとゴールとなるTerminationを設定します。

- Actions（Traitを操作するルール）
- Terminations（終了条件）

### Decision Controller

計画を立てて実行するコンポーネントです。
これまで出てきた定義ファイルやスクリプトファイルを設定していくことでAI Plannerの実行条件を教えることが出来ます。

- Problem Definition の指定をする（使用するActionとTermination（終了条件）が設定される）
- Action と コールバックメソッドの関連付けを行う（Action実施時にコールバックメソッドの呼び出しを行う）
- Trait が設定されたGameObjectを登録する条件を設定する（条件に合ったGameObjectが自動で登録される）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/1f17e853-0257-22c9-ac9f-ed728d8cc4f7.png" width=800>

# やってみよう。

ここからは実際にプロジェクトの設定をしてみたい人向けの手引きとなります。
用意した学習用プロジェクトをサンプルに、定義ファイルやスクリプトの作成方法を説明していきます。

- *[学習用サンプルプロジェクト「AiPlannerNyumon」](https://github.com/q1j/AiPlannerNyumon)*

## 準備

### 準備① パッケージインストール

先ずはAI Plannerのパッケージをインストールするところからになりますが、Unity 2020ではPreview版のパッケージは一部のみしか表示されないようになりました。

AI Plannerも表示されないパッケージとなりましたのでURLを指定してインストールする方法を紹介します。

##### 手順
1. メニューより Window →　Package Manager を選択してウインドウを表示
1. 左上の **+** ボタンより「Add package frome git URL...」を選択してAI PlannerのURL【 com.unity.ai.planner 】を入力してインストールを実行

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/8becb00a-8b9f-6110-da7c-18903689ca08.png" width=800>

詳しくは公式を確認して頂くのが良いと思います。

- *[Unity 2020.1 からパッケージマネージャで発見できなくなったパッケージのインストール方法](https://helpdesk.unity3d.co.jp/hc/ja/articles/900002171066-Unity-2020-1-%E3%81%8B%E3%82%89%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%81%A7%E7%99%BA%E8%A6%8B%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95)*


### 準備② シーンの作成

シーン上にAI Plannerのプランの対象とするGameObjectをいくつか配置します。

- Eater（捕食者）　→　青い四角
- Goal（ゴール）　→　赤い丸
- Feed（餌）を２つ　→　オレンジの丸

置き方は基本自由ですが、ここでは下の図のように設置しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/97f6caeb-2d5a-2c96-a38d-5566cdbeaff1.png" width=500>

### 準備③ ルールを決める

AI Plannerはルールに沿って計画を立てて順番通りに実行するゲームAIライブラリなので、どの様な動きにするかを決めてそれを定義ファイルやスクリプトに落とし込んでいきます。

サンプルプロジェクトでは以下のルールを設定しています。

##### ルール
- Eater（青い四角） が移動して Feed（オレンジの丸） とGoal（赤い丸）を食べる
- Goal（赤い丸） はいちばん最後に食べる
- 全部食べたら終了

## 定義ファイルとスクリプト

準備が出来たら定義ファイルとスクリプトを用意していきます。

### 1. Trait Definition

#### 1-1. Definitionファイルの作成

GameObjectに設定するTrait（特性）の定義ファイルを作成します。

##### 手順
Projectウィンドウ上で右クリック、Create → Semantic → Trait Definition
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/7f53a583-15f0-1168-d766-776f3c388df1.png" width=600>

サンプルプロジェクトでは以下の３つのTrait Definitionファイルを作成しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/0e215f16-ce97-eac6-12ea-b7bfaec64a82.png" width=400>

#### 1-2. プロパティ

プロパティはTraitが持てる変数です。

サンプルプロジェクトでは食べた数をカウントするプロパティを EaterTrait に用意しています。

##### 手順
- プロジェクトウィンドウでEaterTraitを選択
- インスペクタに表示されるPropertiesにIntegerのプロパティを追加してEatCountに名称を変更

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/e97ed843-5893-b9a8-d881-a7e5e9d4232d.png" width=800>

#### 1-3. Traitのビルド

Trait Definitionが準備出来たらSematicメニューからTraitをビルドします。
これによりGameObjectにTrait（特性）を付与出来るようになります。

##### 手順
- メニューより、Semantic → Traits → Build を実行
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/a8a07062-31c2-729a-9506-58ae6a0e31d9.png" width=600>

#### 1-4. GameObjectへの設定

作成したTrait（特性）をGameObjectに付加することで、AI Plannerの計画に組み込みます。

サンプルプロジェクトでは各GameObjectに以下のTraitを付加しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/92937a1c-fa4d-33ab-c636-544dbc55c1d3.png" width=800>

Traitの付加はSematicObjectコンポーネントを使って行います。

##### 手順
- Traitを付加するGameObjectを選択
- SematicObjectコンポーネントを付加
- SematicObjectコンポーネント内の **⊕** ボタンを押下して付加するTraitを選択する

以下ではEaterのGameObjectに **EaterTrait**、**Location**、**Moveable** を設定しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/d721ebfe-22f1-0fc2-4713-4b8d7d96e523.png" width=800>

EaterTraitの他に指定している2つの特性「Location」と「Moveable」は、AI Plannerに用意されている既存の特性となります。

- **Location** を付加することでGameObjectのLocationを参照できる様になります。
- **Moveable** は移動するGameObjectであることをAI Plannerに示すことが出来ます。

同様の手順でFeedとGoalのGameObjectにもTrait（特性）の設定を行っています。
ただしFeedとGoalは移動しないのでMoveableは付加していません。

###### Feedの設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/b13f1a15-52d5-4e35-16da-6de2a86bda80.png" width=800>

###### Goalの設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/6859585b-ad96-f43e-bcc8-bba51a7af900.png" width=800>


### 2. Action Definition

Actionは実行条件と実行時の効果（操作）を設定することでAI Plannerが計画を立てる為の選択肢として機能します。

- Preconditions（実行条件）
- Effects（Traitの操作）
- Reward（報酬）

また各項目を設定するのに変数として利用するパラメータを設定することが出来ます。

- Parameters（パラメータ）
 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/4ff1192d-df41-0ba2-e1fb-4d0ab56f7628.png" width=800>

### 2-1. Action Definitionファイルの作成

Traitを持ったオブジェクトを操作するActionの定義ファイルを作成します。

##### 手順

Projectウィンドウ上で右クリック、Create → AI → Planner → Action Definition
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/c44c6d89-e775-f62c-d6c0-0b6e8f4f0b20.png" width=800>

サンプルプロジェクトでは以下の３つのAction Definitionファイルを作成しました。

- **FeedEatAction** 「 餌（FeedTrait）を食べる」
- **GoalEatAction** 「ゴール（GoalTrait）を食べる」
- **WalkAction** 「（Moveableを）移動する」

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/20c349fb-8b7f-f457-7762-77abe255b973.png" width=400>

#### 2-2. パラメータの設定

Trait Definitionをパラメータとして定義することでAction内で利用することが出来ます。
AI Plannerで用意されているLocationとMoveableも指定可能です。

- **Location** を指定することでGameObjectのLocationを利用可能となります。
- **Moveable** を指定することで対象とするTraitを「Moveableが指定されている（指定されていない）Trait」に限定します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/78bf550e-227b-fc81-9b34-0da80efc081a.png" width=800>

#### 2-3. Actionの定義

作成したAction Definitionの設定を行っていきます。

##### FeedEatActionの設定

「餌を食べる」というアクション（選択肢）を作成します。

###### ① パラメータ（Parameters）

「餌を食べる」というアクションは **EaterTrait** が **FeedTrait**に重なったときに餌（FeedTrait）を削除するという動作とします。
この時に利用する **EaterTrait** と　**FeedTrait** をパラメータとして定義します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/8111f8dd-4ba9-f89f-82f3-b49151b0f7da.png" width=800>

###### ② 実行条件（Preconditions）

パラメータを利用してアクションの実行条件を設定します。
**Location** から参照できる **Position**（位置）を判定し、EaterTraitとFeedTraitが同じ位置であることを条件としています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/650f271a-7fac-d45f-9bd9-ed3b442e3b7e.png" width=800>

###### ③ 操作（Effects）

（実行条件と同じく）パラメータを利用してTraitをどの様に操作するかを設定します。
ここでは２つの内容を同時に行っています。

1. EaterTraitの持つプロパティ **EatCount** を1つ加算
1. **FeedTrait** を削除（Removed）

ここでの削除（Removed）でFeedTraitが設定されるGameObjectが削除される訳ではないということに注意してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/fbc13b7b-9650-62ff-498f-25553b08c160.png" width=800>

###### ④ 報酬（Reward）

アクション実行時の報酬を設定します。
AI Plannerは報酬の合計が高くなるように計画を立てて実行します。

報酬は優先順位ではないことに注意してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/6044bf07-a75a-5a34-72cf-adf32cd412e9.png" width=800>

##### GoalEatActionの設定

基本的な手順はFeedEatActionと同じとなります。
ここではサンプルプロジェクトで設定している値のみを紹介します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/36ccc78a-04da-2bbf-cc48-05917d9435d3.png" width=800>


##### WalkActionの設定

基本的な手順は上２つと同じとなります。

特徴として **UnmovableTarget** パラメータの指定に論理否定（赤の⊕への設定）の方に **Moveble** を指定してます。
これは「Movebleが指定されていない」ことを意味しています。

サンプルプロジェクトでは FeedTrait、GoalTrait、EaterTrait の3つのTraitがあります。
この内「Movebleが指定されていない」のは FeedTrait、GoalTrait の2つになりますので、UnmovableTargetパラメータは FeedTrait、GoalTrait の2つを指すことになります。

また、報酬に **LocationDistance** を使っており、その引数としてパラメータの **Eater** と **UnmovableTarget** を指定しています。
これは2点間（EaterとUnmovableTarget）の距離をReward（報酬）の計算に使用する為の設定で、**Base Value** に設定した値より減算（-=）することで、距離が遠いほど報酬が減るという設定を行っています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/aff00823-7fd1-6958-3a18-15855c2ee05f.png" width=800>

### 3. Action Callback Method

Action Callback Method はアクション実行時に呼び出すコールバックで、主にシーン上のGameObjectの操作に利用します。

サンプルプロジェクトでは以下の2つのコールバックメソッドを用意しました。
ファイル自体はUnityで通常使うC#ファイルと同じ作成の方法となりますので、詳細は省略します。

#### Move

Lerpを使用してGaneObjectを移動させます。

```C#
public IEnumerator Move( GameObject target )
{
    while (target != null && ! IsArrival( target ) )
    {
        transform.position = 
        Vector3.Lerp ( 
            transform.position, target.transform.position, 0.03f );
        transform.LookAt ( target.transform.position );
        yield return null;
    }
}
```

#### DestroyObject

DestroyImmediateを使用してGaneObjectを削除します。
削除に0.3秒止めていますが、これを動きを確認する為のものです。
 
```C#
public IEnumerator DestroyObject( GameObject target )
{
    DestroyImmediate ( target );
    yield return new WaitForSeconds ( 0.3f );
}

```

### 4. Termination Definition

Termination Definitionにて終了条件を指定することでAI Plannerを終了させることが出来ます。

継続的に動き続ける様なゲームAIを作成したい場合は指定をしないことも可能です。
その場合、 Termination Definitionファイルの作成は不要となります。

#### 4-1. Termination Definitionファイルの作成

##### 手順

Projectウィンドウ上で右クリック、Create → AI → Planner → State Termination Definition
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/24fb055e-e907-34e3-d193-1b8a24fc7c0a.png" width=800>

サンプルプロジェクトでは **FoodEaterTermination** という名前でファイルを作成しました。

#### 4-2.Termination Definitionの設定

Termination Definitionの設定項目は以下の3つになります。

- Parameters（パラメータ）
- Criteria（終了条件）
- Terminal Reward（報酬）

サンプルプロジェクトのFoodEaterTerminationファイルでは以下の様な設定を行っています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/06cded6e-84b8-fc41-b7bb-b1e157297ea2.png" width=800>

##### ① Parameters（パラメータ）

パラメータは終了条件で使用する特性（Trait）を定義します。
パラメータには終了条件 **EatCount** をプロパティとして持つ EaterTrait を参照できるよう **Eater** を定義しています。

##### ② Criteria（終了条件）

終了条件にはパラメータが取り得る状態を設定します。

FoodEaterTerminationではEaterTraitに用意したプロパティ **EatCount** が3になったらという終了条件を設定しています。
これは「準備③ ルールを決める」で定義した「全部食べたら終了」というルールに沿ったものとなります。

アクション **FeedEatAction**、**GoalEatAction** の実行時にEaterTraitのEatCountを加算する操作（Effects）を設定しているため、シーン上の全FeedとGoalを削除した時点でEatCountの値は3となり終了条件が満たされます。

##### ③ Terminal Reward（報酬）

Terminal Reward は終了条件が満たされた場合に加算される報酬となります。
計画がゴールするのは良いことなのでアクションより高い値を設定しました。

### 5. Problem Definition

AI Plannerがプランを立てて実行するのに必要な条件（問題領域）を定義します。

#### 5-1. Problem Definitionファイルの作成

##### 手順

Projectウィンドウ上で右クリック、Create → AI → Planner → Problem Definition
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/de590834-9bc0-c69d-31d1-9bdf99af2c60.png" width=800>

サンプルプロジェクトでは **FoodEaterProblemDefinition** という名前でファイルを作成しました。

#### 5-2. Problem Definitionの設定

Problem Definitionの設定項目は以下の2つになります。

- Actions（プランの作成に使用するAction）
- Terminations（終了条件）

サンプルプロジェクトのFoodEaterProblemDefinitionでは以下の様な設定を行っています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/b482c717-d928-3650-8741-0efdc9fef8d5.png" width=800>

##### ① Actions（プランの作成に使用するAction）

作成したAction Definitionファイル **FeedEatAction**、**GoalEatAction**、**WalkAction**　を設定しています。
この設定によりAI Plannerが計画を立てるときの選択肢として利用できるようになります。

##### ② Terminations（終了条件）

作成したTermination Definitionファイル **FoodEaterTermination**　を設定しています。
この設定によりAI Plannerが終了条件（ゴール）を達成するように計画を立てて実行します。

Termination Definitionでの記載しましたように一定の動きを繰り返すような場合には終了条件の設定は不要です。

### 6. Decision Controller

定義ファイルとスクリプトファイルの準備が出来たら **Decision Controller** を構築します。
Decision Controllerを正しく設定することでAI Palnnerは計画を立てて実行を行い、シーン上のオブジェクトを動かし、プランを完了させることが出来ます。

#### 6-1. Decision Controllerコンポーネントの付加

Decision ControllerはコンポーネントなのでGameObjectにAdd Componentして利用します。
Decision Controllerはシーン上にあれば動作するので、どのGameObjectに付けても大丈夫です。

サンプルプロジェクトでは **DecisionController** オブジェクトにAdd Componentしています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/37a957a9-669c-f74f-0de0-b6756d9c49f9.png" width=800>

#### 6-2. Decision Controller コンポーネントの設定

Decision Controller コンポーネントの設定は以下の3つになります。

- Problem Definition（プランの作成に使用するProblem Definition）
- Available actions from the plan（Action DefinitionとAction Callback Methodの紐付け）
- Semantic Query（プランの対象とするGameObjectの条件）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/93d8804c-63a2-4544-82f5-8342dd2b902b.png" width=800>

サンプルプロジェクトのDecision Controllerでは以下の様な設定を行っています。

##### ① Problem Definition（プランの作成に使用するProblem Definition）

Problem Definitionファイルを設定することで（Problem Definitionの）Actions に設定している Action Definition が、（Decision Controllerの） **Available actions from the plan** に自動で設定されます。

サンプルプロジェクトでは Problem Definition ファイル **FoodEaterProblemDefinition** を設定しており、FoodEaterProblemDefinition に設定した **FeedEatAction**、**GoalEatAction**、**WalkAction**　が Available actions from the plan に設定されています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/ec2d288f-1779-f11f-3e27-00c3623ae306.png" width=800>

##### ② Available actions from the plan（Action DefinitionとAction Callback Methodの紐付け）

登録されたActionに対する **Action Callback Method** の指定を行います。

サンプルプロジェクトでは3つのActionに対して **Move**、**DestroyObject** のコールバックメソッドを設定しています。
その際、コールバックメソッドに引数として渡す値（GameObject）を（Problem Definitionに設定した） **Action Definition** の **Parameters** の中から指定します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/712449e8-0a08-7345-f14d-5e9dc30283aa.png" width=800>

##### ③ Semantic Query（プランの対象とするGameObjectの条件）

**Semantic Query** を作成、設定することでAI Plannerが対象とするシーン上のGameObjectを Decision Controller に設定することが出来ます。
Semantic Query の作成は Decision Controller コンポーネント上で実行でき、作成したファイルがそのまま設定されます。

Semantic Query は作成された時点でシーン上のTraitを持った全てのGameObjectを対象としますが、設定を行うことで距離などの制限を付けることが出来ます。

サンプルプロジェクトではデフォルトの状態のままとしている為、シーン上のTraitを持った全てのGameObjectが Decision Controller に登録されています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/54f26ede-6a7c-0cac-de3f-070e8c00dfa3.png" width=800>

### AI Planner のビルド

Decision Controller の設定が出来たら AI Planner のビルドを行います。

##### 手順

- メニューより、AI → Planner → Build

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30693/711d3820-9b90-cc88-3889-6a8873ea764f.png" width=600>

無事にビルドが通ったら完了です。おつかれさまでした。

# より活用したい人向けの情報

本記事は「AI Planner入門」という形でサンプルプロジェクトを例にしてどの様なファイル、設定、スクリプトが必要か、それらがどの様に結びついてくるかを（ざっとではありますが）説明したものになります。

より活用したい人向けに公式マニュアルの **Custom Planner Extensions** ページと Unity Forum の　**AI & Navigation Previews** のスレッドを紹介しておきたいと思います。

## Custom Planner Extensions

- [Custom Planner Extensions](https://docs.unity3d.com/Packages/com.unity.ai.planner@0.2/manual/CustomPlannerExtensions.html)

AI Plannerはインスペクタの設定だけで条件付けがある程度出来るようになっており本記事でもインスペクタ上で出来ることを中心に構成しましたが、実際に活用するためにはアクションの実行条件、報酬設定、終了条件などゲームロジックに合わせて動的に変更する必要が出てくると思います。

そうしたより複雑な設定を行うため AI Planner はC#での実装を行う interface が用意されています。
以下のページにInterfaceの利用方法が解説されていますので参照ください。

## AI & Navigation Previews

- [Unity forum - Custom Planner Extensions](https://forum.unity.com/forums/ai-navigation-previews.122/)

UntiyオフィシャルのAI関連のフォーラムです。
AI Planner に限らずUL-AgentやNevMeshなどについての質問やディスカッション、バグ報告などが行われています。

AI Planner は公式のTwitterなどを見ていても情報が流れてこないのですが、フォーラムを見に行くと新しい情報があったり他の開発者の方からの質問に公式が答えていたりして安心します。

# 最後に。

AI Planner はやっと出てきたUnityのゲームAIとなります。
未だこれからの部分も多々ありますが実験的なプロジェクトなどで使ってみても良いのではと思えるくらいに充実した内容となっております。
興味を持ちましたら是非公式サンプルや動画を見てみて下さい。

本記事が AI Planner の普及と開発者の方の一助となることを願っています。