运行时读取PAK文件
運行時讀取PAK文件
https://zhuanlan.zhihu.com/p/79209172
?
運行時讀取PAK文件
安寧
游戲/仿真開發,UE4用戶
運行時加載資產的問題
Unreal運行時加載資產有兩個問題:
第一,Unreal不會自動加載任何額外的pak文件。
第二,一旦加載了一個pak, 它不會將pak文件中的任何資產添加到內存中的AssetRegistry ..所以即使加載了pak,你也無法訪問它的內容
而這段代碼中的ScanForModPlugins()函數處理了這兩個問題:
https://github.com/smogworks/ModSkeleton/blob/master/Source/ModSkeleton/ModSkeletonRegistry.cpp?
github.com
?
開發和測試流程
兩個非常重要的限制:
在PIE模式中加載Pak文件時,只能加載未Cook的內容
在發布以后的程序中加載Pak文件時,只能加載已Cook的內容
因此需要設計一套流程,便于在發布以后的程序中測試,其中包含兩個步驟:
下面對每個過程進行闡述:
Cook 內容資源
打開內容所在的工程,打開Project Launcher,創建一個新的Profile,僅選擇Cook: By the book , 其余Build, Package, Archive, Deploy, Launch都不要。然后運行該Profile即可達到Cook的效果。
一個讓以后Cook更簡單的辦法是,在運行上述Profile以后,復制其命令內容:
粘貼到一個文本文件中,去掉BuildCookRun之前的內容,復制到剪貼板中;
然后搜索到RunUAT.bat文件,找到其路徑,cmd定位到該目錄下,然后輸入 RunUAT.bat 然后將剪貼板中的內容粘貼到該命令后面,即可直接Cook內容。
Cook以后的內容默認情況下位于
工程目錄/Saved/Cooked/<Platform Folder>/打包Pak
搜索UnrealPak.exe文件,CMD定位到該目錄下,輸入:
UnrealPak.exe Pak文件的完整路徑和名稱 -create=要打包的文件夾路徑注意-create=后面也可以跟一個文本文件,列出所有需要打包的具體uasset等文件的全名。
發布可執行程序
和Cook內容資源過程相似,區別在于這次需要勾選上Build和Package,并合適地設置。
掛載(Mount)Pak并異步加載內容
代碼:
.h:
//pak文件中的文件路徑列表TArray<FSoftObjectPath> ObjectPaths;TArray<TSoftObjectPtr<UObject>> ObjectPtrs;.cpp:
void APakMount::MountPak() {//第一步//FPlatformFileManager::Get()返回單例//GetPlatformFile()返回相應平臺的PlatformFile,即處理相應平臺文件讀寫的對象//因此在Windows平臺,這里返回的是FWindowsPlatformFile的實例IPlatformFile& InnerPlatform = FPlatformFileManager::Get().GetPlatformFile();//第二步//這里創建了一個FPakPlatformFile,但是未指定當前使用什么平臺去讀寫這個文件FPakPlatformFile* PakPlatformFile = new FPakPlatformFile();//第三步//使用相應平臺的PlatformFile去初始化PakPlatformFile//第二個參數是命令行參數,一般都為空PakPlatformFile->Initialize(&InnerPlatform, TEXT(""));//第四步//再將當前PlatformFile設置為"相應平臺下pak文件讀寫"的模式FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);const FString PakFileFullName = TEXT("D:\\ExamplePak.pak");//測試用MountPointFString MountPoint(FPaths::EngineContentDir());//創建FPakFile對象,同樣使用相應平臺的PlatformFile初始化//第二個參數是pak文件的完整路徑+名稱//第三個參數是是否有符號?FPakFile* Pak = new FPakFile(&InnerPlatform, *PakFileFullName, false);if (Pak->IsValid()){//具體Mount方法可以參考函數 FPakPlatformFile::Mount//但是其中有大量多余內容(例如版本編號處理)//Pak->SetMountPoint(*MountPoint);PakPlatformFile->Mount(*PakFileFullName,1000,*MountPoint);TArray<FString> Files;Pak->FindFilesAtPath(Files, *(Pak->GetMountPoint()), true, false, true);for(auto File : Files){FString Filename, FileExtn;int32 LastSlashIndex;File.FindLastChar(*TEXT("/"), LastSlashIndex);FString FileOnly = File.RightChop(LastSlashIndex + 1); FileOnly.Split(TEXT("."), &Filename, &FileExtn);if (FileExtn == TEXT("uasset")){File = FileOnly.Replace(TEXT("uasset"), *Filename);File = TEXT("/Engine/")+File;ObjectPaths.AddUnique(FSoftObjectPath(File));//將FSoftObjectPath直接轉換為TSoftObjectPtr<UObject>并儲存ObjectPtrs.AddUnique(TSoftObjectPtr<UObject>(ObjectPaths[ObjectPaths.Num()-1]));}}MyGI->GetStreamableManager().RequestAsyncLoad(ObjectPaths,FStreamableDelegate::CreateUObject(this,&APakMount::CreateAllChildren));}}掛載的核心方法是 PakPlatformFile->Mount.
掛載之后我們無法直接使用,還需要對其中的資源進行列舉,并轉換成可以直接加載的格式(包括去掉.uasset后綴名,以及前面加/Engine/)
然后將其存儲到FSoftObjectPath數組中,并順便轉換為TSoftObjectPtr并儲存到一個數組中,以便后期進行訪問。
最后使用StreamableManager進行異步加載。
存在的疑問:
使用動態加載的內容
在此例中已知pak中儲存的內容均為staticmesh,因此可以直接這樣處理,生成新的StaticMeshComponent組件。
存在的疑問:
如果不知道類型,如何判斷加載的資源類型?
void APakMount::CreateAllChildren() {UE_LOG(LogTemp,Log,TEXT("finished loading assets"));for (int32 i = 0; i < ObjectPtrs.Num(); ++i){UStaticMeshComponent* NewComp = NewObject<UStaticMeshComponent>(this);if (!NewComp){return;}UStaticMesh* staticMesh = Cast<UStaticMesh>(ObjectPtrs[i].Get());NewComp->SetStaticMesh(staticMesh);NewComp->AttachToComponent(GetRootComponent(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true));NewComp->SetRelativeLocation(FVector(0, (i + 1) * 100.0f, 0));NewComp->RegisterComponent();} }幾個相關概念/類
資產注冊表(Asset Registry)
是特定資產的信息存儲庫,是在保存package時提取的
AssetManager
是一個單例UObject,它提供在運行時掃描和加載主資源的操作。它旨在替換ObjectLibraries當前提供的功能,并包裝FStreamableManager以處理實際的異步加載。引擎資產管理器提供基本管理,但更復雜的事情(如緩存)可以由特定于游戲的子類實現。
主要資產(Primary Assets)
是可以根據游戲狀態的變化手動加載/卸載的資產。這包括地圖和游戲特定對象,例如庫存物品或角色類。
輔助資產(Secondary Assets)
是所有其他資產,例如紋理,聲音等。這些資產是根據主資產的使用自動加載的
?
總結
以上是生活随笔為你收集整理的运行时读取PAK文件的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 车身控制器BCM系统框图
- 下一篇: 虚幻引擎C++开发学习(三)
