UE4 Pak加载

Overview:

   本篇主要说明两点内容:一,Pak正确加载的源码内容及遇到的bug所在;二,Pak的生成问题。如果你看到此篇,说明你有可能需要这些文档:

风蚀之月的UnrealPak使用笔记:http://blog.ch-wind.com/unrealpak-note/

UE4 PAK加载资源:http://blog.csdn.net/u014532636/article/details/72844367

https://answers.unrealengine.com/questions/389842/loadpackageasync-always-fails-if-file-string-not-c.html/该篇主要使用了后两篇的内容,第一篇有关于UnrealPak的内容,这个暂时还没有去实践,只是觉得不错就贴出来了。

补充说明:本篇文档使用的当前引擎为:Unreal 4.17.2(有可能由于版本的变更,导致一些API,方法的不适用)。

Required Knowledge:

   之前,你需要知道怎么得到Pak,以及它的基本使用方法,最基本的要求是你要知道它是什么。你需要知道加载Pak文件的核心API,头文件,组件内容,这些可以在引擎的文档里查到。

Example Code and Knowledge:

     FString SaveContentDir =GetGameContentPakDir() + TEXT("hotupdate.pak");

IPlatformFile&PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

FPakPlatformFile*PakPlatformFile = new FPakPlatformFile();

PakPlatformFile->Initialize(&PlatformFile,TEXT(""));

FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);

FPakFilePakFile(&PlatformFile,*SaveContentDir, false);

FStringMountPoint(FPaths::GameContentDir());

PakFile.SetMountPoint(*MountPoint);

if(PakPlatformFile->Mount(*SaveContentDir, 0, *MountPoint))

{

TArray<FString> FileList;

PakFile.FindFilesAtPath(FileList, *PakFile.GetMountPoint(), true,false, true);

FStreamableManager StreamableManager;

AssetName = "/Game/Paks/MeshCar.MeshCar";

FStringAssetReference reference = AssetName;

UObject* LoadObject = StreamableManager.SynchronousLoad(reference);

If(LoadObject!=nullptr)

{

UStaticMesh* Obj = Cast<UStaticMesh>(LoadObject);

If(Obj!=nullptr)

{

   AStaticMeshActor*actor=GetWorld()->SpawnActor<AStaticMeshActor>

(FVector::ZeroVector, FRotator::ZeroRotator);

  actor->GetStaticMeshComponent()->Mobility= EComponentMobility::Movable;

  actor->GetStaticMeshComponent()->SetStaticMesh(Obj);

}

else

{

….

}

}

}

这些代码是从Overview提及的第二篇链接文章改编而来的,可能是由于版本的原因,该博主的文章,并没有正常发挥作用,把资源加载出来。于是中间经历了大量的尝试,其中值得一提的是用到了下面的代码,不过没来的及试,如果可以的话,你可以代为尝试:

if (FCoreDelegates::OnMountPak.IsBound())

         {

     //4.17版本下Execute(FilePath,4),并不能使用,新的的API多出了一个参数,我就随意添加了一个nullptr,如果你有时间可以细看一下

                   FCoreDelegates::OnMountPak.Execute(FilePath,4,nullptr);

                   GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Cyan, FilePath);

         }

 转到正题,关于修改的内容:

 SaveContentDir路径内容,我是使用了自己存放Pak的文件夹也就是../../../[Project_Name]/

Content/Paks/, GetGameContentPakDir(),下封装了UE4的获取游戏内容的路径,以进行支持IOS的路径安排,事实上,没有进行路径转换,Pak在IOS上也能正确的读取,一种猜测是和UE4自己的封装有关。

FString GetGameContentPakDir()

{

  returnFPaths::GameContentDir()+”Paks/”;

}

当然,你也可把自己的Pak的文件名,作为参数的方式传入

Mount的路径也换成了FPaths::GameContentDir();

关于资源的异步加载:

AssetName = "/Game/Paks/MeshCar";

FStringAssetReference reference = AssetName;

UObject* LoadObject = StreamableManager.SynchronousLoad(reference);

这个和博主的做法类似,但使用博主的路径方式,并不能正确加载出内容,于是有了第三篇unreal answer的sonical1978一句话,是一个亮点:” 通常pak是很容易加载成功的,而异步读取资源是否成功取决于你读取的路径是否正确。把那些.../../../..全部删掉,之后就可以在资源注册表通过各种方法使用这些资源了”,事实上亦是如此,路径问题始终是困扰本人的问题所在,于是,在这个地方,对这个原博主的代码内容,进行更改,直接对使用的资源进行加载即“/Game/Paks/MeshCar”这是个UStaticMesh,所以为了验证是否加载成功,把它加载到了世界场景中:

UStaticMesh* Obj = Cast<UStaticMesh>(LoadObject);

If(Obj!=nullptr)

{

   AStaticMeshActor*actor=GetWorld()->SpawnActor<AStaticMeshActor>

(FVector::ZeroVector, FRotator::ZeroRotator);

  actor->GetStaticMeshComponent()->Mobility= EComponentMobility::Movable;

  actor->GetStaticMeshComponent()->SetStaticMesh(Obj);

}

最终,你会看到指定的模型被加载进场景中。

PS:刚接触的时候,对Pak有一个误解,在之前的测试中,一个朋友提供的文档中,关于Patch的内容误导了一下,到后来才知道,怎样获取正确的更新,Pak需要指定cook内容才能得到合理的利用,通过项目打包指定的map,只有在map中放置的资源才能被加载,而那些资源之外的内容,很有可能在资源注册列表中找不到。

猜你喜欢

转载自blog.csdn.net/u011047958/article/details/78539991