UE5 SubobjectDataSubsystem を使ってみる

# 概要
UnrealEngine5 の SubobjectDataSubsystem を使ってみたメモです。
BPアセットのプロパティなどの変更ができるようです。


## 更新履歴
| 日付 | 内容 |
|:-----|:----|
|2023/06/01| 初版 |

## 参考
以下の記事を参考にいたしました、ありがとうございます。
[UE公式：Subobject Data Subsystem](https://docs.unrealengine.com/5.1/en-US/BlueprintAPI/SubobjectDataSubsystem/)
[[UE5] Blueprint ・Componentが持つプロパティのデフォルト値をSubobjectDataSubsystemを使って確認・変更する方法について](https://qiita.com/EGJ-Kaz_Okada/items/ed47a81b0f4b5a9e0111)


## 環境
Windows10
Visual Studio 2022
UnrealEngine 5.1.1

## 関連ソース
"Engine\Source\Editor\SubobjectDataInterface\Public\SubobjectDataSubsystem.h"
"Engine\Source\Editor\SubobjectDataInterface\Private\SubobjectDataSubsystem.cpp"
"Engine\Source\Editor\BlueprintEditorLibrary\Public\BlueprintEditorLibrary.h"


# Blueprintアセットの変更
通常UEエディタで行うBPアセットのプロパティの変更ができるようです。

## アクターのBPアセットの変数を書き換える
`InObject`に指定のBPアセットを設定し、`Gather Subobject Data For Blueprint`でサブオブジェクトを取得、アクタークラスに対してTickInterval変数の変更をしています。

![example01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/6cdcaa87-fdae-4af4-a22b-d539da86dab4.png)


## アクターのBPアセットにコンポーネントを追加する
指定のBPアセットからルートコンポーネントを調べて`AddNewSubobjectParams`で追加するコンポーネントのパラメータを作成し、`Add New Subobject` でコンポーネントを追加して `Rename Subobject`でリネームしています。

![example02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/5ac0cb52-0f30-d5a6-2998-181dcf02e265.png)


## BlueprintアクターアセットのTick処理を切る
アクターのTickはゲーム中は `SetActorTickEnabled()`で切り替え可能ですが、Blueprintアセットではうまくいかない＆完全にTick処理を切るために `bStartWithTickEnabled` を `false`にしたいと思います。

<img width="280" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/2092c9d2-0bb0-4ddd-8252-2c0dea59eba9.png">

Tickフラグ切り替え用メソッドをC++で用意します。

```cpp:ActorのTickを切る処理
UFUNCTION(BlueprintCallable)
static bool SetTickDisable(AActor* _Actor) 
{
	if (_Actor->PrimaryActorTick.bStartWithTickEnabled) {
		_Actor->PrimaryActorTick.bCanEverTick = false;
		_Actor->PrimaryActorTick.bStartWithTickEnabled = false;

		return(true);
	}

	return(false);
}
```

これをつないで処理することでBlueprintアセット状態のアクターTick処理を切ることができます。
![example04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/0229cb91-64c4-46c3-69f8-c6d20adef382.png)

実用する場合はアセットレジストリを使って検索対象のリストを作成してアクターやコンポーネントに対して `StartWithTickEnable` を切ると良いかと思います。
![example03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/6a8f99ed-13be-2139-9a8c-cfe635b0aae7.png)

:::note info
`PrimaryActorTick.bCanEverTick` だけ `false` にすると継承したBlueprintでTickノードに処理をつなぐとTick処理がされるようです。完全にTick処理を行わないようにするには `PrimaryActorTick.bStartWithTickEnabled` も `false`にする必要があるようです。
:::


# Componentアセットの作成
通常UEエディタで行うコンポーネントアセットの新規作成を行うことができるようです。元になるコンポーネントクラスがBP版とC++版で別メソッドとして用意されています。

## CreateNewBPComponent
BPコンポーネントを新規作成します。
`ComponentClass`には基底となるBPコンポーネント、`New Class Path`は作成するアセットのパス、`New Class Name`は作成するアセット名を入力します。
![CreateBP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/6839f396-6624-9571-6391-b1ad5431eb84.png)
上記例だと [All] -> [コンテンツ] に `SkeletalMeshComponent`を継承した`SkeketalMeshComponent2` というアセットが新規作成されます。


## CreateNewCPPComponent
コンポーネントのC++コードを新規作成します。
`ComponentClass`には基底となるC++コンポーネント、`New Class Path`は作成するアセットのフルパス、`New Class Name`は作成するアセット名を入力します。
![CreateCPP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/5131f5a7-08b3-cdcf-3280-9cbb56da775d.png)
上記例だと [All] -> [C++クラス] -> [MyProject] に `MyActorComponent` というC++で作成したコンポーネントクラスを継承した `MyActorComponent2` というC++クラスアセットが作成され、コンパイルされます。


# まとめ
UEエディタで行っていた処理をBPで行えることが確認できました。コンポーネントの追加/削除などはあまり利用場面がないと思いますが、Blueprintアセットに対して処理を行えるのはプロパティの一括修正などで活用ができそうです。