タイトル: プライマリーデータアセットを活用する方法
SEOタイトル: UE5 Primary Data Asset の使い方|AssetManager・PrimaryAssetId・非同期ロード
| この記事の要点 |
|
Primary Data Asset とは
Primary Data Asset (PDA) は UE5 の Asset Manager システムと連携する Data Asset の特殊な形態です。通常の UDataAsset を Blueprint や C++ から直接参照するとHard Reference となりメモリに常駐しますが、PDA は PrimaryAssetId という軽量な ID で参照し、必要時に明示的にロードします。
通常の Data Asset との違い
| 項目 | 通常の Data Asset | Primary Data Asset |
|---|---|---|
| 基底クラス | UDataAsset | UPrimaryDataAsset |
| 参照方法 | Hard Reference (TObjectPtr) / Soft Reference | PrimaryAssetId (FName + Type) |
| ロード | 参照されると自動ロード | 明示的に Load 呼び出し |
| Asset Manager 登録 | 不要 | 必要 |
| 用途 | 少数の固定設定 | 大量のアイテム / キャラ / モンスター定義 |
| メモリ | 参照元が読まれると常駐 | 必要なものだけロード |
C++ で Primary Data Asset を定義
// ItemDataAsset.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "ItemDataAsset.generated.h"
UCLASS(BlueprintType)
class MYGAME_API UItemDataAsset : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
FName ItemId;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
TSoftObjectPtr Icon;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
TSoftObjectPtr Mesh;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
int32 MaxStack = 99;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
float Weight = 1.0f;
// ★ Asset Manager 用 ID を返す
virtual FPrimaryAssetId GetPrimaryAssetId() const override
{
return FPrimaryAssetId(TEXT("Item"), GetFName());
}
};
Asset Manager にカテゴリを登録
Project Settings → Game → Asset Manager → Primary Asset Types to Scan:
+ Primary Asset Type: Item
Asset Base Class: UItemDataAsset
Has Blueprint Classes: false
Is Editor Only: false
Directories:
- /Game/Items
Specific Assets: (空)
Rules:
Chunk Id: -1
Cook Rule: Always Cook
Apply Recursively: true
これにより /Game/Items 配下の UItemDataAsset 派生アセットが全て自動スキャンされ、FPrimaryAssetId(TEXT("Item"), AssetName) でアクセス可能になります。
実行時に非同期ロード
#include "Engine/AssetManager.h"
void AMyGameMode::LoadItem(FName ItemName)
{
UAssetManager& AM = UAssetManager::Get();
FPrimaryAssetId AssetId(TEXT("Item"), ItemName);
// 非同期ロード開始
FStreamableDelegate Delegate = FStreamableDelegate::CreateLambda([this, AssetId]()
{
UAssetManager& AM = UAssetManager::Get();
UItemDataAsset* Item = Cast(AM.GetPrimaryAssetObject(AssetId));
if (Item)
{
UE_LOG(LogTemp, Log, TEXT("Loaded: %s"), *Item->DisplayName.ToString());
// 使用処理
}
});
TArray Bundles; // 必要なら "UI" などのバンドル名
AM.LoadPrimaryAsset(AssetId, Bundles, Delegate);
}
複数の Primary Asset を一括ロード
void AMyGameMode::PreloadAllWeapons()
{
UAssetManager& AM = UAssetManager::Get();
TArray AssetIds;
AM.GetPrimaryAssetIdList(TEXT("Item"), AssetIds);
FStreamableDelegate Delegate = FStreamableDelegate::CreateLambda([]()
{
UE_LOG(LogTemp, Log, TEXT("Bulk load complete"));
});
AM.LoadPrimaryAssets(AssetIds, TArray(), Delegate);
}
Blueprint からの利用
Blueprint からも Primary Data Asset は扱えます:
- Content Browser で右クリック → Miscellaneous → Data Asset
- 親クラスとして
ItemDataAssetを選択 - 個別のアイテム (Sword.uasset / Potion.uasset 等) を作成
- 各種パラメータを編集
Blueprint ノードで非同期ロード
Async Load Primary Asset (ノード)
Asset: Primary Asset Id (Item.Sword)
Bundles: (empty)
On Loaded → Cast to ItemDataAsset → 使用
サンプル: アイテム図鑑システム
// ItemDatabase.h
UCLASS()
class UItemDatabase : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void GetAllItems(TArray& OutIds)
{
UAssetManager::Get().GetPrimaryAssetIdList(TEXT("Item"), OutIds);
}
UFUNCTION(BlueprintCallable)
void LoadItemAsync(FPrimaryAssetId Id, const FOnItemLoaded& Callback)
{
FStreamableDelegate Delegate = FStreamableDelegate::CreateLambda([Id, Callback]()
{
UItemDataAsset* Asset = Cast(
UAssetManager::Get().GetPrimaryAssetObject(Id));
Callback.ExecuteIfBound(Asset);
});
UAssetManager::Get().LoadPrimaryAsset(Id, TArray(), Delegate);
}
};
Cook ルール
| Cook Rule | 動作 |
|---|---|
| Always Cook | 常にビルドに含める |
| Development Cook | 開発ビルドのみ |
| Never Cook | ビルドに含めない(デバッグ用) |
| Unknown | 他から参照された場合のみ |
Asset Bundle で部分ロード
UAssetBundleData でテクスチャだけ先読み、メッシュは後でロードのような段階的読み込みが可能:
// AssetBundles メタタグで分類
UPROPERTY(EditAnywhere, AssetBundles="UI")
TSoftObjectPtr Icon; // UI バンドル
UPROPERTY(EditAnywhere, AssetBundles="World")
TSoftObjectPtr Mesh; // World バンドル
// ロード時に「UI」バンドルのみ
TArray Bundles = { TEXT("UI") };
AM.LoadPrimaryAsset(AssetId, Bundles, Delegate);
FAQ
Q: なぜ通常の DataAsset ではなく Primary Data Asset を使う?
A: アイテム数百〜数千の RPG / カードゲームでは、全てを Hard Reference にするとメモリと起動時間が爆発します。PDA で必要なものだけロードしましょう。
Q: Asset Manager で見つからない
A: Project Settings の Asset Manager 設定で Directories が正しいか、Cook Rule が Never Cook になっていないか確認。UAssetManager::Get().ScanPathsSynchronous で手動スキャンも可能。
Q: GetPrimaryAssetId は省略できる?
A: Asset Manager の設定で Asset Base Class が一致すれば自動的に FPrimaryAssetId(ClassName, AssetName) が割り当てられます。明示的にオーバーライドした方が制御しやすい。