自律的な針路設定機構をBPで作る

# 概要
自主制作プロジェクトにおいて某SF宇宙船用の移動処理をBPで実装。
エンジンバージョンは5.2~5.3
# 基本要件
要求される挙動は...
- 進行方向へ移動する。
- 目標座標を指定し、基本はその座標へ繰り返しアプローチする軌道を取る。
    (今回は中央に陣取る"ボーグキューブ"を目標とする)
- 一定距離内に障害を検知した場合は旋回しそれを回避する。
- 旋回が終わったら艦のロール軸回転を水平に戻す。

# ノード構造
最終的にブループリントはこのスパゲッティのようになりました_(┐「ε:)_
![イベントグラフ 2024_06_27 13_43_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/e9e03ab7-4821-df98-4a08-37be9b44a7c0.png)


処理の構造としては以下の通り（折り畳み内に詳細を記載）
![イベントグラフ-ナンバリング.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/f31ef6d5-362a-7f44-0d3e-0964ef6ec9ce.jpeg)

<details><summary>①推力制御部分</summary>

- 現在のTransformと速度(float変数)から次フレームの位置を算出して適用する。
![Section1グラフ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/57cdc25b-71e5-f1bb-8f82-c4c9eea6db5c.jpeg)


</details>

<details><summary>②センサー部分</summary>

- Sphere line trace by channelを使用し、艦を中心に45°ずつ5本のトレーサーを広げる。![イベントグラフ 2024_06_27 13_47_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/35f2c9ed-ddca-b094-4755-d0b978b3e1d2.png)
扇形範囲内の障害物の有無を検知する。
(長さが不均衡なトレーサーは自然な挙動になるように感知タイミングを調整したもの)
![StarTrekMini - Unreal Editor 2024_06_27 13_46_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/8e9be7e3-174d-4787-6bdc-100be26b8c4a.png)


</details>

<details><summary>③制御中枢部分</summary>

- センサー部分の情報と追跡対象との位置関係をもとに、大きく分けて4種類の行動に分岐する。
    1. 目標座標に向け旋回する
        自艦から見たターゲットの方向(ローカル座標系)によって旋回方法を判定
![イベントグラフ 2024_06_27 13_48_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/8fcdc7d0-7555-e5b8-6f59-e47726fd6914.png)
        
    2. ロール回転を水平に戻す
        仮想transformとアクターの相対ロール回転を計算し、それを徐々に0に近づけることで水平に戻す
![イベントグラフ 2024_06_27 13_47_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/cff9a7c1-92a5-5792-32db-4d91ffdd4905.png)
        
:::note info
仮想transform(仮称)
アクターの進行方向を示すベクトルを回転値に変換し、actor transformのrotatorと置き換えることでローカルのロール回転値を排除した仮想的なtransformを算出する
![StarTrekMini - Unreal Editor 2024_06_27 17_51_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/d12030e4-4b27-eea7-3088-50906d658029.png)
:::
\
    3. 僚艦接近時の回避機動
        接近を検知した場合、検知方向と反対側に転舵する
        例) 右上方向に検知-->左下方向に転舵

![イベントグラフ 2024_06_27 13_47_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/524bfddd-cec2-a457-5629-0a0fd01ff34f.png)
 \
    4. トレーサーがターゲットを検知した際の回避機動
        左右45°のトレーサーが反応した場合は侵入角度が深すぎるということなので、フレームあたりの旋回角度をより大きくしている。
        ※ターゲットとの衝突(オーバーラップ)は絵面的に一番避けたいので、分岐の優先順位として最優先になるように配置している。
![イベントグラフ 2024_06_27 13_47_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/24fa1875-8af1-35e8-daf7-f9b285aff0f9.png)

### 回転値の算出
これらの分岐を経て実際のrotatorにする処理
アクターから見たアクターのローカル回転は常に0なので、現在値に変化量を与えてワールド回転に戻すというのが基本戦略。
（回転しすぎて裏返ると困るので、再び仮想transformを基準として最終的な回転に制限をかけている
![回転算出.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752748/f3a6b9c8-f33a-66d3-eacc-8425ca5aca38.jpeg)


</details>


以上のロジックで実際に動かしてみるとこんな感じに
https://youtu.be/BJ1jdWjCp5c
<iframe width="560" height="315" src="https://www.youtube.com/embed/BJ1jdWjCp5c?si=uhd_stdcStr7AVUr" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# 終わりに
実装から半年以上経っての記事作成となったため、改めて見ると計算処理の煩雑さが目立つ他、おそらくTimerノードを用いて動作クロックを30fps程度に落としても問題ない(今ならそうする)。
...が、ロール軸回転の算出で使用した仮想的なtransformを置く手法は我ながら良い発明だったと思う。