UE4 ゲーム制作メモ１

# 初めに
　この記事はUE4初心者が苦労しながら、チーム制作・個人製作で学んだ事を記述していくものとなっています。なので、間違っている可能性・別の方法が良かったりする可能性も普通にあるので、その点だけ注意して下さい。あと、中には「知ってるわ！」みたいな機能もあると思います。その場合は飛ばして下さい。
　作成で使用していたバージョンは「Ver 4.26.2, Ver 4.27.2」ですが、記事を書く上で使用しているのはUE5です。少し配置が変わってるぐらいで仕様自体はあまり変わらないので許して...。

# 一覧

　とてつもなく多いので量が多いので、スマホの方は下の一覧でタップして下さい。

| 目次 | 見出し |
|:-:|:-:|
| [マテリアル](#マテリアル)  | [テクスチャの透明度を適用したい](#テクスチャの透明度を適用したい) |
| --  | [マテリアルパラメータコレクション](#マテリアルパラメータコレクション) |
| --  | [マテリアルダイナミックインスタンス](#マテリアルダイナミックインスタンス) |
| --  | [マテリアルインスタンス](#マテリアルインスタンス) |
| --  | [マテリアルファンクション](#マテリアルファンクション) |
| --  | [マテリアルのノード](#マテリアルのノード) |
| --  | [便利なショートカット](#便利なショートカット) |
| [コリジョン](#コリジョン当たり判定)  | [Block, Overlap, Ignore](#block-overlap-ignore) |
| --  | [コリジョンプリセット](#コリジョンプリセット) |
| --  | [メッシュの判定](#メッシュの判定) |
| --  | [トレース系の判定](#トレース系の判定) |
| [AI](#ai)  | [AIの作成](#aiの作成) |
| -- | [ブラックボード](#ブラックボード) |
| -- | [ビヘイビアツリー](#ビヘイビアツリー) |
| -- | [ビヘイビアツリー自体を停止したい](#ビヘイビアツリー自体を停止したい) |
| -- | [ビヘイビアツリーのデバッグ](#ビヘイビアツリーのデバッグ) |
| -- | [標準のデコレーター・タスクノード](#標準のデコレータータスクノード) |
| -- | [ビヘイビアツリーの動き](#ビヘイビアツリーの動き) |

# マテリアル
## テクスチャの透明度を適用したい
　``Texture Sample``ノードを使って、テクスチャ（.pngなど）の透明度設定を適用したい。RGBAピンをベースカラーに繋いでも設定されない。
+ 「詳細 ＞ マテリアル ＞ ``Blend Mode`` ＞ **Translucent**」に設定
+ ``Texture Sample``ノードの「RGBピン」を「ベースカラー」に繋げ、同じく「Aピン」を「**オパシティ**」に繋げる

![テクスチャ 透明度.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/dd22cae5-d087-5d30-3311-93a084bd3b96.png)

### 参考サイト

https://crieit.net/posts/Unreal-Engine

## オパシティとラフネスが同時に設定出来ない
　「詳細 ＞ マテリアル ＞ ``Blend Mode`` ＞ **Translucent**」に設定した上で、``Metallic`‘やラフネスを設定したいが、無効状態になっている。
+ 「詳細 ＞ 透過処理 ＞ ``Lighting Mode`` ＞ **Surface TranslucencyVolume**」に設定
+ 「Metallic・スペキュラ・ラフネス」が有効状態になるので、それぞれのピンに繋げる

![Surface TranslucencyVolume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/becff5f5-ad1a-5aaf-6983-c42df5e7bc29.png)

### 参考サイト

https://forums.unrealengine.com/t/translucent-material-no-roughness-specular-available/365832

## マテリアルパラメータコレクション
　マテリアルパラメータコレクション（以下**MPC**）を一言で言うなら「複数のマテリアルに共通の値を外部から動的変更可能な機能」です。プログラマー的に言うなら「構造体のStatic変数」、DirectX的に言うなら「コンスタントバッファ」になるのかな～と思います。
　``MPC``は**マテリアル専用の構造体**みたいなもので、特定のマテリアルに依存せず外部から自由に変更が可能です。逆に言うなら、値を変更すると使用しているマテリアル全てが変わってしまいます。設定出来るパラメータは「スカラー（float）・ベクター（float4/Linear Color）」のみ可能です。勿論、動的に設定が可能ですが、取得も可能です。
![MPC.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/1da08c5b-6e12-67dd-501d-6d5a3848752a.gif)

### ``MPC``の追加・編集
+ 「追加 ＞ マテリアル・テクスチャ ＞ マテリアルパラメータコレクション」で追加
![MPC作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/06da9f3b-17b6-cf21-d44d-fd27448132b4.png)
+ 「詳細 ＞ マテリアル ＞ ``Scalar Parameters`` / ``Vector Parameters``」で値を追加
    + 名前と初期値を設定出来ます
![MPC 詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/728e8e1d-c313-2bb3-3636-4005dbc1f8ba.png)

※ 今回はテストなので、名前が適当になっていますが気にしないで下さい。

### マテリアル側
+ 「右クリック ＞ パラメータ ＞ ``CollectionParameter``」でノードを召喚
![MPC マテリアル 追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/ba1ac4ae-9c72-4f0a-9431-82df75b876d4.png)
+ 「ノードの詳細 ＞ 一般 ＞ ``Collection``」で作成した``MPC``を設定
+ 「ノードの詳細 ＞ 一般 ＞ ``Parameter Name``」でパラメータ名を設定
![MPC マテリアル 詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/ea015221-177a-1f99-cbf2-5568fe887d71.png)

今回のテストでは``Vector``パラメータを「ベースカラー」に、``Scalar``パラメータを「オパシティ」に設定しました。

### ブループリント側
+ 「レンダリング ＞ マテリアル ＞ ``Set Vector Parameter Value / Set Scalar Parameter Value``」ノードを召喚
![MPC ブループリント セット 召喚.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/b6484ee9-e835-a92b-0a2a-f3c21ddd1f11.png)
+ 引数を設定
    + ``Collection`` -> 作成した``MPC``
    + ``Parameter Name`` -> 上記で設定した``Collection``のパラメータ名（選択すると自動的に候補が出てくる）
    + ``Parameter Value`` -> 変更する値（Vectorなら``Linear Color``構造体、Scalarなら``float``型）
![MPC ブループリント セット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/8ae3fbfd-b2af-67f9-b23b-70d46440f79a.png)

<details><summary>取得したい場合</summary>

「``Get Vector Parameter Value / Get Scalar Parameter Value``」ノードを使用する
![MPC ブループリント ゲット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/195df8b4-df82-8bb3-b109-6e09c4b6a997.png)
</details>

---
　下図のように、``MPC``は使用しているマテリアル全てに影響を与えるので、違うアクター（マテリアル）であっても全てのアクタが変更されます。かなり便利だと思いますが、どこからでも変更出来るので怖くもありますね。
　といっても、自分としては「１マテリアル１MPC」と考えているので、マテリアルを跨ぐ使い方はあまりしたくない...というようりも、跨ぐ必要性に駆られていないだけなのですが...。
![MPC システム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/7dc7f7bd-ba9c-e492-cd1e-df1f47d862f4.png)
　「マテリアルを使用したアクター毎に変更したい」といった場合は、下記の[マテリアルダイナミックインスタンス](#マテリアルダイナミックインスタンス)を使う事になります。むしろこちらの方が多いと思いますが...。

### 参考サイト

https://www.unrealengine.com/ja/blog/material-parameter-collections

http://kagring.blog.fc2.com/blog-entry-391.html

https://hat0xaa.hatenablog.com/entry/2019/03/21/173336

## マテリアルダイナミックインスタンス
　マテリアルダイナミックインスタンス[^0]（以下**MDI**）を一言で言うなら「マテリアルの値を動的に変更可能な機能」です。マテリアルを使うなら「コレ！！」といった技術になります。
　``MDI``は**マテリアル専用の変数**みたいなもので、マテリアルに依存し各アクター毎に自由に動的変更可能な機能です。設定出来るパラメータは「スカラー（float）・ベクター（float4/Linear Color）・テクスチャ（Texture）」が可能です。勿論、動的に設定が可能ですが、取得も可能です。何気にテクスチャも変更できるのはありがたいですね。

![MDI.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/6b61a69f-3dc6-f2b2-5c22-26b0cd4a242e.gif)

[^0]: 公式的には「マテリアルダイナミックインスタンス」なんですが、普段使いでは「ダイナミックマテリアルインスタンス」なんですよね。ですが、今回は公式の言い方で統一します。

### マテリアル側
+ ノードを追加
    + 「右クリック ＞ パラメータ ＞ ``VectorParameter`` / ``ScalarParameter``」でノードを召喚
    ![MDI マテリアル 追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/381c9740-b1dc-7444-e085-c1cb10e3962a.png)
    + もしくは「右クリック ＞ 定数 ＞ ``Constant`` / ``Constant2~4Vector``」で定数を追加、「定数を右クリック ＞ ノードアクション ＞ パラメータに変換」でパラメータに変更
    ![MDI マテリアル 追加2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/6f87301d-527c-2027-f08d-9425aee59f0a.png)
    + または、**圧倒的に便利**なショートカット「<font color=red>**S(scalar) + 左クリック**</font>」と「<font color=red>**V(vector) + 左クリック**</font>」で**一発**で召喚可能
+ 「詳細 ＞ 一般 ＞ ``Parameter Name``」で名前を付ける（もしくはノードをクリックして``F2``）
+ 「詳細 ＞ マテリアルエクスプレッションパラメータ ＞ ``Default Value``」で初期値を設定
+ 「詳細 ＞ マテリアルエクスプレッション ＞ ``Group``」で**グループを設定しておくべき**
    + 設定しておかないと、後述するマテリアルインスタンスで``Global Scalar / Vector Parameter``になってしまう

### ブループリント側
#### 作成
+ 「レンダリング ＞ マテリアル ＞ ``Create Dynamic Material Instance``」でノードを召喚
+ 引数の設定
    + ターゲット -> 作成したマテリアルを使用するプリミティブオブジェクト（``Static Mesh Component``など）
    + Element Index -> 複数個のマテリアルを使う場合は設定する必要がある
    + Source Material -> ``MDI``化したいマテリアル（ターゲット側に``MDI``化予定のマテリアルを既に設定している場合は指定しなくても可）
    + Optional Name -> デフォルトのまま（使った試しが無い）
![MDI ブループリント 作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/2bbbbcb2-552c-1924-f80a-166ad9806c71.png)
+ **戻り値（``Material Instance Dynamic``型）を変数化**[^1]
+ 「レンダリング ＞ マテリアル ＞ Set Material」でノードを召喚（ターゲット側に``MDI``化予定のマテリアルを既に設定している場合は不要）
![MDI ブループリント 作成2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/16d106c6-9238-71c9-a743-5eaf7e5c34f1.png)

[^1]: ``MDI``の値を変更する時は、この戻り値を使用するためです。変更するタイミングが初期化以外なら、変数化しないと変更できません。※ 今回はテストなので戻り値のピンの値をそのまま使っています（本来はローカル変数にしておくべきかと...）

#### 変更
「レンダリング ＞ マテリアル ＞ ``Set Vector / Scalar / Texture Parameter Value``」でノードを召喚

:::note warn
「状況に合わせた表示」をONにしている場合、Material Instance Dynamic型から右クリックしないと、MPC側のノードが表示されるので注意
:::

![MDI ブループリント 変更.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/44dbae24-920a-aa41-518e-f99144d1be6a.png)

<details><summary>取得したい場合</summary>

「``Get Vector / Scalar / Texture Parameter Value``」ノードを使用する
![MDI ブループリント 取得1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/99e2db73-67e9-6c35-09ac-679891397843.png)
もしくは、「``Get Vector / Scalar / Texture Parameter Values``」ノードを使用する（簡単に確認はしたが要検証）
![MDI ブループリント 取得 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/4985cb2b-4baa-b6ba-f66b-59b06435fc9f.png)
</details>

##### 引数の設定

+ ターゲット -> ``Create Dynamic Material Instance``の戻り値（``Material Instance Dynamic``型）
+ ``Parameter Name`` -> [マテリアル](#マテリアル側)で追加したパラメータの名前

:::note warn
Name型（直接指定）なので打ち間違いに注意
:::
+ ``Value`` -> 変更したい値（各ノードに応じた型（Scalar = ``float``型 / Vector = ``Linear Color``構造体 / Texture = ``Texture``オブジェクト参照））

---

　下図のように``MDI``はマテリアル自体の値を変更をする為、アクターを個別に変更可能です。イメージとしては「スポーンしたアクター毎にマテリアルを持っている」が合っているでしょうか。
　初めて使う前は結構躊躇していたのですが、いざ使ってみると全然簡単という事に気付きました。そのためか、私自身この機能をよく使っています。
![MDI システム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/97ba7eda-e0e2-590f-b980-aefb53769f27.png)
　動的に変化する場合はこの機能を使うと非常に便利です。逆に、「別に動的じゃなくて静的でいいんだよ」といった場合は、下記の[マテリアルインスタンス](#マテリアルインスタンス)を使用します。

### 参考サイト

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/MaterialInstances/

https://qiita.com/unknown_ds/items/4173d42f8624e70d6475

http://manabibeya.com/ue4tutorial/intro10/

## マテリアルインスタンス
　マテリアルインスタンス（以下**MI**）を一言で言うなら「マテリアルの値を動的に変更可能な機能」です。こちらもよく使います。プログラム的には「派生クラス」のイメージが近いです。
　基本的には[マテリアルダイナミックインスタンス](#マテリアルダイナミックインスタンス)の静的バージョンの認識で大丈夫です。

:::note warn
特に、コンポーネントにマテリアルを設定する時は、常に**MI**化して設定するべきです</font>[^2]。
:::

![MI サンプル3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/c6f42736-0c79-e98c-4d52-4a7c69cb71be.png)
　``MI``なのですが、「個別に作成せずある程度自由な形でマテリアルを作成し、``MI``を使って個別に設定する」といった使い方も出来ると思います。つまり、色違い・テクスチャ違いを実装するのに色違い毎にマテリアルを作成せず、ベースのマテリアルを``MI``化したものを個別に設定するという事です。この考えは派生と同じですよね。

[^2]: ``MI``化する利点は「コンパイル時間の短縮・作業の簡易化・シェーダーサイズ軽量化」などが挙げられます。

### 作成
+ 「コンテンツブラウザ ＞ 右クリック ＞ マテリアルアクション ＞ マテリアルインスタンスを作成」で新規作成
![MI 作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/74535da0-acaf-8153-29e9-7db86639cf40.png)

### 追加
　[マテリアルダイナミックインスタンス](#マテリアルダイナミックインスタンス)の「マテリアル側」と同じです。つまり、``VectorParameter / ScalarParameter``で対応します。

### 変更
+ 「詳細 ＞ パラメータ グループ ＞（設定したグループ名）＞（設定したパラメータ名）」から、変更したいパラメータのみチェックを付けて値を変更
    + チェックのON/OFFで値を保存しつつ無効化する事も可能
![MI 変更.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/7d208f8e-0fc2-e10b-d60c-fc6e39553e4d.png)
こんな感じで簡単に気持ち悪い岩マテリアルが出来ました。

---

　下図のように``MI``はマテリアル自体の値を変更出来ますが、あくまで静的な変更です。ですが、同じアクターでも``Set Material``関数を用いて複数個の``MI``を用いれば、疑似的に動的な変更が可能ではあります。あくまで「１つの``MI``では静的変更になるよ」という事です。
　UE4のマテリアルを使い始めて真っ先に使う機能ではないのでしょうか？やはり、使い方自体はとてもシンプルなのがいいですよね。
![MI システム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/651cce18-a96e-abee-2f3b-413bcf456879.png)

　少し変わったパラメーターとして、「``StaticBoolParameter``・``StaticSwitchParameter``・``StaticComponentMaskParameter``」といったものがあります。名前の通り、静的に決定し、実行中に変更不可のパラメーターノードです。つまり、「``MI``上で静的に変更する専用ノード = コンパイル時にシェーダーコードが確定するノード」です。少し面白い？ノードです。
![Static パラメーター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/c746eab1-ef26-fafa-e8fa-e1e83114f2d7.png)

### 参考サイト

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/MaterialInstances/

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/HowTo/Instancing/

https://historia.co.jp/archives/1174/

https://www.slideshare.net/EpicGamesJapan/epic-games-japan-ue4dd

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/ExpressionReference/Parameters/

## マテリアルファンクション
　名前の通りのマテリアル専用の関数です。例えば、複数個のマテリアルを作成している場合、同じような処理をまとめたい時に使用します。

### 作成
　「コンテンツブラウザ ＞ 追加 ＞ マテリアル・テクスチャ ＞ マテリアル関数」で作成します。
![MF 作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/b8a745e6-41cb-41d1-d086-272dbeddc433.png)

### 編集
　デフォルトでは最初から「Input In(Vector3)」と「Output Result」が既にあります。いわゆる、引数と戻り値になります。引数を追加したい場合は「右クリック ＞ 関数 ＞ ``FunctionInput``」、戻り値を追加したい場合は「右クリック ＞ 関数 ＞ ``FunctionOutput``」で可能です。
![MF 引数3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/618c5d05-2d61-4fa9-7539-0e3091c35542.png)
　引数の設定はノード詳細から
+ 「マテリアルエクスプレッションファンクションインプット ＞ ``Input Name``」-> 名前
+ 「``Input Type``」-> 型
+ 「``Description``」-> 引数の説明表示（後から見ても分かるように記述しておくべきです）
+ 「マテリアルエクスプレッション ＞ ``Sort Priority``」-> 関数を呼び出す側の順番指定
![MF 引数 設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/f9c73686-5aa6-1773-7245-1f5e39efe394.png)

　同じように、戻り値の設定はノード詳細から
+ 「マテリアルエクスプレッションファンクションアウトプット ＞ ``Output Name``」-> 名前
+ 「``Description``」-> 戻り値の説明表示（後から見ても分かるように記述しておくべきです）
+ 「マテリアルエクスプレッション ＞ ``Sort Priority``」-> 関数を呼び出す側の順番指定
![MF 戻り値.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/baffa17b-b3e3-44d0-5011-a92428167274.png)

　次に、マテリアル自体の設定は何も選択していない状態で詳細から
+ 「マテリアルファンクション ＞ ``Description``」-> 関数の説明表示（後から見ても分かるように記述しておくべきです）
+ 「``Exposes to Library``」-> 関数呼び出し時の検索欄に表示するか？
+ 「``Library Categories Test``」-> 関数呼び出し時の検索欄でのカテゴリー
![MF 設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/17fdb6a2-529e-c3cc-3257-6cc7057ca88f.png)

### 参考サイト

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/Functions/

https://limesode.hatenablog.com/entry/2016/03/16/233054

## マテリアルのノード
### Customノード
　DirectXでお馴染みのHLSLコードで記述する事が可能なノードです。例えば、見た目を簡略化したり、マテリアルエディタ上では実装不能なループ処理を記述する場合に使います。ポストプロセス系のマテリアルなど（例：自作ブルーム）はよく使うのかな？と思います。
　「右クリック ＞ カスタム ＞ Custom」で``Custom``ノードを召喚可能です。
![カスタムノード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/a073e199-3dae-d140-41bd-927a48b3743e.png)
　特に重要なのが、ネット上に存在するコードをそこそこ簡単に引用出来ます[^3]。例として、「[Shadertoy](https://www.shadertoy.com/ "DirectX11を弄っていた時からお世話になっているサイトです")・[NieR:Automata Glith Effect](https://sawcegames.com/en/post/nier-automata-glitch)」などのサイトにあるコードを使わしてもらう場合などが上げられます。
　Shadertoy上のコードを移植するには、そもそも``GLSL``なので``HLSL``に変換する必要があります。その時は「[GLSLをHLSLに書き換える - Qiita](https://qiita.com/kitasenjudesign/items/89297f239059662cd38e)」が非常に参考になります[^4]。変換する時に「VSCode」を使うと、まとめて置き換え出来たり、型に色が付いたりするので出来るのでオススメです。そして、変換したコードを``Custom``ノードに貼り付けた上でキチンと動けば完了です。

[^3]: 個人的にゲームを作成して、SNSに動画を公開する程度なら問題ないと思いますが、少なくとも使用させてもらったURLなどはコメントなどとして記述しておくべきです。
[^4]: ごく稀に、マクロでHLSL/GLSLを切り替えて使えるコードが存在するのですが、基本的にはこちら側で変換する必要があります。

#### 使い方
　詳細な使い方はここには載せないので下記を参考にして下さい。ノード自体の使い方や引数・戻り値の設定方法なども記述されています。個人的に注意すべき点が「<font color="Orange">**引数の名前（スペル）は大文字・小文字まで完全一致させる必要がある**</font>」です。でないとエラーが発生します。後、UnrealEngine用の変更があったりするのでその点も注意です。例えば
+ 「``float2 p = fragCoord/iResolution;``」→「``float2 p = fragCoord;``」
+ 「``float3 col = texture( iChannel0, uv ).xyz;``」→「``float3 col = iChannel0.Sample( iChannel0Sampler, fragCoord ).xyz;``」
    + テクスチャのサンプルの仕方については「[Unable to sample custom texture inside custom expression - UNREAL ENGINE FORUMS](https://forums.unrealengine.com/t/unable-to-sample-custom-texture-inside-custom-expression/284601/5)」を参考にして下さい。

---

https://kinnaji.com/2020/12/24/newmaterialcustomnode/

https://qiita.com/dgtanaka/items/13e643fafeb007961601

https://pafuhana1213.hatenablog.com/entry/2015/02/15/152312

### Float2, 3, 4系について
　Float4での一例なのですが、例えば...
+ 分解したい -> ``BreakOutFloat4Components``
+ 作成したい -> ``MakeFloat4``
+ 変換したい -> ``ComponentMask``
    + ややこしいのが、正式名は``ComponentMask``なのに表示名が``Mask(~)``になってしまう点なんですよね。といっても、検索欄で``mask``と入力しても出てくるので良いのですが...。
    + マスクする値を変更するには、ノードの詳細から変更可能です。
![ComponentMask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/b8bfaf5b-4991-e9a7-6d8e-2368113086f6.png)
+ 値を確認したい（デバッグしたい）-> ``DebugFloat4Values``
    + 　「マテリアル内でデバッグしたい！」という時に使えるのが「``DebugScalar/Float2/Float3/Float4Value``」ノードです。何気に便利なのですが、あまり有名でない気がします。
![DebugFloat4Values.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/8d0c14a2-1ffc-0f4f-efba-1cee8367ef64.png)

![Float4系ノード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/7f77a834-bd40-60c4-307a-48d5c0c9f091.png)

#### 参考サイト

https://unrealengine.hatenablog.com/entry/2018/02/19/230932

### その他の使えるノード
+ OneMinus
    + 1から引いた数値になり、Subtract(1, X)と同じです。
    ![OneMinus.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/ddd3e9bb-8060-d075-7e34-2e271a73597f.png)
+ TexCoord
    + テクスチャのUV座標を取得します。テクスチャのスケールを変更する時などに使います。
    ![TexCoord.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/58ec030b-4b74-40c0-ca16-0371257a91a4.png)
+ Time
    + マテリアル内での時間経過を取得します。Pannerなどに使用したり色々使えます。
![Time.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/a5accdc2-203a-b0cf-ed81-7ebb2e655ec7.gif)
+ Rotator
    + UV座標を回転する計算を行います。
![Rotator.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/9de7e372-fc60-824d-dd57-1ca2ee22dd16.gif)

　まだまだ沢山紹介出来るノードはありますが、もっと知りたい方は下記サイトを覗いてみて下さい。

---

https://historia.co.jp/archives/4559/

https://qiita.com/herorinusu/items/fd44a701c86bf4b7bb3e

https://qiita.com/kai_yoshida/items/02bfff36d37aa4cbb2e9

## 便利なショートカット
　全て「キー ＋ 左クリック」の形になります。その為、左クリックは省略します。
| ショートカットキー | 内容 |
|:-:|:-:|
| <font color=red>**A**</font>  | 足し算  |
| <font color=red>**D**</font>  | 割り算  |
| <font color=red>**M**</font>  | 掛け算  |
| 1 ~ 4  | float～float4の定数（Constant, Constant2/3/4Vector）  |
| <font color=red>**T**</font> | テクスチャサンプル |
| O  | OneMinus（1-x）  |
| <font color=red>**S**</font>  | スカラーパラメータ  |
| U  | テクスチャUV座標  |
| <font color=red>**V**</font>  | ベクターパラメータ  |

残念ながら、引き算はハブられてしまいました。引き算よりもOneMinusの方が使う機会が多いからですね？

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/HowTo/Placing_Expressions_Functions/

[目次へ](#一覧)

# コリジョン（当たり判定）
　若干UE4の当たり判定がめんどくさく感じるのは気のせいでしょうか？かなり簡単に実装出来るのですが...何故か使いづらさを感じるこの頃...。

## Block, Overlap, Ignore
　いわゆる、「衝突・検知・無視」になります。
+ Block
    + ゲームに登場する物理的に衝突がある物体が``Block``（衝突）になります。壁だったり、ボールだったりと実際に触れる物が当てはまります。現実世界での当たり判定ですね。
![COL_collideEvent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/8c818619-774e-d00c-c00c-f22e41e92f4f.png)
![Block.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/420e461d-133d-2e12-8d7f-7b234faf7bb3.gif)
+ Overlap
    + これは判定用（センサー的なもの）として使うのが大半だと思います。その為、オブジェクト自身は貫通し、「当たり始め / 終わり」の二通りの関数が用意されています。現実世界で言うなら、自動改札機や自動ドアのセンサー部分に当たります。
![COL_overlapEvent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/e9637957-89a6-7ada-b8bd-c2191187b5a5.png)
![Overlap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/1a953b72-424c-03fb-d428-dd025ec65e72.gif)
+ Ignore
    + 文字通りの「無視」になり、物理世界には関与しないという事です。例えば、装飾用のオブジェクトやエフェクトなどが当てはまります。
![COL_ignore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/c4694c06-2975-d7b0-0479-e5aedda921e7.png)
![Ignore.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/2240901e-663e-684c-cdb0-acc6aa73e787.gif)

※ 画像は[コリジョンの概要](https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Physics/Collision/Overview/)から参照してきました。

### プログラム上でのお話
　とりあえず変更するには「詳細 ＞ コリジョン ＞ コリジョンプリセット ＞ ``NoColision / BlockAll / OverlapAll``」で変更可能です。コリジョンプリセットの詳細に関しては後述します。
![コリジョンプリセット 簡易.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/0a3e5b33-5016-cd9a-e740-e1485ec7dda0.png)
　当たり判定をブループリント側で取得するには、「詳細 ＞ イベント ＞ ``On Component Hit / Begin Overlap / End Overlap``」の「+」をクリックすると関数が出現した上で、関数へとフォーカスします。既に存在している場合は「+」が「ビュー」へと変化します。
![On Component Hit-Begin Overlap-End Overlap 追加-ビュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/8d0eac9f-aba9-d9c3-b74f-a4d43faa201e.png)
+ 関数一覧
![On Component Hit-Begin Overlap-End Overlap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/49587cde-6fba-2524-d1e4-de135f3b9108.png)

### 注意点
　「Overlap」についてなのですが、<font color="red">検知したいオブジェクト**両方とも**「Generate Overlap Events」にチェックを入れる必要があります</font>。
![コリジョン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/891d1b37-5af3-9b53-adf7-a66835463aa8.png)
　更に、<font color=red>物理シミュレーション中に「Hit」判定を取りたい場合は、「Simulation Generates Hit Events」にチェックを入れる必要があります</font>。物理シミュレーションは「詳細 ＞ 物理 ＞ ``Simulate Physics``」をONにしている場合です。
![物理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/86942577-edf7-bccd-08d7-cec346d73fd1.png)

### 参考サイト

https://shivat.hatenablog.com/entry/2016/05/12/115304

https://zenn.dev/daichi_gamedev/books/unreal-engine-5/viewer/collision-hit-overlap

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Physics/Collision/

## コリジョンプリセット
+ ``Collision Enabled``
    + ``No Collision`` -> 無効化
    + ``Query Only`` -> 当たり判定専用（Overlap専用）
    + ``Physics Only`` -> 物理挙動専用（検出不要なキャラクターなど）
    + ``Collision Enabled`` -> 通常（当たり判定・物理挙動）
![Collision Enabled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/64357809-476a-5403-3b18-f154766e021f.png)
+ ``Object Type``
    + デフォルトでは６種類あると思います。これはオブジェクトのタイプに合わせて設定を変更するべきです。ただ、変更は任意になります。
![Object Type.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/2e1df06b-370e-888c-bfb2-022f67cdd351.png)
+ トレース反応
    + 後述する、``Line Trace by Channel``などの関数に使います。いわゆる、レイキャストなどのトレース処理で判別するために使用します。簡単に言えば**タグ**になるでしょうか。
![コリジョンプリセット トレース応答.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/3a555857-9ef4-17a3-ed6e-08aa88344317.png)
+ オブジェクト反応
    + 通常の当たり判定で使用する判別用タグみたいなものです。主にコレを使い分けて当たり判定を管理などします。
![コリジョンプリセット オブジェクト反応.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/b5b8f12c-a8b3-14bb-2a06-61d5f448b443.png)

　勿論、コレらの設定はBP側で変更可能です。一例ですが、一時的に当たり判定を無くしたいといった場合は、下図のようになります。
![当たり判定 OFF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/b5341056-8842-5c45-04d0-b36901dc5128.png)

### コリジョンプリセットの追加
　実はプリセットは独自に追加する事が可能で、「プロジェクト設定 ＞ エンジン ＞ コリジョン」から追加・編集が可能になっています。詳細は下記サイトをご覧ください。
![プリセット新規追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/b6fc8604-ffa0-a1c5-7097-c17bf75d8a11.png)

https://tamfoi.hatenablog.com/entry/2017/01/26/230114

### 参照サイト

https://unrealengine.hatenablog.com/entry/2014/07/10/231035

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Physics/Collision/Reference/

## メッシュの判定
　例えば、独自にスタティックメッシュのアセットを読み込んだとして、それらの当たり判定をスタティックメッシュ単体に付与する事が可能です。読み込んだスタティックメッシュのアセットを開き、「コリジョンのタブ ＞「～を追加」」で簡易的なコリジョンを追加する事が可能です。
　簡易的なコリジョンを調整する機能として、「コリジョンのタブ ＞ オートコンベックスコリジョン（凸型分解）」を使い、当たり判定の詳細を弄ることが可能です。
![メッシュ コリジョン オードコンベックスコリジョン(凸型分解).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/a65e4251-3f93-207e-d352-a9f1882ca160.png)
　ですが、例えば円柱内に空洞がある場合など、うまくいかない場合があります。その場合は、「詳細 ＞ コリジョン ＞ ``Collision Complexity`` ＞ ``Use Complex Collision As Simple``」を選択する事でメッシュに完全一致する当たり判定を設定出来ます。表示されない時は、ウィンドウ左上にある「表示 ＞ 複雑なコリジョン」を選択する事で表示されます。
![Use Complex Collision As Simple.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/db88d414-156c-ed30-4a77-d68aff89948a.png)
　正確な分、重たくなりますし、物理シミュレーションに対応していないというデメリットも存在するので地形などのオブジェクトにしておくのが無難だと思います。適用した結果が下図になります。
![円柱 当たり判定 比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/1fe4301e-71e8-2498-95a8-3dd5c2353ef4.png)

### 参考サイト

https://docs.unrealengine.com/4.27/ja/WorkingWithContent/Types/StaticMeshes/HowTo/SettingCollision/

https://historia.co.jp/archives/10622/

https://historia.co.jp/archives/20498/

## トレース系の判定
　少し注意点があるライントレース（レイキャスト）系のお話です。下図の図形は<font color=blue>**青が「Overlap」**</font>、<font color=gold>**黄色が「Block」**</font>になっています。

### Line Trace By Channel
　限定的なレイトレースを実行するノードです。

:::note
特徴
**トレース応答**を判断基準にしている為、**「Overlap」は反応せずに「Block」のみ反応**します
:::

![Line Trace By Channel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/67a402d3-86ab-49eb-7763-beb156f2733f.gif)

### Multi Line Trace By Channel
　Line Trace By Channelの複数感知版ですが、そこそこややこしいのが、このノードです。

:::note
特徴
+ 「Blockオブジェクト」までに存在する複数個の「Overlapオブジェクト」を**感知**します
+ 「Blockオブジェクト」が感知出来ない場合は「Overlapオブジェクト」を**無視**します
:::

![Multi Line Trace By Channel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/028e1305-6329-03e2-85a0-53b28914e7a2.gif)

### 参考サイト

http://kagring.blog.fc2.com/blog-entry-229.html

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Tracing/HowTo/SingleLineTraceByChannel/

https://unrealengine.hatenablog.com/entry/2014/10/11/003032

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Tracing/HowTo/MultiLineTraceByChannel/

### Line Trace For Objects
　通常イメージするレイトレースはこのノードになると思います。

:::note
特徴
上記ノード（～ Channel）と違い、判断する基準が「**Object Type**」になっています。なので、その点を気にしないと反応しない事になりかねません。ただし、引数が配列なので複数タイプを判断可能です。
:::

![Line Trace For Objects.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/d5fee887-297a-fd44-f506-393a0ed50d75.gif)

### Multi Line Trace For Objects
　このノードも同じく「Object Type」を判断基準にしている場合のレイトレースになっています。``Multi Line Trace By Channel``よりもシンプルに反応してくれます。
![Multi Line Trace For Objects.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/7d70c45c-1472-ffb7-fe9a-21e1654f3e81.gif)

### 参考サイト

http://kagring.blog.fc2.com/blog-entry-230.html

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Tracing/HowTo/MultiLineTraceByObject/

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Tracing/HowTo/SingleLineTraceByObject/

[目次へ](#一覧)

# AI
　敵などに使われるAIです。基本的には[ビヘイビアツリー](https://thinkit.co.jp/article/10012)で実装する事になります。詳細は下記サイトを覗いて見て下さい。というより、公式・先人の方々が十分説明されているので、詳細についてはあまり触れません。

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/

https://historia.co.jp/%3Fp%3D1102

## AIの作成
　まず、~~何も考えず~~AI三点セット（ブラックボード・ビヘイビアツリー・AIコントローラー）を作成します。
![AI 作成 一覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/6b80fc6b-030e-1ed7-def6-d70060a74c9d.png)
　次に、AIを使用したいキャラクターを開き「詳細 ＞ ポーン ＞ ``AI Controller Class``」に作成したAIコントローラーを設定します。

:::note warn
「詳細 ＞ ポーン ＞ ``Auto Possess AI`` ＞ ``Placed in World or Spawned``」に設定してください。でないと「AIが動かねぇ～」という事態になりかねません。
:::

![AI コントローラー 設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/2a9b621b-4dc0-de2e-c91b-7322eb08fb7f.png)
　次に、ビヘイビアツリーの「詳細 ＞ ``BEHAVIORTREE`` ＞ ``Blackboard Asset``」にブラックボードをセットして、AIコントローラー側で「Run Behavior Tree」ノードを呼び出して完了です。詳しい実行方法は下記サイトをご覧ください。

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/BehaviorTreeQuickStart/

https://ken26u.blog/ue4/2020-07-14-024209/2020/07/14/

## ブラックボード
　初見だと、「ナニコレ？」となること間違いなしの機能ですが、自分なりの解釈では「インターフェース機能でアクセスするAI専用の構造体」です。例えば、キャラクター情報やビヘイビアツリー全体でアクセスする要素だったり、デコレーターノードで使用したりなど、色々な用途で使用すると思います。詳しい説明は下記サイトを覗いて見て下さい。ブラックボードの立ち位置は下記サイトの画像が参考になります。

https://hahanha-create.com/2020/01/11/%E3%80%90ue4-ai%E5%85%A5%E9%96%80%E3%80%91%E7%B0%A1%E5%8D%98%E3%81%AAnpc%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6ue4%E3%81%AEai/

　ブラックボードにアクセスするには「``Set Blackboard Value as ~``」で設定し、「``Get Blackboard Value as ~``」で取得します。「Key」に関しては「変数へ昇格」で変数化（``Blackboard Key Selector``構造体）した上で、「詳細 ＞ 変数 ＞ インスタンス編集可能」をONにしておいて下さい。
![AI ブラックボード 設定・取得.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/23cd38f2-bbb3-1888-d831-35c7bd3eccb4.png)
　すると、ビヘイビアツリー側で変数の設定が可能になり、候補にBBのキーが表示されます。また、違う方法も存在するのですが、その方法は「Name型」で直接指定となっているので、関連付けが可能なこちらのやり方をオススメします。
![AI BB 変数 関連付け](https://user-images.githubusercontent.com/52647796/157348076-f05b0979-04b9-4ec8-b802-adb86275c88e.png)

## ビヘイビアツリー
　UnrealEngine君の一押しのAIシステムですが、いくつかの点に気を付ければ普通に使いやすいシステムだと思います。ともかく、資料も充実していますし、[公式サイト](https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/)での日本語の説明も分かりやすくまとめてあるので、初めて使う方も安心して使う事が可能なはずです。
![AI ビヘイビアツリー 全体図（仮）](https://user-images.githubusercontent.com/52647796/158055410-a1dc6a5b-a50f-42d1-a222-a149c7f7a214.png)
※ 上図はかなり適当なのでサンプルのようなものです

### サービスノード
+ 説明
    + 「ブラックボードの更新用ノード」に当たります
+ 使い方
    + 「イベント Recive Tick AI」をオーバライドして更新処理
    + 「イベント Receive Activation AI」をオーバライドして初期化処理
    + 「イベント Receive Deactivation AI」をオーバライドして終了処理
![AI BTS 関数一覧](https://user-images.githubusercontent.com/52647796/158050819-38414dd6-2c50-4657-a921-1c55fa0c9d15.png)
+ 注意点
    + 順番によっては呼ばれるのが最後になる場合がある（特に関数）
    + 「詳細 ＞ ``Call Tick on Search Start``」をONにするだけで順番が変わる
    + 「詳細 ＞ ``Interval``」で呼ばれるタイミングを変更できる
    + 「詳細 ＞ ``Random Deviation``」で呼ばれるタイミングにランダム性が付与される
![AI BTS 詳細](https://user-images.githubusercontent.com/52647796/158052299-dbe2aef7-a6c0-46ec-985d-6b70b1a7290a.png)

### デコレーターノード
+ 説明
    + 「ビヘイビアツリーの条件式ノード」に当たります
+ 使い方
    + 「Perform Condition Check AI」をオーバライドして戻り値で可否判断処理を行う
    + 「イベント Receive Tick AI」をオーバライドして更新処理
    + 「イベント Execution Start AI」をオーバライドして初期化処理
    + 「イベント Execution Finish AI」をオーバライドして終了処理
![AI BTD 関数一覧](https://user-images.githubusercontent.com/52647796/158053884-e1350866-5bb0-466f-9568-121f012f6d51.png)

:::note warn
「詳細 ＞ フローコントロール ＞ オブザーバーを中止」を変更すると、挙動が変わったりするので注意
:::

+ 基本的にはフローコントロールは``Self``でOK
    + 例えば、「このタスクで終了したい」場合で``Both``に設定すると、低優先度（数値が大きい物）が飛ばされるようになる
+ 「詳細 ＞ コンディション ＞ ``Inverse Condition``」は条件を反転する事が可能なので、「～ではない」のような場合に便利

### タスクノード
+ 説明
    + 「ビヘイビアツリーの行動処理ノード」に当たります
+ 使い方
    + 「イベント Receive Execute AI」をオーバライドして初期化処理
    + 「イベント Receive Tick AI」をオーバライドして更新処理
![AI BTT 関数一覧](https://user-images.githubusercontent.com/52647796/158053648-39c91e60-4081-424c-b4f9-951c2f98d204.png)

:::note warn
「**Finish Execute**」ノードの呼び忘れに注意。でないと、永遠にタスクが終わらない事に...。
:::

### ノードの移動
　何気に便利なデコレーターとサービスノードのドラッグアンドドロップ。あまり紹介されていない気がするのは、気のせいでしょうか？
![ビヘイビアツリー ノード D D](https://user-images.githubusercontent.com/52647796/158114179-c50f6cb4-89e0-4562-9193-f6f0b46ac814.gif)

### 参考サイト

https://bintololab.com/ue4-enemy-battle-ai

https://ken26u.blog/ue4/2020-07-14-024209/2020/07/14/

https://hahanha-create.com/2020/01/11/%E3%80%90ue4-ai%E5%85%A5%E9%96%80%E3%80%91%E7%B0%A1%E5%8D%98%E3%81%AAnpc%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6ue4%E3%81%AEai/

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/

https://historia.co.jp/%3Fp%3D1102

https://historia.co.jp/archives/10221/

https://qiita.com/4_mio_11/items/9e8af2ce82ee2a7625b5#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%B0

https://qiita.com/4_mio_11/items/d622b3bcbf1489ab644b

## ビヘイビアツリー自体を停止したい
　``Stop Logic``ノードを使う事で可能。例えば、プレイヤーが死亡した時にAIを動かしたくない時に使えます。
![AI 停止](https://user-images.githubusercontent.com/52647796/158092983-eff942a4-ee87-47a1-be13-f267d275baa7.png)

https://unrealengine.hatenablog.com/entry/2017/06/14/005914

## ビヘイビアツリーのデバッグ
### 全体的な流れ
　通常のブループリントと同じ「F9」でブレイクポイントを置く事が可能です。デバッグ状態になると、簡単なタスクの動きを監視する事が可能で、赤線は前回の流れを表し、白線は現在の流れを表します。ただし、**タスク毎にしか止まらず**、「デコレーター」や「タスクまでの途中経過（セレクター）」で停止する事は出来ません。その場合は内部のブループリントでブレイクポイントを置く必要があります。
![AI ビヘイビアツリー デバッグ](https://user-images.githubusercontent.com/52647796/158094559-2732ef61-e9a0-41ed-b0b9-5719712f64bf.png)
　勿論、ブレイクポイントを設定していない状態で実行すると、リアルタイムでAIの動きが表示されます。
![ビヘイビアツリー デバッグ](https://user-images.githubusercontent.com/52647796/158098233-050c16e7-36a4-453a-b31e-62c0bb26340c.gif)

### デコレータノード
　「じゃあ、全くデコレーターのデバッグが出来ないじゃん。使えねぇ～」と思うかもしれませんが、ちゃんとデコレーターの挙動は表示されます。具体的には、失敗したデコレータの右側に<font color=red>赤い縦線</font>で表示します。なので、連続でデコレータが存在する場合、かなり分かりやすいと思います。
![AI デバッグ デコレーター](https://user-images.githubusercontent.com/52647796/158095036-220a9797-b02b-462f-88cf-0898c44eb268.png)
　更に言うと、後述するブラックボードデコレーターに関しては具体的な値と結果を表示してくれます。
![AI デバッグ ブラックボードデコレーターノード](https://user-images.githubusercontent.com/52647796/158097442-3bd4ecf6-53e6-4ce5-9259-cce1faf4f246.png)

### キー
　更に、ブレイクポイントに止まった状態で「ブラックボード ＞ キー」には、その時点での値が「現行値」といった形で表示されるようになります。何気に便利な機能です。
![AI デバッグ キー](https://user-images.githubusercontent.com/52647796/158100229-328b4414-ed53-4266-a2ab-87cd9dbfd009.png)

## 標準のデコレーター・タスクノード
　元々搭載されていて使えそうなノードを抜粋して記述します。

:::note
基本的に自作のブループリントノードはC++と比べ遅くなります。パフォーマンスを気にするならばC++で作成するのも考えておいた方がいいかもしれません。
:::

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/BehaviorTreeNodeReference/

### タスクノード
+ ``Move Directly Toward``
    + 指定のアクタか座標へ**直線移動**するノード
    + ナビメッシュ関係なく動きます
    + 詳しくは「[UE4 AIがナビメッシュを使わずに移動する際のTips - Hatena Blog](https://unrealengine.hatenablog.com/entry/2020/06/27/234413)」をご覧ください
+ ``Move To``
    + ナビメッシュを使用して指定の座標へ移動するノード
    + ナビメッシュを使用しているので、途中に存在するオブジェクトを避けて動きます
    + 設定次第で到達不可能な場合でも、出来る限り移動しようとします。
    + ナビゲーションシステムについては「[[UE4] ナビゲーションシステムの概要 - Qiita](https://qiita.com/EGJ-Ken_Kuwano/items/354027f0b41d46c9e640)」を、ナビゲーションメッシュについては「[UE4 ナビゲーションメッシュを作成する - 凛のUE5/UE4とゲーム制作と雑記ブログ](http://kagring.blog.fc2.com/blog-entry-400.html)」をご覧ください
+ ``Play Animation``
    + アニメーション再生を行うノード
    + 何と、ビヘイビアツリー側でアニメーション再生が可能になっています
    + 非常に簡素な敵のアニメーション管理なら使えそうですが、「アニメーションブループリントとビヘイビアツリーの両方で管理をする」といった事は絶対止めた方がいいです
+ ``Play Sound``
    + サウンド再生をするノード
    + ビヘイビアツリー側で再生可能なのですが、まだ``Play Animation``よりかは使う機会が多いのかなと思います
+ ``Rotate to face BB entry``
    + 指定の方向に回転をするノード
    + ``Move Directly Toward``の回転版に当たります
    + ただし、「指定の」
    + 詳細は「[ビヘイビアツリーの「Rotate to face BB entry」タスクについて - Hatena Blog](https://pafuhana1213.hatenablog.com/entry/2015/10/28/232832)」をご覧ください
+ ``Run Behavior``
    + 別のビヘイビアツリーを起動するノード
    + いわゆる、「ビヘイビアツリー in ビヘイビアツリー」です
    + 詳細は「[第四十八回 UE4標準のタスクについて　"Run Behavior"編 - FC2](http://unrealengine4yorozu.blog.fc2.com/blog-entry-48.html)」をご覧ください
    + 動的バージョンもあるのですが、そちらについては「[第0073回 / NPCに仕事をさせる - Ameba](https://ameblo.jp/ue4-master/entry-12632430764.html)」をご覧ください
+ ``Wait Blackboard Time``
    + 待機をするノード（キーで時間指定）
    + もっとシンプルな``Wait``ノードもあるのですが、時間調整が動的に出来ないのでこちらのノードをオススメします
    + 攻撃後や行動後のクールタイムなどに使用します(デコレーター側にクールタイムノードがあるのですが残念ながら静的指定なので微妙...)

![AI ビヘイビアツリー タスクノード](https://user-images.githubusercontent.com/52647796/158111117-fac2b788-72b5-439b-a787-52c8b3368324.png)

---

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/BehaviorTreeNodeReference/BehaviorTreeNodeReferenceTasks/

　簡単に紹介しましたが、非常に簡素なキャラに限ってはビヘイビアツリーだけで、アニメーション・サウンド・行動がコントロール出来るので時短になります。ただし、少しでも複雑になってくる場合は流石に、行動・サウンドぐらいにしておいた方がいいとは思います。

### デコレーター
+ ``Blackboard Based Condition``
    + ブラックボードの値だけで評価をするノード
    + intやfloatなどは大なり小なりなどの比較も可能です
+ コンポジット
    + ``Blackboard Based Condition``以上、ブループリント未満のロジックを組む事が出来るノード
    + 「ブラックボードの単純比較だけでは物足りないが、ブループリントを作成するまでもない」といった場合に使います
    + And, Or, Notの論理演算を使用する事が可能です
+ ``Conditional Loop``
    + 条件が一致している限り常に処理が続くノード
    + ブラックボードの値を使えるので、特定の条件で常に処理しておきたいといった場合は非常に便利だと思います。
    + ルートから再評価という形でも同じにはなると思いますが、このノードを使うと実行範囲が限られるので、バグを減らせるのかもしれません
+ ``Cone Check``
    + コーンの範囲内に目標が存在するかを判定するノード
    + コーンの半径は静的決定ですが、原点・方向・目標（座標指定）はブラックボードの値を使用できます。
    + パッと思いつくのは、ステルスゲームなどの視野内判定に使えると思います
+ ``Does Path Exist``
    + 2点間の座標でナビメッシュを使った経路探索を行うノード
    + 経路探索に複数の種類があり、それぞれ速度と精度が異なります
    + 勿論、ブラックボードの値を使えるので動的決定です
+ ``Is At Location``
    + 指定の位置に存在するかを確認するノード
    + ある程度の誤差を許容する範囲は静的決定ですが、指定の位置に関してはブラックボードの値を使います
    + ナビメッシュを使って、経路と一致しているかを確かめる事も出来ます

![AI ビヘイビアツリー デコレーターノード](https://user-images.githubusercontent.com/52647796/158115962-528f1289-c2a3-45c4-b48a-cb7377690478.png)

---

https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/BehaviorTreeNodeReference/BehaviorTreeNodeReferenceDecorators/

　デコレーターノード側も標準でかなり便利なノードが存在します。なのですが、少し不満点を挙げるならもう少し動的に決定出来るノードを増やしてほしいです。特に、``Cooldown``ノードは本当に思います。動的なら間違いなく便利なので紹介していました[^5]。

:::note
　デコレーターノードの自作ブループリントだけ、速度低下云々については無いみたいです。なので、標準のノードに不便に感じたら、気にせず自作ブループリントノードを作成してしまって構わないと思います。
:::

[^5]: ふと思ったんですが、静的なノードがどれも時間に関係するノードですね。やはり、時間関係となるとややこしくなるのでしょうか？となると、``Wait Blackboard Time``が特殊なだけ？

## ビヘイビアツリーの動き
　AI最後として、割とややこしいビヘイビアツリーの挙動のお話です。というのも、普通に使うだけでも色々ゴチャゴチャな動き方をします。
　例えば、デコレーターノードの「詳細 ＞ フローコントロール ＞ オブザーバーを中止」を``None``以外にしたり、サービスノードの「詳細 ＞ サービス ＞ ``Call Tick on Search Start``」をONにすると関数の呼ばれるタイミングが変わってきます。ホントにヤヤコシイデス。
　大体の流れを理解しておけば、各関数の意味が分かってくると思います。

<details><summary>前提条件</summary>

+ 全てのデコレーターノード
    + 成功判定
    + 「オブザーバーを中止」は``None``
+ 全てのサービスノード
    + 「``Call Tick on Search Start``」はOFF
    + 「``Interval``」は0.001
    + 「``Random Deviation``」を0
        + 「tick every 0.00s」と表示するように
        + いわゆる、「イベント Receive Tick AI」を毎フレーム呼び出し
+ 全てのタスクノード
    + 「イベント Receive Tick AI」で「Delay」ノード（Duration: 0.2）を呼び出し、完了後「Finish Execute」しています
+ 全体図は下の画像になります
![AI ビヘイビアツリー 全体図 呼び出し確認](https://user-images.githubusercontent.com/52647796/158120296-623f7d59-61ed-42d8-b1c9-380de00ebe0f.png)

</details>

### 実行前
　まず、AIコントローラー側で「Run Behavior Tree」ノードが実行されます。恐らく、ノード内の処理でルート直下のサービスノードが呼び出されます。ノード内では「下位ノードの情報取得開始」と「実行開始」が呼び出されます。
![まとめ1](https://user-images.githubusercontent.com/52647796/158505128-e9035f86-05cb-47bc-b90c-eb86f00076f3.png)
1. ``Run Behavior Tree``ノード 実行
    1. <font color=blue>**ルート直下のサービス２ 動作**</font>
        1. イベント Receive Search Start（下位ノードの情報取得開始？）
        2. イベント Receive Activation（実行開始）

### タスク１ 実行
　「Run Behavior Tree」が呼ばれた後、ルート直下のサービスで「更新」と「下位ノードの情報取得開始」が呼び出されます。次に、左下にあるデコレーター（下位ノード）が呼ばれ、「状態判定」が行われて成功した時だけ、同ノードの「実行開始」とタスク・サービスノードの処理が実行されます。
![まとめ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/2e944c2c-7324-eebd-d41f-b4e44a4152fa.png)
　下位のデコレーターから上位のサービスへ移行して、サービスの「更新」を呼び出します。更に、下位のサービスへ移行して「実行開始」を呼び出します。ようやく、下位のタスクの「実行開始」を呼び出してタスクの更新処理を始めます。
![まとめ3](https://user-images.githubusercontent.com/52647796/158510702-b70e5be9-19a2-4e63-8e15-ef10fdb35640.png)
　タスクの更新ですが、最初にタスクの「更新」が呼び出され、サービスの「更新」が呼ばれるのですが、**上から順に呼ばれます**。つまり今回は「サービス２ → サービス１」の順番になります。タスクで「**Finish Execute**」が呼ばれるまで、「タスク１ → サービス２ → サービス１」が繰り返されます。
![まとめ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/3573b89b-feb5-f0f5-e6c9-e5724ca97a5d.png)
　タスクの終了の合図として「**Finish Execute**」関数を呼び出し、デコレーターの「実行終了」が呼び出されます。そして、次点のデコレーターへ移行した上で「状態判定」が行われ、成功した場合のみ「実行開始」が呼び出されます。もし、した場合、実行していたタスクにくっついていたサービスの「実行終了」が呼び出されます。
![まとめ5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/67fa7ed8-6ab9-4e58-4d42-f55367793fbb.png)

<details><summary>文章まとめ</summary>

1. <font color=blue>**ルート直下のサービスノード２ 動作**</font>
    1. イベント Receive Tick（更新処理）
    1. イベント Receive Search Start（下位ノードの情報取得開始？）
1. <font color=red>**下位ノードのデコレータ１ 動作[^8]**</font>
    1. Perform Condition Check AI（状態判定 ※今回は全て成功）
    1. イベント Receive Execution Start（実行開始）
1. <font color=blue>**上位のサービス２へ移行**</font>
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**下位のサービス１へ移行・動作**</font>
    1. イベント Receive Activation（実行開始）
1. <font color=Orange>**タスク１ 動作**</font>
    1. イベント Receive Execute（実行開始）
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**最上位のサービス２へ移行**</font>
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**次の上位のサービス１へ移行**</font>
    1. イベント Receive Tick（更新処理）
1. タスクの更新で「**Finish Execute**」が呼び出されるまで無限ループ
    1. タスク１を更新
    1. 最上位のサービス２を更新
    1. 次点のサービス１を更新
    1. 下位のノードが見つからないので終了 ＝ 最下位
    1. タスクの更新に戻る（1へ戻る）
1. <font color=Orange>**タスク１で「**Finish Execute**」関数を呼び出す（タスク１ 更新終了）**</font>
1. <font color=red>**デコレーター１へ移行へ移行**</font>
    1. イベント Receive Execution Finish（実行終了）
1. <font color=red>**次点ノードのデコレータ５ 動作**</font>
    1. Perform Condition Check AI（状態判定）
1. 失敗した場合
    1. <font color=blue>**実行中のサービス１へ移行移行**</font>
        1. イベント Receive Deactivation（サービス１ 実行停止）
    1. <font color=blue>**一番上へ戻る（サービス２ 動作）**</font>
1. 成功した場合
    1. イベント Receive Execution Start（実行開始）

</details>

[^8]: UnrealEngineのビヘイビアツリーでは、ルート分岐した時は左から実行されます。

### タスク３ 実行
　前項でデコレータ５が状態判定で成功した場合のお話です。最初に、サービス５へ移行した後に「下位ノードの情報取得開始」が呼び出され、デコレータ３へ移行します。そして、デコレータの「状態判定」で「成功」した後に「実行開始」が呼び出されます。
![まとめ6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/02462730-9773-98b7-81c9-dd8b1878b721.png)
　関連が停止したサービス１へ移行した後、実際に「実行停止」が呼び出されます。停止されたので、次点のサービス５へ移行したうえで、「実行開始」と「更新」が呼び出されます。更に、下位のサービス３へ移行して、「実行開始」が呼び出されます。
![まとめ7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/a1bdb64e-3b4d-c6db-70b1-cc6b44403fce.png)
　サービス関係の準備が整ったので、実際にタスク３の「実行開始」と「更新」が呼び出されます。タスク１の時と同じように、上から呼ばれるので「サービス２ → サービス５ → サービス３」の「更新」が呼び出されます。そして、タスク３の「更新」へ戻ります。
![まとめ8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/79e063c0-ada1-4bbe-d9a0-d0c2a5c22427.png)
　終了の合図がタスク３で呼び出され、デコレータ３へ移行した上で「実行終了」が呼び出されます。次に、次点のデコレータ４へ移行して「状態判定」が呼び出されて成功した場合は、デコレータの「実行開始」が呼び出されます。
![まとめ9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/316dd11f-7d0b-0729-0c85-c416fccc701c.png)

<details><summary>文章まとめ</summary>

1. <font color=blue>**サービス５へ移行**</font>
    1. イベント Receive Search Start（下位ノードの情報取得開始？）
1. <font color=red>**デコレータ３へ移行**</font>
    1. Perform Condition Check（状態判定 ※今回は全て成功）
    1. イベント Receive Execution Start（実行開始）
1. <font color=blue>**サービス１へ移行**</font>
    1. イベント Receive Deactivation（実行終了）
1. <font color=blue>**次点のサービス５へ移行**</font>
    1. イベント Receive Activation（実行開始）
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**最下位のサービス３へ移行**</font>
    1. イベント Receive Activation（実行開始）
1. <font color=Orange>**タスク３へ移行**</font>
    1. イベント Receive Execute（実行開始）
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**サービス２へ移行**</font>
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**サービス５へ移行**</font>
    1. イベント Receive Tick（更新処理）
1. <font color=blue>**サービス３へ移行**</font>
    1. イベント Receive Tick（更新処理）
1. <font color=Orange>**タスク３へ移行**</font>
    1. Finish Execute 呼び出し（更新終了合図）
1. <font color=red>**デコレータ３へ移行**</font>
    1. イベント Receive Execution Finish（実行終了）
1. <font color=red>**デコレータ４へ移行**</font>
    1. Perform Condition Check（状態判定 ※今回は全て成功）
    1. イベント Receive Execution Start（実行開始）

</details>

### タスク４ 実行
　大体の流れは「タスク３ 実行」と同じで、呼ばれる場所が異なるだけなので、ある程度は飛ばします。タスクの更新終了（Finish Execute関数を呼んでから）から載せます。
　実行完了の手順は、サービスもデコレータも**下位から上位の順**で呼び出されます。つまり、「デコレータ４ → デコレータ５」・「サービス４ → サービス５」といった感じに「実行終了」が呼び出されます。
![まとめ10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/e0253677-2f94-7803-8763-cfc0607c19f8.png)
　終了手順が呼び出されたら全てのタスクを一巡し終えたので、最初からである「サービス２の更新」から始まります。
　ただし、タスク中に中断・終了した場合などは、最上位から最下位のノード順で「実行終了」が呼ばれます。そして、タスクノードの「イベント Receive Abort」が呼ばれるみたいです。名前の通りですね。

### 「イベント Receive Search Start」ノードについて
　今回は「下位ノードの情報取得開始」だろうと考えて作成しましたが、間違っているならすいません。呼ばれる順番については書かれているサイトはあったのですが、目的そのものについては「コレだ！」といったものは見つかりませんでした。なので、憶測で決めました。ビヘイビアツリー自体が[ツリー構造](https://wa3.i-3-i.info/word1257.html)のはずなので、「下位ノードの検索を行う」前に呼ばれるものだと思ったからです。

https://forums.unrealengine.com/t/what-does-the-event-receive-search-start-node-do/301881

https://historia.co.jp/archives/10221/

---

<details><summary>呼び出しの履歴（テキスト）</summary>

　上記の動きは下記のテキストを書き起こしたものです[^6]。念の為、テキストの方も残しておきます。コメント（//）に関しては独自に追記したものです[^7]。

---

<font color=blue>**サービス2**</font>	Search Start <font color=green>// サービス２ 下位ノードの情報取得開始？</font>
<font color=blue>**サービス2**</font>	Activation <font color=green>// サービス２ 実行開始</font>

<font color=green>// AIコントローラー側でのRun Behavior Tree呼び出し済み</font>

<font color=blue>**サービス2**</font>	Tick
<font color=blue>**サービス2**</font>	Search Start <font color=green>// サービス２ 下位ノードの情報取得？</font>

<font color=red>**デコレーター1**</font>	Condition Check <font color=green>// デコレーター１ 成功判定</font>
<font color=red>**デコレーター1**</font>	Execution Start <font color=green>// デコレーター１ 実行開始</font>

<font color=blue>**サービス2**</font>	Tick

<font color=blue>**サービス1**</font>	Activation <font color=green>// サービス１ 実行開始</font>
<font color=Orange>**タスク１**</font>	Execute <font color=green>// タスク１ 実行開始</font>

<font color=Orange>**タスク１**</font>	Tick
<font color=blue>**サービス2**</font>	Tick
<font color=blue>**サービス1**</font>	Tick

<font color=green>// タスク１ 実行中</font>

<font color=Orange>**タスク１**</font>	Tick
<font color=blue>**サービス2**</font>	Tick
<font color=blue>**サービス1**</font>	Tick
<font color=green>// タスク１ Finish Execute呼び出し</font>

<font color=red>**デコレーター1**</font>	Execution Finish <font color=green>// デコレーター１ 実行終了</font>

<font color=red>**デコレーター5**</font>	Condition Check <font color=green>// デコレーター５ 成功判定</font> 
<font color=red>**デコレーター5**</font>	Execution Start <font color=green>// デコレーター5 実行開始</font>
<font color=red>**デコレーター5**</font>	Search Start <font color=green>// サービス5 下位ノードの情報取得？</font>

<font color=red>**デコレーター3**</font>	Condition Check <font color=green>// デコレーター３ 成功判定</font>
<font color=red>**デコレーター3**</font>	Execution Start <font color=green>// デコレーター３ 実行開始</font>

<font color=blue>**サービス1**</font>	Deactivation <font color=green>// サービス１ 実行終了</font>

<font color=red>**デコレーター5**</font>	Activation <font color=green>// サービス５ 実行開始</font>
<font color=red>**デコレーター5**</font>	Tick

<font color=red>**デコレーター3**</font>	Activation <font color=green>// サービス３ 実行開始</font>
<font color=Orange>**タスク3**</font>	Execute <font color=green>// タスク3 実行開始</font>

<font color=Orange>**タスク3**</font>  Tick
<font color=blue>**サービス2**</font>  Tick
<font color=red>**デコレーター5**</font>  Tick
<font color=red>**デコレーター3**</font>  Tick

<font color=green>// タスク3 実行中</font>

<font color=Orange>**タスク3**</font>  Tick
<font color=blue>**サービス2**</font>  Tick
<font color=red>**デコレーター5**</font>  Tick
<font color=red>**デコレーター3**</font>  Tick
<font color=green>// タスク3 Finish Execute呼び出し</font>

<font color=red>**デコレーター3**</font>  Execution Finish <font color=green>// デコレーター３ 実行終了</font>

<font color=red>**デコレーター4**</font>  Condition Check <font color=green>// デコレーター４ 成功判定</font>
<font color=red>**デコレーター4**</font>  Execution Start <font color=green>// デコレーター４ 実行開始</font>

<font color=red>**デコレーター3**</font>  Deactivation <font color=green>// サービス3 実行終了</font>

<font color=red>**デコレーター4**</font>  Activation <font color=green>// サービス４ 実行開始</font>
<font color=Orange>**タスク4**</font>  Execute <font color=green>// タスク4 実行開始</font>

<font color=Orange>**タスク4**</font>  Tick
<font color=blue>**サービス2**</font>  Tick
<font color=red>**デコレーター5**</font>  Tick
<font color=red>**デコレーター4**</font>  Tick

<font color=green>// タスク4 実行中</font>

<font color=Orange>**タスク4**</font>  Tick
<font color=blue>**サービス2**</font>  Tick
<font color=red>**デコレーター5**</font>  Tick
<font color=red>**デコレーター4**</font>  Tick
<font color=green>// タスク4 Finish Execute呼び出し</font>

<font color=red>**デコレーター4**</font>  Execution Finish <font color=green>// デコレーター４ 実行終了</font>
<font color=red>**デコレーター5**</font>  Execution Finish <font color=green>// デコレーター５ 実行終了</font>
<font color=red>**デコレーター4**</font>  Deactivation <font color=green>// サービス４実行終了</font>
<font color=red>**デコレーター5**</font>  Deactivation <font color=green>// サービス５ 実行終了</font>

<font color=Orange>**タスク１**</font>  Abort <font color=green>// タスクを中断した際に呼び出される（ゲーム終了など） 今回の場合はESCキーで終了</font>

<font color=green>// 全タスク完了</font>

---

</details>

[^6]: 今回の記事で一番メンドクサカッタ作業だったりします。
[^7]: 方法は完全にゴリ押しで、全てのノードの全ての関数にPrintStringでそれぞれ記入します。そして、アウトプットログの出力された文字をWordコピペして、余計なものは消して、ジャンル分け（着色）して...という悲しい方法ですね。更に、それをQiitaの記述方法に変換するという...。

[目次へ](#一覧)

# 次回へ
　予想以上に書く量が多くなってしまい、投稿が遅くなってしまいました。申し訳ありません。実はまだまだ書くことがあるので、次回へ続きます。次回はアニメーションやアセットなどを色々書きます。流石にそこそこの量で分割するので、全３～４回で終わると思います。今回は多すぎたなぁ。今度こそ３月末に上げるぞ～！

---

　２週間で終わらなくて悲しい事態になってしまいました。自分の悪い癖なのですが、「１記事で書き終わりたい欲」が...ダメですね...最初から下書きを分割しとくべきでした。言い訳するなら、全て動くようにUE5上で確認したり、追加で書きたい事が増えたりするんですよね...。