【UE5】AssetDataからアセットを探す

UE5をさわっている際に、コンテンツブラウザのアセットへのアクセスではまったので、メモも兼ねて記事にします。
過去に投稿した記事[『FStringからブループリントをSpawnする』](https://qiita.com/_akoto_/items/1392f3cec02ec026ee73)の内容が、UE5だとアクセスの仕方が変わっていた箇所もあり、補足の記事となります。

# 調査環境
**UnrealEngine 5.1.1**

# AssetDataとは
コンテンツブラウザのアセットへのアクセスするには、目的のアセットのAssetDataを見つける必要があります。
AssetDataの説明については、以前書いた記事の[『AssetData構造体とは』](https://qiita.com/_akoto_/items/a5a28cb52f7d342b7a16#assetdata%E6%A7%8B%E9%80%A0%E4%BD%93%E3%81%A8%E3%81%AF)または、[『AssetData構造体を取得する為のノード』](https://qiita.com/_akoto_/items/a5a28cb52f7d342b7a16#assetdata%E6%A7%8B%E9%80%A0%E4%BD%93%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E7%82%BA%E3%81%AE%E3%83%8E%E3%83%BC%E3%83%89)をご参照ください。

**AssetDataについては、二つ注意点があります**。

一つ目の注意点は、UE5では、**AssetData構造体の定義が変わっている**点です。
以下の画像のように『<font color="red">**AssetClassPath**</font>』というパラメータが増えています。
![スクリーンショット 2023-04-06 180957.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/18bc77a3-e689-5f4c-cf5a-02a12bb5efd2.png)


二つ目の注意点が、**AssetClassを使わない**という点です。
これは、<font color="red">**5.1のバージョンから、AssetClassが正しい情報を返さなくなっている**</font>為です。
詳細は、おかずさんがTwitterで説明されている為、[おかずさんのツイート](https://twitter.com/pafuhana1213/status/1620307267785744384)をご参照ください。


# AssetDataを取得する方法
今回補足したかった点です。
基本的には、[以前書いた記事](https://qiita.com/_akoto_/items/a5a28cb52f7d342b7a16#assetdata%E6%A7%8B%E9%80%A0%E4%BD%93%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E7%82%BA%E3%81%AE%E3%83%8E%E3%83%BC%E3%83%89)での紹介しているように、GetAssetsRegistryを使って、GetAssetByPathやGetAssetsbyClass等のノードを使用する事で変わりません。
UE5から、『ContentBrowserDataSubsystem』や『SubobjectDataSubsystem』というサブシステムが追加されており、**GetAssetByPathやGetAssetsbyClassなどのノードが実装**されています。
その為、当初はこちらに移行するのかなっと考えていましたが、GetAssetsRegistryと同様の使い方をしても、目的の動作はしませんでした。
今後、バージョンアップされた際に、Subsystemを使う必要があるかも知れません。

:::note warn
GetAssetsbyClassでの、引数のClassNameがName型ではなく、<font color="red">**TopLevelAssetPath型**</font>になっている為、注意してください。
プロジェクトの内のアセットを探すのが目的なら、**TopLevelAssetPathのPackageNameは、『/Script/Engine』** を入れておけば大丈夫です。
:::

![スクリーンショット 2023-04-05 175145.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/7f40b2cd-9754-69b2-68ae-9f252bea9f42.png)


# ブループリントのクラスを取得する

今回補足したかったもう一つの点です。
過去に投稿した記事『[FStringからブループリントをSpawnする](https://qiita.com/_akoto_/items/1392f3cec02ec026ee73#assetdata%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E3%82%8B)』だと、AssetDataからのAsset化は、『**AssetRegistryのGetAssetsから、名前一致でAssetDataを見つけるという方法**』を取っていたのですが、この方法だと、AssetDataを見つける事は出来ますが、<font color="red">**Castが失敗**</font>してしまう為、Asset化が出来ない事が分かりました。

対応方法としては、こちらもおかずさんが[Qita記事](https://qiita.com/EGJ-Kaz_Okada/items/ed47a81b0f4b5a9e0111#subobjectdatasubsystem-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6bp%E3%81%8C%E6%8C%81%E3%81%A4%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E5%88%9D%E6%9C%9F%E5%80%A4%E3%82%92%E5%8F%96%E5%BE%97%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)を上げているので、一度参照ください。

具体的には、以下のようなブループリントのように、『GetBlueprintAsset』から目的のブループリントを引数に渡して、GetObjectまで変換してキャストを行います。

![スクリーンショット 2023-04-05 182328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/770725c6-d8f8-0723-04c9-af65431af1f8.png)

:::note alert
GetAssetsRegistryから探した、AssetDataからのAsset化は、**キャストに失敗**してしまいます。
:::

# 最後に
最後に、GetDataで取得できるSubjectData構造体で実装されているチェックノードを紹介して記事を締めます。

**IsValid**
![IsValid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/8953bb57-98e8-f2ea-5053-c661650c3359.png)
オブジェクトの存在をチェックする。


**IsComponent**
![IsComponent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/fdd3f55f-bd80-693a-5b07-170abc889c72.png)
コンポーネントかをチェックする。

**IsActor**
![IsActor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/d8cfdd23-e185-3fea-dea0-8483b03eae6e.png)
アクターかをチェックする。

**IsRootComponent**
![IsRootComponent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/509a4f68-0703-92fa-1726-64b0f5d9ba51.png)
ルートコンポーネント(ブループリントの直下のコンポーネント)であるかをチェックする。

**IsDefaultSceneRoot**
![IsDefaultSceneRoot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/d54f94ed-d4d0-7308-4bb4-e49da4a54115.png)
DefaultSceneRootであるかをチェックする。

**IsSceneComponent**
![IsSceneComponent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/3ca29ff4-5c68-3e74-9069-d3f231c5bf55.png)
SceneComponentであるかをチェックする。

**IsRootActor**
![IsRootActor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/3f1bedd2-e301-ad04-3a64-31b664b1a3b0.png)
結果がtrueで返さってきます。
IsRootActorの挙動はちょっと不明です。『This is the root actor if it points to an AActor and has no parent』っという説明されていた為、Actorを親クラスにしたブループリントのサブクラスであるかの判定を行っているのかと思いましたが、そういう訳でもなさそうでした...。

**IsNativeComponent**
![IsNativeComponent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/9b63af93-eda0-1163-d63c-73a17a2de107.png)
こちらは、EComponentCreationMethod::Nativeでないかのチェックを行っています。EComponentCreationMethod::Nativeは、クラス宣言時にデフォルトとしてセットされている為、
EComponentCreationMethod::Nativeでないかのチェックがどういう時に、役に立つのか調べきれませんでした。
列挙型のEComponentCreationMethodは、以下の定義がされています。

```c++
UENUM()
enum class EComponentCreationMethod : uint8
{
	/** A component that is part of a native class. */
	Native,
	/** A component that is created from a template defined in the Components section of the Blueprint. */
	SimpleConstructionScript,
	/**A dynamically created component, either from the UserConstructionScript or from a Add Component node in a Blueprint event graph. */
	UserConstructionScript,
	/** A component added to a single Actor instance via the Component section of the Actor's details panel. */
	Instance,
};
```

:::note info
事前にチェックを行い、Castノードに余計なアセットが辿り着かないようにチェックを行いましょう。
:::