本文链接 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文件在游戏启动的时候,会全部自动"挂载"

什么叫挂载?

代码里面叫做MountMount 是一个有别与Load的概念,Mount是读取pak文件中的文件信息,就是获取pak文件中有哪些文件,以便后续查找文件的时候,确定pak中是否有指定的文件。

什么时候挂载?

app启动的时候,在LaunchEngineLoop中的PreInit函数中,会调用FPakPlatformFile::MountAllPakFiles("Game/Content/Paks/") 。这个函数就是Paks下面所有的pak文件并遍历挂载。

2. 多个Pak如何决定加载及搜索顺序?

引擎内部维护一个已经挂载的pak文件列表,当需要打开其中的文件的时候,会遍历这些pak中的文件列表,查看该pak是否包含该文件,如果包含,则认为该文件包含在改pak中。

这个文件搜索方法表面:

  1. apk文件列表决定了查找顺序。
  2. 如果多个pak都包含某个文件,则肯定使用顺序在前的pak

3. pak文件名可以控制读取顺序

那么这个pak文件列表中的顺序是如何来决定的呢?阅读代码我们会发现,它使用一个ReadOrder的字段来排序,Order越大,就排在前面,Order一样,则默认按文件名排序。这个ReadOrder有以下规则:

  1. Paks文件夹中,并已游戏名开头的文件起始Order为4;Content目录Order为 3 。如果paks文件夹中pak的文件名不是以游戏名为开头,则会满足Content这个条件。

  2. 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;
    }
    
  3. 在前两条规则的基础上,文件名以_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;
    }
    

结论

通过上面的内容我们可以得出结论:

  1. Paks文件夹中的pak文件会全部自动挂载
  2. 非Paks文件夹中的pak文件需要自行手动挂载,效果和Paks文件夹中一致
  3. 使用一定格式的文件名,可以控制pak中文件的搜索顺序

这几个结论,可以推到出一个新的话题,那就是热更。通过下载新的pak,并控制搜索顺序,则可以很容易“屏蔽”老pak中的资源文件。当然这个新的pak需要一定规则生成,是一个补丁包,不是完整pak包。好在UE本身就提供差异修改打patch的工具, 下一篇我们就来讨论一下UE4的patch热更方案。 UE4 版本Patch方案

UE4中Pak文件的读取规则相关推荐

  1. ue4中Pak文件中挂载的资源名称获取

    在pak文件中,会挂接很多资源.api也在变化, 废话不多说,上代码 FPakPlatformFile* GetPakPlatformFile() { FPakPlatformFile* pakPla ...

  2. C++中头文件的命名规则

    C++中头文件的命名规则,因为C++是从C语言发展而来的,为了与C兼容,C++保留了C语言中的一些规定,其中就包括用.h作为后缀的头文件,比如大家所熟悉的:stdio.h.math.h和string. ...

  3. UE4的.pak文件的加密和签名

    UE4源码支持.pak文件的数据加密和文件签名,并已集成在打包流程中,只需设置密钥后打包便会根据密钥配置自动进行.pak的加密和签名.加密和签名是相互独立的,可以只加密不签名也可以反之.注意:签名后会 ...

  4. C++中txt文件的读取和写入

    C++中Txt文件读取和写入 一.ASCII 输出 为了使用下面的方法, 你必须包含头文件<fstream.h>(译者注:在标准C++中,已经使用<fstream>取代< ...

  5. java读取zip中指定文件_java读取zip中指定文件

    public static void main(String args[]) { String file = "c://ssi.zip"; String saveRootDirec ...

  6. android中XMl文件的读取

    废话不多说了直接上代码: 新建一个Xml文件用于读取: test.xml <Languages cat="1"><lan id="1"> ...

  7. android的读取xml配置文件,android中XMl文件的读取

    废话不多说了直接上代码: 新建一个Xml文件用于读取: test.xml java Eclipse Swift Xcode C# Visual Studio 后台: import android.su ...

  8. python中读取文件编码_[转载]python中使用文件的读取编码问题

    原文链接:https://www.cnblogs.com/qianboping/p/6524420.html 今天想写个程序合并文件的,以前一直觉得python的编码解码好烦,只要处理文件合并之类的都 ...

  9. vba访问服务器中txt文件,vba读取word内容 vba读取txt文件

    excel vba 读取 word 指定字符 Sub 按钮1()Dim myPath As StringSet Wdapp = CreateObject("Word.Application")Wdap ...

最新文章

  1. 【DIY】一个名叫“故事鸡”的儿童玩具是如何用树莓派3B+练成的
  2. springMVC实现文件下载(附带Servlet方式)
  3. smokeping部署安装
  4. Objective-C 内存管理机制
  5. php分页类smary,Smarty分页实现方法完整实例
  6. Linux内核设计第四周——扒开系统调用三层皮
  7. Android开发笔记(三)屏幕分辨率
  8. 程序员漫画:影响程序员一生的书单
  9. 使用 Linux下 timerfd 系列 API 创建定时器并使用 epoll 监听
  10. 一文读懂全球CTRM市场的前世今生
  11. html5数字在线处理,Qunee for HTML5 - 中文 : 事件处理
  12. 非线性光学近似计算机应用,非线性光学.doc
  13. 服务器被攻击的常见手段以及解决方法
  14. SuperMap iMobel for Android 基础环境搭建
  15. 【Photoshop抠图技巧】PS新手必备,七种高效好用的方法
  16. AD怎么输入坐标_CAD入门基础小知识(二)捕捉栅格绘制直线amp;使用坐标绘图...
  17. android 生成Excel表
  18. 车载服务器系统,车载系统平台与终端产品的介绍
  19. 【转载】MATLB绘图
  20. 佛祖保佑,永无 BUG,永不修改 | KEIL 调试系列总结篇

热门文章

  1. rust嵌入式key/value数据库
  2. 【免费毕设】JSP旅游网站建设设计与实现(源代码+论文)
  3. 使用H5中的video标签时,页面中间显示“暂停”图标;点击播放,图标消失;点击暂停,图标出现(play、pause、ended)
  4. 如何利用(微软学术)/(google学术)/google网页,聚焦最新科技文献,并获得PDF版...
  5. 【视频格式】m3u8格式视频下载
  6. android java join_java中的join用法
  7. 苹果招聘人手继续改善Siri功能
  8. 将圆滑软件中的数据改写为用grapher画多测道图
  9. RK3288 编译不过遇到的问题
  10. 市场调研报告-全球与中国2-氨基-5-碘吡啶市场现状及未来发展趋势