虚幻引擎4:打包游戏中用于使用PAK文件,加载/加载文件以及使用AssetRegistry加载资产的正确方法是什么?

时间:2019-01-21 12:57:50

标签: unreal-engine4

我想这样做: 创建并打包原始游戏。然后,我想基于原始游戏中的蓝图,使用新的网格/声音/动画和蓝图创建其他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文件一无所知。我试图告诉AssetRegistry这些带有AddPath方法的文件在哪里,但仍然无法正常工作。

所以我尝试的示例代码在这里:

         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);
     }

我尝试了很多版本的路径,但没有任何效果。我在大约两周的时间里陷入了混乱,对于如何做以及将如何工作,我没有更多的提示。那么这应该如何正常工作呢???我在这里的论坛和StackOverflow上找到了一些解决方案,但是它们不再起作用了。

1 个答案:

答案 0 :(得分:0)

我已经从.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.
       }
   }
}

希望能对您有所帮助。加油!