UE4中Pak文件的读取规则
本文链接 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::Printf(TEXT("%sPaks/%s-"), *FPaths::ProjectContentDir(), FApp::GetProjectName()))) {return 4; } else if (PakFilePath.StartsWith(FPaths::ProjectContentDir())) {return 3; } else if (PakFilePath.StartsWith(FPaths::EngineContentDir())) {return 2; } else if (PakFilePath.StartsWith(FPaths::ProjectSavedDir())) {return 1; }return 0; }
在前两条规则的基础上,文件名以
_P.pak
为结尾的,享有额外Order。额外Order最低100。如果结尾形如_n_P.pak
其中n是数字,则会再额外得到 n乘以100的Order值。 例如_2_P.pak
则额外Order为 300 。// 如果文件名以 "_P.pak" 结束 if (PakFilename.EndsWith(TEXT("_P.pak"))) {uint32 ChunkVersionNumber = 1;FString StrippedPakFilename = PakFilename.LeftChop(6);// 倒着检测,看_P.pak 前面有没有 _n 结构int32 VersionEndIndex = PakFilename.Find("_", ESearchCase::CaseSensitive, ESearchDir::FromEnd);if (VersionEndIndex != INDEX_NONE && VersionEndIndex > 0){int32 VersionStartIndex = PakFilename.Find("_", ESearchCase::CaseSensitive, ESearchDir::FromEnd, VersionEndIndex - 1);if (VersionStartIndex != INDEX_NONE){VersionStartIndex++;FString VersionString = PakFilename.Mid(VersionStartIndex, VersionEndIndex - VersionStartIndex);if (VersionString.IsNumeric()){// 如果有数字并大于1 则认为这个数字是一个Version;为了保证基础100的Order,这里会额外 +1int32 ChunkVersionSigned = FCString::Atoi(*VersionString);if (ChunkVersionSigned >= 1){ChunkVersionNumber = (uint32)ChunkVersionSigned + 1;}}}}// 计算OrderPakOrder += 100 * ChunkVersionNumber; }
结论
通过上面的内容我们可以得出结论:
- Paks文件夹中的pak文件会全部自动挂载
- 非Paks文件夹中的pak文件需要自行手动挂载,效果和Paks文件夹中一致
- 使用一定格式的文件名,可以控制pak中文件的搜索顺序
这几个结论,可以推到出一个新的话题,那就是热更。通过下载新的pak,并控制搜索顺序,则可以很容易“屏蔽”老pak中的资源文件。当然这个新的pak需要一定规则生成,是一个补丁包,不是完整pak包。好在UE本身就提供差异修改打patch的工具, 下一篇我们就来讨论一下UE4的patch热更方案。 UE4 版本Patch方案
UE4中Pak文件的读取规则相关推荐
- ue4中Pak文件中挂载的资源名称获取
在pak文件中,会挂接很多资源.api也在变化, 废话不多说,上代码 FPakPlatformFile* GetPakPlatformFile() { FPakPlatformFile* pakPla ...
- C++中头文件的命名规则
C++中头文件的命名规则,因为C++是从C语言发展而来的,为了与C兼容,C++保留了C语言中的一些规定,其中就包括用.h作为后缀的头文件,比如大家所熟悉的:stdio.h.math.h和string. ...
- UE4的.pak文件的加密和签名
UE4源码支持.pak文件的数据加密和文件签名,并已集成在打包流程中,只需设置密钥后打包便会根据密钥配置自动进行.pak的加密和签名.加密和签名是相互独立的,可以只加密不签名也可以反之.注意:签名后会 ...
- C++中txt文件的读取和写入
C++中Txt文件读取和写入 一.ASCII 输出 为了使用下面的方法, 你必须包含头文件<fstream.h>(译者注:在标准C++中,已经使用<fstream>取代< ...
- java读取zip中指定文件_java读取zip中指定文件
public static void main(String args[]) { String file = "c://ssi.zip"; String saveRootDirec ...
- android中XMl文件的读取
废话不多说了直接上代码: 新建一个Xml文件用于读取: test.xml <Languages cat="1"><lan id="1"> ...
- android的读取xml配置文件,android中XMl文件的读取
废话不多说了直接上代码: 新建一个Xml文件用于读取: test.xml java Eclipse Swift Xcode C# Visual Studio 后台: import android.su ...
- python中读取文件编码_[转载]python中使用文件的读取编码问题
原文链接:https://www.cnblogs.com/qianboping/p/6524420.html 今天想写个程序合并文件的,以前一直觉得python的编码解码好烦,只要处理文件合并之类的都 ...
- vba访问服务器中txt文件,vba读取word内容 vba读取txt文件
excel vba 读取 word 指定字符 Sub 按钮1()Dim myPath As StringSet Wdapp = CreateObject("Word.Application")Wdap ...
最新文章
- 【DIY】一个名叫“故事鸡”的儿童玩具是如何用树莓派3B+练成的
- springMVC实现文件下载(附带Servlet方式)
- smokeping部署安装
- Objective-C 内存管理机制
- php分页类smary,Smarty分页实现方法完整实例
- Linux内核设计第四周——扒开系统调用三层皮
- Android开发笔记(三)屏幕分辨率
- 程序员漫画:影响程序员一生的书单
- 使用 Linux下 timerfd 系列 API 创建定时器并使用 epoll 监听
- 一文读懂全球CTRM市场的前世今生
- html5数字在线处理,Qunee for HTML5 - 中文 : 事件处理
- 非线性光学近似计算机应用,非线性光学.doc
- 服务器被攻击的常见手段以及解决方法
- SuperMap iMobel for Android 基础环境搭建
- 【Photoshop抠图技巧】PS新手必备,七种高效好用的方法
- AD怎么输入坐标_CAD入门基础小知识(二)捕捉栅格绘制直线amp;使用坐标绘图...
- android 生成Excel表
- 车载服务器系统,车载系统平台与终端产品的介绍
- 【转载】MATLB绘图
- 佛祖保佑,永无 BUG,永不修改 | KEIL 调试系列总结篇
热门文章
- rust嵌入式key/value数据库
- 【免费毕设】JSP旅游网站建设设计与实现(源代码+论文)
- 使用H5中的video标签时,页面中间显示“暂停”图标;点击播放,图标消失;点击暂停,图标出现(play、pause、ended)
- 如何利用(微软学术)/(google学术)/google网页,聚焦最新科技文献,并获得PDF版...
- 【视频格式】m3u8格式视频下载
- android java join_java中的join用法
- 苹果招聘人手继续改善Siri功能
- 将圆滑软件中的数据改写为用grapher画多测道图
- RK3288 编译不过遇到的问题
- 市场调研报告-全球与中国2-氨基-5-碘吡啶市场现状及未来发展趋势