UE内で管理されているアセットへのC++を使ったアクセス
UE内で管理されているアセットへの基本的なアクセスにはIAssetRegistryクラスを使用するのがとても簡単
UEditorAssetLibraryクラスやUEditorLoadingAndSavingUtilsクラスを併用する事でほぼすべての操作がC++上から実行できる。
ただし、これらの機能はエディタ有効時(#if WITH_EDITOR ~ #endifブロック内)にしか使用することはできない。
依存モジュールの追加
UEditorAssetLibraryクラスやUEditorLoadingAndSavingUtilsクラスを使用する場合、EditorScriptingUtilitiesやUnrealEdといった依存モジュールをプロジェクトに追加する必要がある。
プロジェクトのビルド設定スクリプト(???.Build.cs)に以下のようにして依存モジュールを追加する
using UnrealBuildTool; using UnrealBuildTool.Rules; public class UEAssetUtility : ModuleRules { public UEAssetUtility(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); PrivateDependencyModuleNames.AddRange(new string[] { "EditorScriptingUtilities", // 追加 "UnrealEd" // 追加 }); } }
アセットの検索
AFRFilterを使って、
- 検索するパス
- 検索するクラス型
- 再帰的に検索するのか?
などの条件を細かく指定する事が可能。
GetAssets関数は検索条件に引っかかったアセットをTArrayコンテナで一挙に受け取ることができる。
FARFilter Filter; // 指定したパス以下のアセットを取得 Filter.PackagePaths.Add(FName(TEXT("/Game/Common"))); Filter.PackagePaths.Add(FName(TEXT("/Game/Levels"))); // 指定したクラス型名のアセットを取得 Filter.ClassPaths.Add(USkeletalMesh::StaticClass()->GetClassPathName()); Filter.ClassPaths.Add(UStaticMesh::StaticClass()->GetClassPathName()); Filter.bRecursivePaths = true; // Trueなら、PackagePathsで指定したパス以下を再帰的に検索する Filter.bRecursiveClasses = true; // Trueなら、ClassPathsで指定したクラスの派生クラスも検索する TArray<FAssetData> OutAssetData; if (IAssetRegistry::Get()->GetAssets(Filter, OutAssetData)) { int32 Index = 0; for (auto& AssetData : OutAssetData) { const FString AssetName = AssetData.AssetClassPath.GetAssetName().ToString(); const FString PackageName = AssetData.PackageName.ToString(); UE_LOG(LogTemp, Log, TEXT("Found asset[%d]: '%s' %s"), Index++, *AssetName, *PackageName); } }
アセットを一挙に受け取るのではなく、見つかったアセットを個別評価するEnemerateAssets関数も存在する
FARFilter Filter; // 指定したパス以下のアセットを取得 Filter.PackagePaths.Add(FName(TEXT("/Game/Common"))); Filter.PackagePaths.Add(FName(TEXT("/Game/Levels"))); // 指定したクラス型名のアセットを取得 Filter.ClassPaths.Add(USkeletalMesh::StaticClass()->GetClassPathName()); Filter.ClassPaths.Add(UStaticMesh::StaticClass()->GetClassPathName()); Filter.bRecursivePaths = true; // Trueなら、PackagePathsで指定したパス以下を再帰的に検索する Filter.bRecursiveClasses = true; // Trueなら、ClassPathsで指定したクラスの派生クラスも検索する int32 Index = 0; IAssetRegistry::Get()->EnumerateAssets(Filter, [&Index](const FAssetData& AssetData) { const FString AssetName = AssetData.AssetClassPath.GetAssetName().ToString(); const FString PackageName = AssetData.PackageName.ToString(); UE_LOG(LogTemp, Log, TEXT("Found asset[%d]: '%s' %s"), Index++, *AssetName, *PackageName); });
パッケージが存在しているか調べる
指定したパッケージが、UE管理内アセット中に存在するかを判定する。
FPackageName::DoesPackageExist関数では、未だディスクに保存されていないOnMemoryなパッケージは判定されないようなので、その際はIAssetRegistry::TryGetAssetByObjectPathなどと使い分けるとよい
const FString PackageName(TEXT("/Game/Common/Materials/MI_BaseColorAndNormal")); if (FPackageName::DoesPackageExist(PackageName)) { // PackageNameで指定されたパッケージが見つかった UE_LOG(LogTemp, Log, TEXT("Package %s already exists"), *PackageName); } else { // PackageNameで指定されたパッケージが見つからなかなった UE_LOG(LogTemp, Log, TEXT("Package %s was not found"), *PackageName); }
パッケージが依存しているアセットを全て取得
指定したパッケージが依存しているアセット(例えばマテリアルインスタンスアセットならば親マテリアルアセットなど)を全て取得する。
IAssetRegistry::GetDependenciesで取得できるのは依存先アセットのパッケージ名なので、FAssetDataが必要ならばパッケージ名を使ってIAssetRegistry::GetAssetsなどで取得する。
const FName PackageName(TEXT("/Game/Common/Materials/MI_BaseColorAndNormal")); TArray<FAssetIdentifier> OutDependencies; if (IAssetRegistry::Get()->GetDependencies(FAssetIdentifier(PackageName), OutDependencies)) { int32 Index = 0; // 見つかった依存先アセットを全て列挙 for (const auto& DependencyAsset : OutDependencies) { if (DependencyAsset.PackageName != NAME_None) { UE_LOG(LogTemp, Log, TEXT("Found dependency asset[%d]: %s"), Index++, *(DependencyAsset.PackageName)); } } }
パッケージが参照しているアセットを全て取得
指定したパッケージが参照しているアセット(例えばマテリアルアセットならば子マテリアルインスタンスアセットやテクスチャアセットなど)を全て取得する。
const FName PackageName(TEXT("/Game/Common/Materials/MI_BaseColorAndNormal")); TArray<FAssetIdentifier> OutReferencers; if (IAssetRegistry::Get()->GetReferencers(FAssetIdentifier(PackageName), OutReferencers)) { int32 Index = 0; // 見つかった参照先アセットを全て列挙 for (const auto& ReferenceAsset : OutReferencers) { if (ReferenceAsset.PackageName != NAME_None) { UE_LOG(LogTemp, Log, TEXT("Found reference asset[%d]: %s"), Index++, *(ReferenceAsset.PackageName)); } } }
アセットの複製
指定したアセットを複製する。 参照しているアセットなどは複製元と同じものとなるため、参照アセットごと複製する場合には全ての参照アセットに対して、
- 参照アセットの複製
- 複製した参照アセットへの差し替え
を行っていく必要がある。
const FString SrcPackageName(TEXT("/Game/Common/Materials/MI_BaseColorAndNormal")); const FString DstPackageName(TEXT("/Game/Level/Materials/MI_BaseColorAndNormal")); // SrcPackageNameで指定されたパッケージを、DstPackageNameで指定された場所へ複製する UObject* DstObject = UEditorAssetLibrary::DuplicateAsset(SrcPackageName, DstPackageName); if (IsValid(DstObject)) { UE_LOG(LogTemp, Log, TEXT("Duplicate asset: %s -> %s"), *SrcPackageName, *DstPackageName); } else { UE_LOG(LogTemp, Warning, TEXT("Failed to duplicate asset: %s -> %s"), *SrcPackageName, *DstPackageName); }













