UE5：アセットインポート時に任意の処理を実行する方法

## はじめに
UnrealEngineからはたくさんの恩恵を受けていますが、不満がないこともないです。
その1つがバッチ処理が苦手なことです。
UE4の時代には量産してしまったアクターに項目を追加したり、設定を見直したりしたいときにどう向き合うのが正解なのかわからず、かなり泥臭い対応をしてきました。
特にブループリントメインで開発を行っている場合この問題は顕著であったと思います。

しかし、**UE5になってこの問題は劇的に改善しました**。

https://qiita.com/EGJ-Kaz_Okada/items/ed47a81b0f4b5a9e0111

おかずさんの記事に書かれているエディターユーティリティブループリントやエディターユーティリティウィジェットの紹介がまじでイケてます。
* **C++、Pythonなし、ブループリントだけで完結する**
* **通常のブループリントと同じように各クラスのコンポーネントや変数を編集できる**
* **データテーブルなんかも当然のように参照できるので内容に応じてクラスにパラメーターをセットしたりコンポーネントを追加したりできる**

クラスの参照方法が少し特殊だったり、アクターにコンポーネントを追加しようとしたりすると少し複雑になったりするのですが、基本的に自在にバッチ処理ができるようになりました。
オフラインで動作するので多少処理が冗長でも良いかという気軽さもあってすごく使いやすいです。

今回の記事ではエディターユーティリティブループリントの詳細には触れませんので、気になる方はおかずさんの記事を御覧ください。

## データテーブルの内容に応じてアクターをセットアップする
上述のエディターユーティリティブループリントやエディターユーティリティウィジェットを使い、データテーブルの内容に応じてアクターをセットアップすることができるようになりました。
私の開発環境ではデータテーブルの編集をエクセルで行い、CSVをインポートすることで内容が反映されるようになっています。
変更が反映されたらエディタースクリプトを実行して、アクターなどのセットアップをするという流れです。
具体的には以下のような手順です。
![Change1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714557/4c9efca0-5458-7dc3-0a92-d658d1e00063.png)

この手順は面倒くさいというのもそうなのですが、エディタスクリプトを手動で実行しないとゲームに変更が反映されないということが一番の問題です。
この、**エディタスクリプトの実行を自動にできたらさらに便利になりそう**です。
今回はこのアセットがインポートされたときに任意のエディタースクリプトを実行する方法を紹介します。

## アセットインポート時に任意のエディタスクリプトを実行する大まかな流れ
大まかな流れとしては以下のようになります。
**①. エディタ起動時に指定のエディターユーティリティブループリントが起動するように登録する**
**②. エディターユーティリティブループリントとアセットインポート時のデリゲートをバインドする**
**③. インポートされたアセットに応じた処理を呼び出す**
以下にそれぞれの手順を説明します。
## ①エディタ起動時に指定のエディターユーティリティブループリントが起動するように登録する 

#### エディターユーティリティブループリントを作成する
今回のケースではエディターユーティリティブループリントを使用します。
エディターユーティリティウィジェットを使っている方が多いように思いますが、今回はエディターユーティリティブループリントの方が都合が良いです。
任意のフォルダーに作成してください。
#### DefaultEditorPerProjectUserSettings.iniの準備をする
> **Project/Config/DefaultEditorPerProjectUserSettings.ini**

上記のiniファイルにエディターユーティリティブループリントのパスを記載することになります。

:::note warn
このファイルが存在しない方もいると思いますが、その場合にはConfigフォルダ直下にDefaultEditorPerProjectUserSettings.iniというファイルを作成してください。このファイルの中身はとりあえず空でも大丈夫です。
:::

#### DefaultEditorPerProjectUserSettings.iniを編集する
DefaultEditorPerProjectUserSettings.iniに以下の2行を追加します。

> [/Script/Blutility.EditorUtilitySubsystem]
StartupObjects=/Game/Enclosure/Editor/ENC_Editor_ReimportProcess.ENC_Editor_ReimportProcess

1行目は誰でも同じ記載になりますが、2行目は起動したいエディターユーティリティブループリントのパスになります。
複数ある場合の記述など詳細は以下のリンクを参考にしてください。

https://docs.unrealengine.com/4.26/ja/ProductionPipelines/ScriptingAndAutomation/Blueprints/StartupObjects/

ここまでの手順でエディタを起動すると登録したエディターユーティリティブループリントが呼び出されるようになります。

## ② エディターユーティリティブループリントとアセットインポート時のデリゲートをバインドする
![Reference4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714557/a722d4c2-e8f9-3d81-38e7-814a4b1dd897.png)
①の手順で登録されたブループリントはエディタを起動すると上図のRunイベントが呼び出されます。
このタイミングで、アセットインポート時のデリゲートをバインドしてあげることになります。

そのためにInportSubsystemという機能を利用します。

https://kinnaji.com/2021/09/05/ue4importsubsystem/

上記の記事がとてもわかりやすいので参考にしていただければと思います。
基本的にInportSubsystemの概要と以下のデリゲートを利用できることを押さえていただければ十分です。
| デリゲートの種類 |概要|
|:-:|:-:|
|FOnAssetPreImport OnAssetPreImport|Import処理開始前のデリゲート|   |
|FOnAssetPostImport OnAssetPostImport|Import処理終了後のデリゲート|   |
|FOnAssetReimport OnAssetReimport|Reimport処理後のデリゲート|   |
|FOnAssetPostLODImport OnAssetPostLODImport|SK,SM等のアセットのLODImport処理終了後のデリゲート|   |

:::note warn
上述の記事はUE4時代のものなのでUE5だと利用できない機能が一部ありますが、今回利用する機能の部分については問題ありません。
:::

ImportSubsystemを利用してエディターユーティリティブループリントのRunイベントで以下のような処理を記述します。
![Change2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714557/23605f41-080e-0ee3-d58d-547f2039882a.png)
このようにすることで、アセットがインポートされるたびに指定したイベント（画像ではOnAssetPostImport_BP_Event）が呼び出されるようになります。
このイベントの先にインポート時に実行したい処理を書いていけば、アセットに応じた処理を実行することができるようになります。
## ③インポートされたアセットに応じた処理を呼び出す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714557/f500294b-29ee-a947-5316-e6dcdc037efe.png)
上図の通りインポートの度にイベントが呼び出されるので、処理を書いていきます。
特に上図の②の部分は強力で、InCreatedObjectとの比較で行いたい処理の場合分けが簡単にできます。
## こんな感じに利用しています
自分の環境では、アニメーションモンタージュを利用しています。
しかし、再生するときにモンタージュアセットを指定するのではなく、ラベルで呼び出せるようにしています。
モンタージュとラベルのヒモ付をエクセルで行いデータテーブルに登録しています。
![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714557/1d0108e8-5427-0bae-6573-3af697638cd3.gif)
ちょっと分かりづらいかなと思いますが、エクセルで登録したモンタージュアセットをデータテーブル更新時に、ブループリントのモンタージュ用の配列にセットしているところです。
## 注意事項
* エディタを起動後、登録したエディターユーティリティブループリントを編集するとImportSubsystemとのバインドが切れてしまいます。その場合、エディタを再起動するか、手動でRun関数を呼び出す必要があります。
* エディタスクリプトでクラスにコンポーネントを追加したりするとランタイムでセットアップするよりもディスクサイズが大きくなります。なのでなんでもかんでもオフラインで処理するのではなく、処理コストとディスクサイズを天秤にかけて、適度な利用を心がける必要はあるかと思います。

## 終わりに
アセットインポート時に任意の処理を呼び出す方法を紹介しました。
基本的にはエディターユーティリティがまじでイケているというところと、それを自動化に利用しましょうという感じです。