本文链接 https://blog.csdn.net/BDalasja/article/details/95618330
最近项目转战UE4了,需要研究UE4的热更,就此研究了一下PAK文件的相关内容。
pak文件是UE打包后的一种文件格式,所有的资源文件都是存储在这个文件中。我们在打包后的项目下,可以发现 content目录下有一个Paks目录,目录中一般会有一个pak文件和一个sig文件。既然叫Paks,说明肯定会有多个pak文件。以堡垒之夜为例,可以看到Paks目录下有40+的pak文件。那么这些pak文件是怎么组织的?引擎是怎么知道哪个文件在哪个pak文件中的?多个pak文件中如果同时有某个资源(热更的情况),又是如何处理覆盖关系?
1. Paks中的pak文件在游戏启动的时候,会全部自动"挂载"
什么叫挂载?
代码里面叫做Mount
。Mount
是一个有别与Load
的概念,Mount是读取pak文件中的文件信息,就是获取pak文件中有哪些文件,以便后续查找文件的时候,确定pak中是否有指定的文件。
什么时候挂载?
app启动的时候,在LaunchEngineLoop中的PreInit函数中,会调用FPakPlatformFile::MountAllPakFiles("Game/Content/Paks/")
。这个函数就是Paks下面所有的pak文件并遍历挂载。
2. 多个Pak如何决定加载及搜索顺序?
引擎内部维护一个已经挂载的pak文件列表,当需要打开其中的文件的时候,会遍历这些pak中的文件列表,查看该pak是否包含该文件,如果包含,则认为该文件包含在改pak中。
这个文件搜索方法表面:
- apk文件列表决定了查找顺序。
- 如果多个pak都包含某个文件,则肯定使用顺序在前的pak
3. pak文件名可以控制读取顺序
那么这个pak文件列表中的顺序是如何来决定的呢?阅读代码我们会发现,它使用一个ReadOrder
的字段来排序,Order越大,就排在前面,Order一样,则默认按文件名排序。这个ReadOrder
有以下规则:
-
Paks文件夹中,并已游戏名开头的文件起始Order为4;Content目录Order为 3 。如果paks文件夹中pak的文件名不是以游戏名为开头,则会满足Content这个条件。
-
Engine目录下的pak文件Order为2,游戏的用户存储目录则为1,其他为0 。
文件夹自身的优先级逻辑如下:int32 FPakPlatformFile::GetPakOrderFromPakFilePath(const FString& PakFilePath) { if (PakFilePath.StartsWith(FString: