【UE4】AIを良い感じに歩かせたい

#はじめに
Unreal Engine 4 (UE4) その2 Advent Calendar 2018 10日目の記事です。

[Unreal Engine 4 (UE4) その2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ue4_zwei)

#まずは結果確認
早速ですが今回の記事を参考にAIの歩行運動を良い感じにした場合と、エンジンにビルトインされているデフォルトの歩行運動機能を実行した場合との結果を提示します。

Characterブループリントでは
**Use Controller Rotation Yaw = チェックを外す**
**Orient Rotation to Movement = チェックを入れる**
**Rotation Rate = Zを90に変更**
と各種オプションを設定しています。
それぞれの歩行運動機能をAIControllerクラスで実装しアタッチしています。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">アドカレ用 <a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://t.co/YacxmQ8gOR">pic.twitter.com/YacxmQ8gOR</a></p>&mdash; PavilionDV7 (@Dv7Pavilion) <a href="https://twitter.com/Dv7Pavilion/status/1071060524241084418?ref_src=twsrc%5Etfw">2018年12月7日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


カスタムした方は**曲がり角**で、非常にスムーズな経路を辿っておりとても人間的です。それと比べデフォルトの方では曲がり角をほぼ直角に曲がります。
更にデフォルトの方ではオプションを設定したことで即座に進行方向に振り向くのではなく、少しゆっくりと進行方向へと振り向きます。それによって**移動方向とエージェントの体の向きが揃っておらず**、いわゆる**[ストレイフ移動](https://en.wikipedia.org/wiki/Strafing_(gaming))（Strafing Movement、平行移動、カニ歩き）**が発生しています。カスタムの方ではストレイフ移動は発生せず、移動方向とエージェントの体の向きが一致しています。

#プロジェクトはこちら
バージョン：4.21.0
https://1drv.ms/u/s!Au-8FqgREBKZhTvkxVeDjmderuY9

#AIC_CustomMoveTo ブループリント
結果を見ていただいた通り、カスタムとデフォルトでは大きく差異があり、デフォルトの方では不自然な点が多く見られたと思います。この問題をどのように解決したのかをプロジェクトの**AIC_CustomMoveTo**の実装を提示しつつ紹介していきます。（これはAI Controllerクラスを継承したクラスです）

> ここで提示する実装例はあくまでも理解のしやすさ、ブループリントの見通しのよさを重点に置いているので何かしらのプロジェクトで使用する場合には更に機能追加が必要になるかもしれません。

##1. 目的地までの経路を見つける
![2018-12-01_16h03_44.png](https://qiita-image-store.s3.amazonaws.com/0/104467/ddc02d11-1f85-44b7-d7e0-adad8a6dacf0.png)

カスタムの歩行運動機能では用意されている**AI Move Toノード**等の移動ノードは使う事が出来ません。ですが「どの経路を通るべきか」という情報は必須なので**Find Path to Actor Synchronouslyノード**で目的地までの経路を取得し保持しておき、**現在、どの曲がり角へ向かっているか**を記録するためのインデックスを初期化します。

##2. 曲がり角へ到達しているかチェック
![2018-12-01_16h09_58.png](https://qiita-image-store.s3.amazonaws.com/0/104467/5d539361-8e4e-59b8-6b1c-a3c9a2f1cdef.png)

現在向かっている曲がり角の座標位置を取得し、コントロール中のPawnとの距離をチェックしAcceptance Dist以内ならTRUEを返します。

##3.1. Pawnの回転と移動
![2018-12-01_16h21_09.png](https://qiita-image-store.s3.amazonaws.com/0/104467/80e05595-143e-5f1d-e80f-ed4ded6d59a9.png)

2番でのチェックでFALSEが返った場合の処理です。ここが**AIを良い感じに歩かせる肝となる箇所**です。
見ての通り処理自体は非常に単純です。

Find Look at Rotationノードで**Pawnから向かっている曲がり角へと向かう回転**を取得し、RInterp Toノードへと渡します。返ってきた値をPawnの回転へセットすることで、**徐々に曲がり角へ向く**ようになります。

次に移動です。これはプレイヤーキャラクターの操作でお馴染みの**Add Movement Inputノード**を使っています。**World Direction**へと渡すベクトルは**Pawnの前方ベクトル**です。

**Find Look at RotationとRInterp Toにより徐々に向きを変えつつ、常に前方へと移動する**。この2つを組み合わせることで、デフォルトの歩行運動機能の問題点（直角に曲がる、移動方向と体の向きの不一致）が解決します。

##3.2. インデックスの更新
![2018-12-01_16h38_40.png](https://qiita-image-store.s3.amazonaws.com/0/104467/3bada676-9376-bda1-7aa6-50445361e85e.png)
2番でのチェックでTRUEが返った場合の処理です。
保持した経路配列のサイズと現在のインデックスを比べ、配列の最後のインデックスと現在のインデックスが同値であれば**目的地へ到達した**とし、TRUEを返します。そうではない場合現在のインデックスをインクリメントしてFALSEを返します。
![2018-12-01_16h38_49.png](https://qiita-image-store.s3.amazonaws.com/0/104467/d3ed8132-c327-2b89-e9c2-5c65dcbbeb9a.png)


##4. Tickの停止
![2018-12-01_16h39_32.png](https://qiita-image-store.s3.amazonaws.com/0/104467/bad2ef64-51b2-d3fd-2a5d-55a3ea5785f7.png)

3.2番にてTRUEが返った場合はSet Actor Tick Enabledで更新を止め、移動処理を今後行わないようにしています。

#Behavior Tree版
AI Controllerでの実装をそのままBehavior TreeのBTTaskへと移植したバージョンもプロジェクトに同梱してあります。アセット名は**BTT_CustomMoveTo**です。
![2018-12-05_22h07_32.png](https://qiita-image-store.s3.amazonaws.com/0/104467/68d62f76-5c41-c4e7-ef9b-874ffc2f8801.png)

AI Controller版と違いはほとんどありません。目的地到達後の処理が**Set Actor Tick Enabledノード**から**Stop Logicノード**に置き換わっているくらいです。

BTTaskでは**Finish Executeノード**を通してBehavior Treeシステムにタスクの成功\失敗を通知します。BTT_CustomMoveToではエージェントが最終目的地に到達した場合にのみFinish ExecuteノードでTRUEをセットし、成功を通知します。
Finish Executeノードが呼ばれない間、BTTaskノードは**処理中**を表す**EBTNodeResult::InProgress**を返します。InProgressは「今このタスクを処理中だから他のタスクには遷移しないでくれ～」という状態を表すものです。
これによりBTT_CustomMoveToはエージェントが最終目的地に到達するまで他のタスクに遷移はしないようになります。


#おわりに
今回紹介した実装方法は
[The Occupation で採用された AI ロコモーションのレイヤー アプローチ](https://www.unrealengine.com/ja/tech-blog/a-layered-approach-to-ai-locomotion-in-the-occupation)
を参考にしたものです。
実装例もどこかの掲示板かなにかに貼り付けられていたものをベースに書き直したものなのですが、失念してしまい探し出すことも出来ませんでした。

今回はブループリントのみでお手軽に結果を出してみましたが、より見栄えの良い歩行運動を行わせるには上記リンク先のように**アニメーションとアニメーションBPとの連携**も必須となります。例えば配布したプロジェクトでは見栄えが良くなるようなレベルになっていますが、目的地をエージェントの**真後ろ**にした場合、不自然に大回りするように見えるはずです。

このようなエージェントの歩行運動機能は一人称・三人称のシューターやアクションに登場するエージェントには不向きだと思いますが、オープンワールドによくある市民等のエージェントには非常にマッチするはずです。
機会があれば是非お試しいただければと思います。

ここまで読んでいただきありがとうございました。

---

明日は@diberidarshiさんの記事になります。
ARKitについてですかね？とても楽しみです！