BPオンリーのプロジェクトでのガンビットAIライブラリ「JohnnyGambitLibrary」の使い方

#はじめに
この記事は[Unreal Engine 4 (UE4) その3 Advent Calendar 2020 ](https://qiita.com/advent-calendar/2020/ue4_tre)の22日目の記事です
以前作成して地道に更新している自作ライブラリのJohnnyGambitLibraryですが、C++プロジェクトを前提としている部分が大きかったのでBPのみで構築するためのHowtoを書きました

#JohnnyGambitLibraryとは？
OSSとして公開している意思決定AIに絞ったゲームAIライブラリです
UE4には標準でbehaviortreeなどの高機能なゲームAIの仕組みがありますが、ゲームのジャンルによっては高機能すぎてオーバースペックだったりします
そんな時に拡張が楽でちょっとした意思決定AIを作成したい時に使うためのライブラリです
特徴としては、導入までをプログラマが対応しておけば後の拡張は最低限のUE4の知識を持つプランナーだけである程度複雑なAIも組めるようになる点です

イメージとしてはFF12のガンビットAIを意識しています
![FF12](https://lh3.googleusercontent.com/proxy/c0ra7TKc2Ztlp7ANWhGAN-NyPwJ5OrY_U6I7t8SGYZWrIvqm39NC7rWWom_OGBLORWwMcvvTuiTnMeym7VUV3_srJFAtBvrqJX8y0susMxModEdWaCBw79jwojttMUB-)

[公開時の記事はこちら](http://johnnygamestudio.hatenablog.com/entry/2020/09/01/020727)
[リポジトリはこちら](https://github.com/JohnnyBoss1206/JohnnyGambitLibrary)

上記の記事で詳細な解説はしてあるのでご覧ください
構成としては以下のようになっています

![JohnnyGambitLibraryの構成図](https://cdn-ak.f.st-hatena.com/images/fotolife/j/johnnygamestudio/20200901/20200901012730.png)

### 想定する使用シチュエーション
- コマンドバトルなどの複雑な自律AIが必要でない時のEnemyAI
- 簡易的なメタAI
- プレイヤーがAIを構築できるようなゲーム時の味方AI

などを考えています


#Howto
###環境
UE4.25.4
Windows10

<span style="color: #ff0000">今回はTopDownTemplateにJohnnyGambitLibraryを適用させて画面をクリックしたところが右上、右下、左上、左下のどこか判定するゲームAIを作成します</span>

[今回作成したプロジェクトはGithubで公開しています](https://github.com/JohnnyBoss1206/UE4Advent2020)

##STEP 1. プロジェクトにJohnnyGambitLibraryプラグインを追加する
プロジェクトへのPluginの追加方法は色々なところに書かれているので省きます
わからない人は以下の記事を参考にしてみてください
Pluginフォルダを作成してその下に落としてきたソースを配置してプロジェクトのuprojectファイルをダブルクリックしてコンパイル走らせるだけなので初心者でも出来ると思います
[CRIさんの導入記事](https://game.criware.jp/learn/tutorial/ue4/lesson01/)
[C++でのPlugin導入方法（途中までは一緒）](https://qiita.com/JGS_Developer/items/8345753fa13b81779d5b)

##STEP 2. ガンビットAIを使いたいActorへGambitAIComponentクラスを追加する
GambitAIComponentはガンビットAIの本体となるクラス


※画像ではTopDownCharacter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/94764a03-854e-7f61-98c7-823493c3ed03.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/98b15ae6-08ff-6e4d-fcae-9669875eccc7.png)


##STEP 3. GambitAIの条件判定となるActorのメンバ変数にGambitAIParameterクラスを追加する
GambitAIParameterはGambitAIComponentが条件判定を行う際に必要なパラメータ群を管理するクラスです
GambitAIComponentを持っていないクラスでもGambitAIParameterを持っていればGambitAIの対象に出来ます
※画像ではTopDownCharacterにのみ追加しています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/943203dd-3975-f80b-7919-787333c88709.png)

###STEP 3-2. GambitAIParameterのインスタンスを生成する
BegeinPlayなどで追加したメンバ変数のインスタンスを生成してあげましょう
GambitAIParameterはUObjectしか継承していないのでSpawnActorは使えません
なので[この記事を参考に](http://imoue.hatenablog.com/entry/2017/03/09/235150)してGambitAIParameterを生成しましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/235711ba-7b76-77ac-e733-2fc4d1a4a483.png)


##STEP 4. AIConditionクラスを継承したガンビット（条件判定）クラスを作成する
このクラスがJohnnyGambitLibraryのキモとなります
なるべく、一つのAIConditionで単純な構成にしたほうが後々組み合わせしやすくなります
今回作成するのは以下の4つを作成します

| クラス名 | 概要 |
|:-----------|------------:|
| Gambit_Left| クリックした場所が左側か？|
| Gambit_Right| クリックした場所が右側か？| 
| Gambit_High| クリックした場所が上側か？|
| Gambit_Low| クリックした場所が上側か？| 

### STEP 4-2. DoAICondition関数の中身を作成する
作成したAIConditionクラスにはDoAIConditionというそのAIConditionが成立するかどうかの判定する際に呼ばれる関数があります
この関数がTRUEの時そのガンビットは条件を満たしているということになります
Myには自身のGambitAIParameter、TargetListにはターゲットとなる対象のGambitAIParameterが入っているので、GetValueToFloat・GetValueToInt・GetValueToStringのいずれかを使って値を取得し条件判定を作成していきましょう

※今回はターゲット情報はないので使っていません
※画像はGambit_Left
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/e4ce9b5d-5c3f-03e4-642c-9097e9e22ff7.png)

##STEP 5. FDataTableGambitAISheetを継承したDataTableを作成しAIConditionクラスをアクションを設定していく
ActionConditionClassListには複数のAIConditionクラスが設定可能なので、今回は「右上」「右下」「左上」「左下」となるように組み合わせて設定していく
**この時設定したActionIDがヒットした時に取得できることになります**

**※この時Priorityを設定するとより値の高いものから優先的に条件判定がされます
※同Priorityの場合、より重みがあるアクションがよりHITする確率が高くなります**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/eeafb295-84d9-7cbc-97b5-2e608203fa29.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/4a4744fc-603a-79b1-85fb-a5ab1fe2deca.png)


###STEP 5-2. GambitAIComponentを持つActorのBeginPlayなどで作成したDataTableを指定してInitializeAIを行っておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/2b4bc1e1-ea3b-ab6d-160f-76a6f8d1393e.png)


##STEP 6. 条件判定につかう値が変動したタイミングでGambitAIParameterにSetParameterをしていく
※画像では画面クリック時にSetParameterしている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/a7d4704f-d573-0bbf-3a7c-e41ac0280043.png)


##FINAL STEP 7. GambitAIComponentのThinkActionを実行しGetCurrentActionID関数でヒットしたActionIDを取得する
ThinkActionを実行すれば、自身のGambitAIComponentが持つDataTableに設定された中から条件が合致するものを判定した結果のActionIDがGetCurrentActionID関数で取得できます
そのIDを元にゲーム固有のアクション処理を実行してください
サンプルではPrintStringしているだけです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/0aa116dc-384f-8b10-259e-427b235f564e.png)

#動作結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138731/b07b5e70-5d21-f939-4bd0-cf13460a396b.png)

#あとがき
いかがだったでしょうか
機能の内容としてはシンプルなものになっていますし、正直ライブラリといってもコード量もそこまで多くはありません
ですが、behaviortreeが高機能すぎて正直オーバースペックだしこれだけのためにプランナーにbehaviortreeの使い方を覚えてもらうのはちょっと…
というシーンではちょうどいいサイズ感になっているのではないでしょうか
AIConditionクラスの組み合わせで自由に新しい条件判定のアクションが作成できますし、BPの使い方さえマスターすればAIConditionクラスをプランナーだけで作成してもらうことも可能なサイズ感になっています
試しにつかってみていただけるととてもうれしいです