はじめに
この記事では簡単な DataAsset を作成し、そのデータアセットに登録したアセットを非同期ロードをして利用する実装について解説します。
C++ を含む内容ですが難易度は低めです。

以下の環境で執筆されています。
- UE5.3.1
- Blink Template
- Rider 2023.3.1
解説
① PrimaryDataAssetの作成
まず、UPrimaryDataAsset を継承したクラスを C++ で作成します。
CustomData というフォルダに MagicDataAsset という名前で作成しました。

UPROPERTY で使用したいアセットをソフト参照で定義していきます。
▼ MagicDataAsset.h
#pragma once
#include "CoreMinimal.h"
#include "NiagaraSystem.h"
#include "PaperSprite.h"
#include "Engine/DataAsset.h"
#include "MagicDataAsset.generated.h"
UCLASS(BlueprintType)
class BLOGC_API UMagicDataAsset : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
/* 名前 */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "MagicSettings")
FText Name;
// 以下ソフト参照(TSoftObjectPtr)のアセット群
// ロード時に選択できるようにAssetBundlesを指定しておく
/* サムネイル */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MagicSettings|UI", meta = (AssetBundles = "UI"))
TSoftObjectPtr<UPaperSprite> Thumbnail;
/* Niagaraエフェクト */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MagicSettings|Action", meta = (AssetBundles = "Action"))
TSoftObjectPtr<UNiagaraSystem> Effect;
// AssetBundlesは複数指定も可
/* サウンド */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MagicSettings|Action/UI", meta = (AssetBundles = "Action, UI"))
TSoftObjectPtr<USoundWave> Sound;
};
Paper2D やNiagara のモジュールを追加します。
▼ プロジェクト名.Build.cs
using UnrealBuildTool;
public class BlogC : ModuleRules
{
public BlogC(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { "Paper2D", "Niagara" });
}
}
これで C++ での実装は終わりです。
ビルドしてみましょう。 ビルドが失敗する場合はほかに UnrealEngine 関連のプロセスが動いていないことや、.sln の再生成。Intermediate や Saved を消して再度実行してみましょう。
プロジェクトが起動したら、その他->データアセットを選択して C++ で作成したデータアセットを指定します。


② 作成したデータアセットへの登録
作成したデータアセットを開き、このデータが呼ばれたときに利用したいアセットを登録していきます。

ソフト参照で定義した変数なので参照ビューアを見ると設定したアセットがソフト参照で接続されていることなのが分かります。 これにより、DA_Magicをロードしたとき芋づる式にアセットがロードされないため、ロード時間が集中してヒッチが発生したりするのを防ぐことができます。
ただし、ロードが行われていないアセットを利用することはできないので、次の章からロードして利用する方法を解説します。

③ アセットマネージャーの設定
アセットのロード周りの仕組みをより便利に使うための機能。アセットマネージャーが独自に作成した MagicDataAsset を認識できるように設定を行います。
プロジェクト設定からアセットマネージャーを開きます。

スキャンするプライマリアセットタイプからインデックスを追加し、PrimaryAssetType, AssetBaseClass, Directoriesを指定します。

新たに PrimaryDataAsset を追加した場合は忘れずに登録しましょう。
④ 非同期ロードの実装
準備したアセットを利用して非同期ロードを行いアセットを利用するサンプルを実装してみましょう。
※今回は Actor で実装しますが場所はどこでも大丈夫です。
変数 MagicData を作成し、作成したデータアセットを登録します。

以下の内容を記述します。
1秒後にデータアセット内の任意のデータを非同期ロードして利用するというものです。
ロードが完了したとき Object として返されるので、MagicDataAsset で Cast して内部の変数にアクセスできるようにします。
これらの変数はソフト参照なので利用するノードに指定できませんが、この時点ではロード済みのアセットは参照を解決して利用できます。ここでは省いていますが、ロードに失敗したアセットは参照の解決で null を返すので、必要に応じてチェックすることをおすすめします。
このBPをレベルに配置してスタンドアローンで実行すると
アセットが非同期ロードで読み込まれ利用できました。

ポイントしてはAssetBundlesにActionが割り振られているアセットのみ非同期ロードしていることです。
meta = (AssetBundles ="バンドル名") を指定することで、大量のアセットが登録されているデータアセットでも必要最低限のデータのみをロードすることができます。
/* サムネイル */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MagicSettings|UI", meta = (AssetBundles = "UI"))
TSoftObjectPtr<UPaperSprite> Thumbnail;
/* サウンド */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MagicSettings|Action/UI", meta = (AssetBundles = "Action, UI"))
TSoftObjectPtr<USoundWave> Sound;
例えば Load Bundles に UI を指定した場合は、Thumbnail と Sound のみが読み込まれ UI が指定されていない Effect の読み込みを阻止することができます。

これらの機能をうまく活用してユーザーにストレスフリーな作品を作ってみてはいかがでしょうか。
最後までお読みいただきありがとうございました。