我想这样做:创建并打包原创游戏。然后我想根据原始游戏中的蓝图创建带有新网格/声音/动画和蓝图的附加 PAK 文件。原始游戏不应该知道任何关于附加网格/动画/等的信息。因此,我需要在原始游戏中使用 AssetRegistry 创建一个智能系统,扫描所有 PAK 文件,加载/挂载它们,并使用 AssetRegistry 扫描这些 PAK 文件中的所有资产。
我为实现目标所做的事情:我为目标平台(Windows 独立版)成功创建并打包了原始游戏。然后在项目中,我创建附加内容并为目标平台烘焙它们。我使用 UnrealPak.exe 为附加内容创建 PAK 文件。我可以通过将 PAK 文件放在 Paks 文件夹中来加载/挂载原始游戏中的 PAK 文件,并且它们在游戏启动时加载/挂载(这句话是基于原始游戏中的 LOG 文件,我不知道如何来检查它是否真实)。我什至可以使用 FCoreDelegates::OnMountPak.Execute 来加载/挂载 PAK 文件(这句话也是基于原始游戏的 LOG 文件)。因此加载/挂载 PAK 文件应该可以正常工作。但现在最大的问题在哪里。我想使用 AssetRegistry 扫描所有 PAK 文件中的所有资产。我尝试了我想出的一切。我尝试了 ScanPathsSynchronous 方法、GetAllAssets 方法。唯一发生的事情是它从原始游戏 PAK 文件加载资产。看来 AssetRegistry 对其他 PAK 文件一无所知。我试图用 AddPath 方法告诉 AssetRegistry 这些文件在哪里,但仍然不起作用。
所以我尝试过的示例代码在这里:
FString path1 = FPaths::ConvertRelativePathToFull(FString("../../../TestPaks/Content/Paks/test.pak"));
FString path2 = FPaths::ConvertRelativePathToFull(FString("../../../TestPaks/Content/Paks/testmaterial.pak"));
bool check1 = false;
bool check2 = false;
if (FCoreDelegates::OnMountPak.IsBound())
{
check1 = FCoreDelegates::OnMountPak.Execute(path1, 0, nullptr); //Number should be 0-4; specifies search order
check2 = FCoreDelegates::OnMountPak.Execute(path2, 0, nullptr); //Number should be 0-4; specifies search order
}
UE_LOG(LogTemp, Warning, TEXT("%s"), *path1);
UE_LOG(LogTemp, Warning, TEXT("%s"), *path2);
FString NewString1 = check1 ? "true" : "false";
FString NewString2 = check2 ? "true" : "false";
UE_LOG(LogTemp, Warning, TEXT("check 1 = %s"), *NewString1);
UE_LOG(LogTemp, Warning, TEXT("check 2 = %s"), *NewString2);
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
IAssetRegistry& assetRegistry = AssetRegistryModule.Get();
TArray<FString> ContentPaths;
TArray<FAssetData> data;
//assetRegistry.AddPath(path1);
FString contentRelativeDir = TEXT("/Game/Paks");
assetRegistry.AddPath(contentRelativeDir);
assetRegistry.ScanPathsSynchronous({ contentRelativeDir });
//assetRegistry.SearchAllAssets(true);
assetRegistry.GetAllAssets(data, false);
assetRegistry.GetAllCachedPaths(ContentPaths);
for (FString& data : ContentPaths)
{
UE_LOG(LogTemp, Warning, TEXT("GetAllCachedPaths: %s"), *data);
}
FString NewString = FString::FromInt(data.Num());
UE_LOG(LogTemp, Warning, TEXT("%s"), *NewString);
for (int32 i = 0; i < data.Num(); i++)
{
FString s = data[i].AssetName.ToString();
FString ss = data[i].AssetClass.ToString();
UE_LOG(LogTemp, Warning, TEXT("%s | %s"), *s, *ss);
}
Run Code Online (Sandbox Code Playgroud)
我尝试了很多版本的路径,但没有任何效果。我陷入这种混乱状态大约两周了,对于该做什么以及什么会起作用,我没有更多的建议。那么这应该如何正常工作???我查看了这里的论坛和 StackOverflow,有一些解决方案,但它们不再起作用了。
小智 7
我已从 .pak 文件加载资源,但我使用 FStreamableManager 而不是 AssetRegistry。我将描述我所做的事情......
1)挂载.pak文件:我只需要将额外的.pak文件放入WindowNoEditor / [Project_Name] / Content / Paks /文件夹(假设您打包为window),游戏引擎将自动挂载该.pak文件。
2) 从该 .pak 文件加载/获取资源:
FPakPlatformFile *PakPlatformFile;
FString PlatformFileName = FPlatformFileManager::Get().GetPlatformFile().GetName();
if (PlatformFileName.Equals(FString(TEXT("PakFile"))))
{
PakPlatformFile = static_cast<FPakPlatformFile*>(&FPlatformFileManager::Get().GetPlatformFile());
}
else
{
PakPlatformFile = new FPakPlatformFile;
if (!PakPlatformFile->Initialize(&FPlatformFileManager::Get().GetPlatformFile(), TEXT("")))
{
UE_LOG(LogTemp, Error, TEXT("FPakPlatformFile failed to initialize"));
return;
}
FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);
}
TArray<FString> ArrAllMountedPakFile;
PakPlatformFile->GetMountedPakFilenames(ArrAllMountedPakFile);
for (int32 i = 0; i < ArrAllMountedPakFile.Num(); i++)
{
FString PakFileName = ArrAllMountedPakFile[i];
FString PakFilePathFull = FPaths::ConvertRelativePathToFull(PakFileName);
FPakFile PakFile(PakPlatformFile, *PakFilePathFull, false);
TArray<FString> FileList;
FString MountPoint = PakFile.GetMountPoint();
PakFile.FindFilesAtPath(FileList, *MountPoint, true, false, true);
for (int32 i = 0; i < FileList.Num(); i++)
{
FString AssetName = FileList[i];
FString AssetShortName = FPackageName::GetShortName(AssetName);
FString FileName, FileExt;
AssetShortName.Split(TEXT("."), &FileName, &FileExt);
FString NewAssetName = TEXT("/Game/<path_to_asset>/") + FileName + TEXT(".") + FileName;
FSoftObjectPath StrNewAssetRef = NewAssetName;
FStreamableManager AssetLoader;
UObject* NewLoadedObject = AssetLoader.LoadSynchronous(StrNewAssetRef);
if (NewLoadedObject)
{
// do something, cast to compatible type.
}
}
}
Run Code Online (Sandbox Code Playgroud)
希望对您有所帮助。欢呼!
| 归档时间: |
|
| 查看次数: |
13236 次 |
| 最近记录: |