UE资源热更打包工具HotPatcher

重要通知:作者没有任何平台和渠道录制收费课程,也不对任何第三方的商业行为背书。请擦亮双眼,谨防上当受骗。
本软件的开源协议:允许在商业项目中免费使用功能,但不允许任何第三方基于该插件进行任何形式的二次收费,包括但不限于录制收费课程、对插件及代码的二次分发等。

HotPatcher是一个用于管理热更版本和资源打包工具,用于追踪工程版本的原始资源变动来打出Patch。支持一键Cook多平台,一键打包多平台Patch,编辑器支持Windows和MacOS,再写一套从服务器下载patch的流程就是一套完整的游戏热更方案。HotPatcher已经在非常多的UE项目中使用,并会持续更新支持新的引擎版本,欢迎提issus。

HotPatcher与UnrealFrontEnd中的Patch机制不同,UE的Patch管理工程时存在一些问题:基于原始的的工程版本,很难在不同的电脑上打出完全相同的Patch,也无法基于Patch的版本再打出一个Patch,并且Patch包含的内容不能够直观预览。并且不能方便地能够把外部文件打包到pak中(如lua文件、db等non-assets,往往不在Content目录下),也无法方便地管理工程和Patch版本。

这个插件就是为了解决这样的问题,以项目原始资源作为版本依据,只需管理工程本身而无需关注UE生成的其他文件。并且可以方便地进行Cook/生成Pak/提取基础包中的资源信息/版本间diff/Patch拆分等操作。具有非常丰富的配置化选项与Commandlet支持,可以非常方便地实现自动化热更新出包流程。

目前支持的引擎版本为UE4.21-UE5,并对IoStore机制提供了支持!有很多朋友私信来问插件相关的问题,我创建了个群来讨论UE热更新和HotPatcher插件的问题(QQ群958363331),欢迎加入交流UE相关的技术。

为了方便地统一收集和管理热更新和HotPatcher常见的问题与解决方案,我新建了一篇文章来记录和整理:UE4热更新:Questions & Answers,遇到问题可以先去看这个FAQ页面。关于比较多人反馈插件内配置参数与之前的录制视频不一致的问题,是因为插件进行了很多更新迭代,每个版本的详细变动,可看更新日志

Showcase

元梦之星 QQ Apex Legends Mobile WitiSports MOSSAI 二之国:交错世界

基于HotPatcher的资源管理框架

HotPatcher已经不仅仅只是一个热更打包工具,而是一套涵盖了热更新、构建提升、包体优化、资源审计等全方位的资源管理框架。

Forward

注意:该插件只能打出包含UE的资源以及添加的外部文件作为热更的内容(支持lua),修改的C++代码无法热更,需要自己设计好架构。如果是纯蓝图项目则可以完全使用这个工具进行热更。

HotPatcher插件支持根据选择只打包指定的资源(可以指定包含过滤器以及忽略过滤器以及可以指定单个资源),支持资源的递归依赖分析(如只打包某个地图及其所有依赖的资源),打包的Path中可以选择不包含未引用的资源,也不会包含未改动的资源,还会分析项目中的无效资产以及忽略重定向器的资源,实现了基于项目资产的版本追踪而无需管理额外的内容(如DDC),只需要在打Patch之前Cook一遍保证Cook的内容是基于最新工程版本的即可(也支持在生成Patch时自动Cook所有要包含的资源)。而且还支持Chunk、支持bMonilithic模式,配置化的方式支持随意组合,支持导出资源的依赖关系,而且还支持通过Commandlet来执行Cook和Patch以及Release信息的导出,可以随意结合ci/cd实现自己的出包流程。

除了包含UE的资源文件外,额外的支持:

  • 支持给特定的平台添加平台相关的文件(如每个平台的Wwise bnk文件)
  • 支持包含项目Cook出的非资源文件。如AssetRegistry.bin/GlobalShaderCache*.bin/ShaderBytecode*.ushaderbytecode;
  • 支持包含引擎、项目、和插件的ini文件;
  • 支持包含外部的文件夹和文件(如lua文件,视频文件等),并且可以自定义挂载点,供运行时访问;
  • 打出的pak中可以不包含任何UE的资源文件(只要在HotPatcher中不添加任何资源即可),方便只更新lua的代码或者只更新Ini之类的配置文件;
  • 支持分析不同平台的基础包的差异,生成统一的基础包描述文件,用于后续热更的版本比对。

插件的其他功能:

  • 支持Cook单个资源;
  • 支持从PakList*.txt中导入多平台的基础包信息
  • 支持基于上一个patch版本再打出一个patch版本;
  • 支持检测未cook的资源;
  • 支持版本间的diff,可以看到新增、修改、删除(但是删除的资源在之前的版本的pak中是无法删除的,只是diff展示用)的资源信息;
  • 支持检测重复的文件包含;
  • 支持导出该插件所有的中间生成信息和配置;
  • 支持自定义UnrealPak的参数(可以自己指定加密参数与项目统一);
  • 支持同时打出多个平台的patch;
  • 支持Patch的Chunk,指定在一个Patch版本中把资源分别打包到多个Pak中;
  • 支持检测Chunk的文件包含进行错误处理
  • 支持把Patch中的每个资源单独打包为pak,支持任意资源(包括但不限于UE asset/外部文件/各种cooked的bin数据、ini)只要是hotpatcher里可以添加的都可以单独打成pak。
  • 支持多线程打包pak,不启动UrealPak.exe,提高执行效率。
  • 支持导出所选资源的依赖关系
  • 编辑器支持Cook/AddToPatchSettings等功能,方便编辑器下的操作
  • 支持在Cook的同时手机Shader等metadata信息
  • 支持IoStore
  • 支持增量地更新Shader、AssetRegistry
  • 支持Shader Patch

同时,我也写了一个批量Cook的工具,用于一键Cook指定的多个平台(当然使用命令行也可以),目的就是使用最少的步骤完成任务。

我录了一个插件使用说明的视频:

如果不能翻墙可以看B站的链接:UE4热更新:HotPatcher插件使用教程

插件使用流程

为了方便版本管理,项目一定要使用某种版本控制工具,建议Git.

  1. 打开HotPatcher,选择ByRelease,导出*_Release.json,其中记录了所指定的每个资源的信息;
  2. 使用UE直接打包任意平台的项目(如windows/android/ios)
  3. 在工程中修改/添加/删除资源,修改引擎/项目/插件的设置等;
  4. 打开HotPatch,在Cook项选择你要打Patch的平台并执行Cook(勾选bCookPatcherAssets);
  5. 打开HotPatcher,选择ByPatch,以上面导出的*_Release.json为基础版本,根据需求选择你需要打到Pak中的内容;
  6. 点击GeneratedPatch,会生成Pak文件和各种信息(其中也包含当前版本的*_Release.json,使Patch可以增量更新)
  7. 生成的Pak中就包含了与上次打出的包中所有差异的内容。

Cook参数说明

重要:HotPatcher内实现了单独的Cook流程,无需再执行UE默认的Cook过程(插件中的Cooker部分),只需要在Patch的配置中启用bCookPatchAssets即可。

HotPatcher中的Cook部分是为了打Patch时方便Cook多个平台,以及方便指定地图(插件会扫描整个项目中的所有地图并列出),不用每次Cook都使用命令行。

Cook可选的分为Platforms/Map(s)/Settings

  • Platforms:选择Cook 的平台,可以多选;
  • Map(s):选择要Cook的Map,该选项下会列出当前工程里所有的Map,可以多选(代码里我也提供了列出引擎和插件目录下Map的选项,如果需要可以在HotPatcherEditor.build.cs中通过控制ENABLE_COOK_ENGINE_MAPENABLE_COOK_PLUGIN_MAP的值来自行开启);
  • Filter(s):可以选择只Cook指定的目录,可以添加多个;
  • Settings:选择Cook设置,默认提供了Iterator/UnVersioned/CookAll/Compressed四个选项,我也提供了OtherOptions可以自己指定要Cook 的参数。

注意:Map(s)中的地图和Settings中的CookAll必须要选中其中的一个或者Filters中具有指定的目录才可以执行Cook,如果只选了CookMap,则只会Cook该Map所引用到的资源,没有被引用的不会被Cook,这个需要注意。

点击CookContent之后会将Cook的log输出到UE的OutputLog中。

ByRelease参数说明

ByRelease操作导出的是一个json的文件,记录了导出时所选择的每个Asset资源的HASH值,基于此HASH值我们可以在后续的Patch中知道该资源是不是被修改了。

Release Settings

  • VersionId:指定当前导出的资源信息是什么版本。
  • ByPakList:从PakList导入来生成Release的配置。
  • PlatformsPakListFiles:打基础包生成的PakList*.txt文件,可以同时指定多个平台,用于分析各个平台的文件差异,并记录这些差异来生成项目在这些平台的Release.json文件,用于统一描述多个平台的基础包信息。

在不通过指定PakList*.txt导出Release的情况下,导出的release.json中只包含项目中有引用的资源,没有引用的不会包含。但是引擎默认打包时会把一些没有引用的资源也打包到里面,这就会导致一些资源在基础包中事实上已经存在了,但是在release.json中没有记录,有用到这些资源的话会导致重复包含(使用时没有问题,只是这些资源在pak中会有两份)。使用PakList*.txt就不会存在这个问题。

  • IncludeFilter:当前Release扫描哪些目录下的资源。
  • IgnoreFilter:当前Release忽略哪些目录下的资源。
  • bAnalysisFilterDependencies:对所选过滤器的资源进行依赖分析
  • AssetRegistryDependencyTypes:对所选过滤器中得资源进行依赖分析时要包含的引用资源类型,依赖于bAnalysisFilterDependencies是否启用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace EAssetRegistryDependencyType
{
enum Type
{
// Dependencies which don't need to be loaded for the object to be used (i.e. soft object paths)
Soft = 0x01,

// Dependencies which are required for correct usage of the source asset, and must be loaded at the same time
Hard = 0x02,

// References to specific SearchableNames inside a package
SearchableName = 0x04,

// Indirect management references, these are set through recursion for Primary Assets that manage packages or other primary assets
SoftManage = 0x08,

// Reference that says one object directly manages another object, set when Primary Assets manage things explicitly
HardManage = 0x10,

// Note: Also update FAssetRegistryDependencyOptions when adding more flags
};

static const Type None = (Type)(0);
static const Type All = (Type)(Soft | Hard | SearchableName | SoftManage | HardManage);
static const Type Packages = (Type)(Soft | Hard);
static const Type Manage = (Type)(SoftManage | HardManage);
}

Soft是具有FSoftObjectReference的资源引用,Hard是直接的资源引用,如果想要Soft和Hard都包含,可以选择Package,这个选项默认情况下选Package就好,除非你自己来处理资源引用关系。

  • IncludeHasRefAssetsOnly:对选中的过滤器中的资源文件进行依赖分析(递归分析至Map),如果资源没有被引用则不会打包到Patch中。
  • IncludeSpecifyAssets:结构的数组,可以指定当前Release中的单个资源,该结构的第一个参数需要指定资源,第二个参数控制是否分析并包含当前指定资源的依赖到pak中。
  • Add Extern Assets to Platform:用于指定在不同的平台包含的不同的文件。
    • Target Platform:包含这些文件的平台(AllPlatform则是每个平台都包含)
    • AddExternFileToPak:记录Release中包含的非资源文件
    • AddExternDirectoryToPak:记录Release中包含的非资源文件

AddExternFileToPakAddExternDirectoryToPak对应的是Project Settings-Packing中的Additional Non-Asset Directories To Package等设置,用于标记本地包中所包含的非资源文件。

SaveTo

  • SaveAssetDependency:是否存储当前Release版本中所选资源的依赖关系。
  • SaveReleaseConfig:是否存储当前Release的所有选项信息。
  • bBackupMetadatas:是否备份当前版本的Metadata目录。
  • BackupMetdataPlatforms:选择要备份Metadata的平台,该选项依赖于bBackupMetadatas=true
  • SavePath:本次的Release信息存储位置。会在当前目录下创建出名字为VersionId的文件夹,所有的文件在此文件夹中,支持[PROJECTDIR]等标记相对路径。

注意:导出Release时,资源的包含需要与UE直接打包时的设置一致,因为这里导出的Release是记录使用UE直接打出的包所包含的资源。

ByPatch参数说明

ByPatch是真正执行打包出Pak的工具,可以基于之前导出的版本(通过ByRelease导出的Json文件),也可以包含外部文件/文件夹、配置文件(ini)、Cook出的非资源文件(AssetRegistry.bin等),并且可以指定多个平台,支持输入UnrealPak的参数,可以导出当前Patch的各种信息。

支持指定资源过滤器:

HotPatcher打Patch的选项解析:

BaseVersion

  • bByBaseVersion:是否是基于某个基础版本的Patch,若为false,则只打包选择的过滤器文件(依然会分析依赖)和添加的外部文件,若为true则必须要指定一个基础版本,否则无法执行Patch。同时该属性也会控制是否生成Diff信息,若为false则不生成Diff(没有基础版本diff也无意义)。
  • BaseVersion:该选项应选择Patch所基于的版本文件,可以ByRelease或者上次一的Patch生成,默认为*_Release.json

PatchSettings

  • VersionId:当前Patch的版本的ID
  • IncludeFilter:当前Patch扫描哪些目录下的资源变动。
  • IgnoreFilter:当前Patch忽略哪些目录下的资源变动(资源依赖分析之前)。
  • bForceSkipContent:是否开启强制忽略掉某些资源(对Patch的最终结果进行过滤)
  • Force Skip Content Rules:强制忽略掉某些目录下的资源(对Patch的最终结果进行过滤),可以用于忽略Editor的Content内容,如/Engine/Editor/Engine/VREditor等。
  • Force Skip Assets:再Patch的最终结果中忽略掉指定的资源。
  • bAnalysisFilterDependencies:对所选过滤器的资源进行依赖分析
  • Recursive Widget Tree:对于当前Patch中变动的UserWidget资源,递归分析包含它们的parent Widget资源,并包含进Patch中,用于解决修改了子控件,父控件不生效的问题。
  • AssetRegistryDependencyTypes:与Release中描述的含义相同。
  • IncludeHasRefAssetsOnly:对选中的过滤器中的资源文件进行依赖分析(递归分析至Map),如果资源没有被引用则不会打包到Patch中。
  • IncludeSpecifyAssets:结构的数组,可以指定需要打到Pak中的单个资源,该结构的第一个参数需要指定资源,第二个参数控制是否分析并包含当前指定资源的依赖到pak中,第三个参数AssetRegistryDependencyTypesRelease中描述的含义相同。。
  • IncludeAssetRegistry:在当前的Patch打出的Pak中包含AssetRegistry.bin文件。(已废弃)
  • IncludeGlobalShaderCache:在当前的Patch打出的Pak中包含GlobalShaderCache-*.bin文件。(已废弃)
  • IncludeShaderBytecode:在当前Patch打出的Pak中包含PROJECT_NAME\Content\ShaderArchive*.ushaderbytecode文件。(已废弃)
  • IncludeEngineIni:在当前打出的Patch中包含引擎目录下的ini,也会包含平台相关的ini
  • IncludePluginIni:在当前打出的Patch中包含所有启用的插件中的ini(引擎目录和项目目录的插件都会包含)
  • IncludeProjectIni:在当前的Patch打出的Pak中包含项目的ini文件(不会包含DefaultEditor*.ini
  • bEnableExternFilesDiff:是否对添加的外部文件进行Diff比对,用于只打包修改或者新增的外部文件。
  • Add Extern Assets to Platform:用于指定在不同的平台包含的不同的文件。
    • Target Platform:包含这些文件的平台(AllPlatform则是每个平台都包含)
    • AddExternFileToPak:添加外部的非资源文件到Pak中,如txt、视频。
    • AddExternDirectoryToPak:记录Release中包含的非资源文件

AddExternFileToPak的元素要求:

  1. FilePath需要指定所选文件的路径。
  2. MountPath为该文件被打包到Pak中的挂载路径,默认是../../../PROJECT_NAME/下。

在游戏运行时可以通过FPaths::ProjectDir来访问。
如,AAAA.json的MountPath../../../HotPatcherExample/AAAAA.json,在运行时加载的路径:

1
FPaths::Combine(FPaths::ProjectDir(),TEXT("AAAAAA.json"));

Pak中的所有文件可以通过IPlatformFile来访问。

  • AddExternDirectoryToPak:结构的数组,添加外部文件夹到Pak中,该结构第一个参数(DirectoryPath)为指定系统中的文件夹路径,第二个参数(Mount Point)指定该路径在Pak中的挂载路径;指定文件夹下的所有文件会被递归包含,并且挂载路径均相对于所指定的MountPoint

  • IncludePakVersionFile:是否在当前打出的Patch中存储版本信息。

  • PakVersionFileMountPoint:由IncludePakVersionFile控制是否可以编辑,用于指定*_PakVersion.json文件在Pak文件中的挂载点,默认为../../../PROJECT_NAME/Extention/Versions

ChunkOptions

我为HotPatch增加了Chunk的功能,支持把一个Patch中的资源分别打包到不同的Pak中去。如把一个Patch中的所有Package打包到一个pak里(或者把当前Patch的指定地图打包到某个pak里),所有的lua打包到另一个pak里。

Chunk支持的参数如下:

  • bEnableChunk:是否对当前的Patch执行Chunk
  • bCreateDefaultChunk:是否创建默认的Chunk,用于存储在手动指定的Chunks中不存在的文件
  • ChunkInfos:Chunk信息的列表,用于指定Chunk中应该包含哪些资源。

ChunkInfos的是一个FChunkInfo的结构数组,其结构的成员为:

  • ChunkName:当前Chunk的名字
  • bStorageUnrealPakList:是否存储当前Chunk的PakCommand.txt
  • bStorageIoStorePakList:是否存储当前chunk的IoStore的paklist文件
  • AssetIncludeFilters:指定Chunk中的资源过滤器(注意所选过滤器中的资源不会进行依赖分析)
  • AssetIgnoreFilters:指定Chunk的忽略过滤器
  • bAnalysisFilterDependencies:对所选过滤器的资源进行依赖分析
  • AssetRegistryDependencyTypes:与Release中描述的含义相同。
  • IncludeSpecifyAssets:指定Chunk中包含哪些单个资源,支持进行依赖分析
  • AddExternFileToPak:添加外部文件到Chunk
  • AddExternDirectoryToPak:添加外部目录到Chunk,支持递归分析
  • InternalFiles:用于指定Chunk中是否包含AssetRegistry.binIni等文件

基本上Chunk的参数和Patch选择的参数的一致,可以按照需求配置。

注意:Chunk的原理是:先在Patch的设置中选择资源,会执行一遍整个Patch的资源分析,分析出来的结果用于Chunk配置的过滤,意思就是Chunk中所包含的资源必须是本次Patch的中具有的,一定要注意AssetIncludeFilters不会进行依赖分析,如果你Patch中的过滤器中的资源引用到了其他模块,比如引擎或者插件,在Chunk中也需要指定相应的目录到过滤器。

每个Chunk中所指定的资源可以重复,一份资源可以在ChunkA中包含也可以被ChunkB包含。

而且我还给Chunk增加了错误提示,如果开启了Chunk模式,但是Patch中的所有资源没有在Chunk中全部指定,会在HotPatcher底部的Infomations中提示有哪些资源没有在Chunk中被包含,方便进行错误处理。

PakOptions

  • bCookPatchAssets:是否开启为Patch中的uasset进行Cook,如果开启会在打包时对当前Patch中的所有uasset资源进行Cook(会增加Patch的生成时间,需要等待Cook完成)

  • Io Store Settings

  • bIoStore:是否开启Io Store

  • bAllowBulkDataInIoStore:是否允许bulk data存储到Io Store中

  • IoStorePakListOptions:传递给IoStorePaklist的参数,如-compress

  • IoStoreCommandletOptions:传递给IoStoreCommandlet的参数

  • PlatformContainers:需要指定每个平台的global.utoc以及IoStore Patch的路径

  • bStoragePakList:存储IoStore的paklist文件

  • bStorageBulkDataInfo:存储StorageBulkDataInfo,当开启CookPatchAssets时,将Cook的信息存储到BulkDataInfo.ubulkmanifest,可以不开启(目前不支持CookPatchAssets支持IoStore)

  • Unreal Pak Settings

  • UnrealPakListOptions:传递给paklist文件的参数,如-compress

  • UnrealCommandletOptions:传递给UnrealPak的参数

  • Encrypt Settings

  • bEncrypt:开启加密

  • bEncrypt:加密Index

  • bUseDefaultCrypt.ini:使用项目中config/DefaultCrypt.ini中的配置

  • bSign:开启Sign

  • CryptoKeys:指定Crypto.json文件,当没有选中bUseDefaultCrypt.ini时可指定

  • DefaultPakListOptions:该数组可以指定打包pak或IoStore每条资源的的参数,如-compress

  • DefaultCommandletOptions:该数据可以指定执行pak/IoStore的命令时commandlet的追加参数。

  • ReplacePakCommandTexts:用于替换PakCommand.txt中的文本

  • PakTargetPlatforms:该数组为选择要打出的Patch的平台,可以多选,一定要注意所选的平台已经被Cook。

PakOptions Advanced:

  • bCustomPakNameRegular:是否重写Pak命名规则,控制PakNameRegular是否可修改。
  • PakNameRegular:生成Pak的命名规则,可以通过预置变量值来控制,目前预置值有:{VERSION}/{BASEVERSION}/{CHUNKNAME}/{PLATFORM}四个值,在生成时会替换为当前配置的具体值,默认的命名规则为{VERSION}_{CHUNKNAME}_{PLATFORM}_001_P,如果在没有开启Chunk的情况下,{CHUNKNAME}值为空,并且会处理掉两个连续的__

SaveTo

  • bIgnoreDelatedAssetsInfo:在Patch信息中清理掉被删除的asset/文件信息,开启意味着不会记录被删除的文件。
  • bStorageDeletedAssetsToNewReleaseJson:控制ContentBrowser中删除的资源是否存储到新ReleaseJson中去,具体描述请看2020.11.07 Update
  • bStoragePakList:是否存储UnrealPak.exe-Create参数文件。
  • bStorageDiffAnalysisResults:是否存储当前的Patch版本与Base版本的差异信息。
  • bStorageAssetDependencies:是否存储当前Patch版本中所选资源的依赖关系。
  • bStoragePatchConfig:是否存储当前Patch的所有选项信息。
  • bBackupMetadatas:是否备份当前版本的Metadata目录。
  • SavePath:本次的Patch信息存储位置。会在当前目录下创建出名字为VersionId的文件夹,所有的文件在此文件夹中。

Advanced

  • bStandaloneMode:是否以独立模式运行,勾选会拉起一个单独的UE进程执行Patch任务,不会阻塞当前的编辑器,在资源规模庞大的情况下建议勾上此选项。
  • bScanCacheOptimize:开启以来扫描缓存优化,可以加快依赖分析的速度。

ByShaderPatch参数说明

ShaderPatch通过指定新/旧版本的Metadata目录,读取其中的ShaderLibrarySource目录中的.ushaderbytecode文件来进行比对和Patch的。

Version

  • VersionID:当前ShaderPatch的版本号

Config

  • ShaderPatchConfigs:ShaderPatch的配置,是一个结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
USTRUCT(BlueprintType)
struct FShaderPatchConf
{
GENERATED_USTRUCT_BODY()

UPROPERTY(EditAnywhere, BlueprintReadWrite)
ETargetPlatform Platform;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FDirectoryPath> OldMetadataDir;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FDirectoryPath NewMetadataDir;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bNativeFormat;
// since UE 4.26 (Below 4.26 this parameter has no effect)
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bDeterministicShaderCodeOrder = true;
};

Save

  • bStorageConfig:是否存储当前的配置文件
  • SavePath:Patch和配置文件的生成路径

Advanced

  • bStandaloneMode:拉起一个单独的进程执行任务,不阻塞编辑器。

Commandlet

我给插件提供了四个个Commandlet,分别是HotCookerHotPatcher以及HotReleaseHotShaderPatch,用于Cook、Patch生成、导出Release信息以及ShaderPatch,

这四个Commandlet都可以指定-wait参数当Commandlet执行完毕时等待输入(防止窗口自动关闭)。

Commandlet指定的-config文件中的属性可以被替换,使用-PropertyName=来指定(目前不支持指定数组),如果是结构的嵌套属性,如SavePath.Path这样的成员属性,可以通过.来指定:-savepath.path=

HotPatcher的Commandlet增强支持可以看更新Log:2021.01.14 Update

HotCooker

重要:该功能已废弃,只需要勾选bCookPatchAssets即可。

Cooker使用方法:

1
UE4Editor.exe PROJECT.uproject -run=HotCooker -config="cook-config.json"

在编辑器中导出cook配置的时候如果选中了所有地图,会在导出的配置文件里会把bCookAllMap为true,在Cook的Commandlet里执行就会Cook所有地图了,而且只要bCookAllMap为true就会Cook所有地图,和CookMaps里的地图数量没关系。

HotPatcher

Patcher使用方法:

1
UE4Editor.exe PROJECT.uproject -run=HotPatcher -config="patch-config.json"

HotRelease

Release使用方法:

1
UE4Editor.exe PROJECT.uproject -run=HotRelease -config="export-release-config.json"

HotShaderPatch

ShaderPatch使用方法:

1
UE4Editor.exe PROJECT.uproject -run=HotShaderPatch -config="export-shaderpatch-config.json"

它们的-config参数所接收的文件都可以从编辑器中通过插件导出。

编辑器支持(UE4.23+)

HotPatcher添加了在ContentBrowser中对资源选中的右键菜单扩展,可以实现一键Cook、添加所选的资源至Patch Setting的功能。

Cook

AddToPatchSettings

项目设置

插件支持在编辑器中右键选中资源进行Cook和打包,为了方便配置,在Project Settings中创建了HotPatcher的配置项:

可以用来指定UnrealPak的参数、加密配置、打包的存储目录等。

Update Log

2024.04.07 Update v82.0

更新地址:v82.0,相较于上个版本,进行了大量优化和BUG修复。

不管在哪个引擎版本中使用HotPatcher,都强烈建议你更新到最新的版本,出现问题也便于排查。

更新内容如下

  1. 修复在某些情况下*.m.ubulk文件未被打包进去的bug
  2. 优化了PAK的打包耗时,对大量文件的扫描做了缓存和多线程优化,大幅提升打包速度
  3. 支持Accompany的COOK模式
  4. 添加了更多的性能标记
  5. 优化日志级别
  6. 支持cache-ddc-only的Cook模式
  7. 模块启动时自动加载../../../PROJECT_NAME/ShaderLibs目录下的所有ShaderLibrary
  8. 支持Nanite和WP的COOK
  9. WP的差异更新支持(由于WP的One File Per Actor机制,修改WP场景并不会导致关卡资源本身的变动,我扩展了一种检测机制,可以实现WP的差异检测)
  10. 优化FExternFiles的访问
  11. 优化Release记录的外部文件从绝对路径变为标记路径
  12. 修复在UE5中COOK时产生假文件的问题
  13. 修复导出release时的路径包含//的问题
  14. 修复PatcherProxy获取到PackageTracker不准确的问题
  15. 优化PackageTracker的实现,剔除已经Track到的资源
  16. 优化PackageTracker,可递归Tracker分析
  17. 统一CollectPakCommand中ParallelFor的锁,避免竞争问题
  18. 支持-AddAssetsByFile=参数传递一个LongPackageName的列表打包
  19. 修复ShaderLib未被打包进pak的问题
  20. 允许在Cook的Cmdlet里添加Pre与Post任务
  21. 优化插件Slate实现,在Toolbar中支持二级菜单,直接选中打开对应的页面
  22. 支持监听进程的Crash,并会将Crash文件存储到Saved/HotPatcher/Crashs
  23. 兼容GameFeaturePacker与ShaderPatcher两个Mods(均需更至最新)

目前v82.0已经正式发布,可以从hxhb/HotPatcher拉取和更新。旧版本插件打开Patch页面也会有新版本的更新提示。

2023.06.05 Update v81.0

更新地址:Release v81.0

1. 修复CmdlHandler的日志输出问题、DDC Backend配置不Clean
2. Cmdlet支持TargetPlatformsOverride可替换配置文件中的TargetPlatform
3. 执行Patch时可通过NoSearchAllAssets禁止资源扫描
4. 优化GC时机
5. 修复开启PackageTracker追踪到包含在基础版本里未变动的资源
6. 优化Notification输出格式
7. 统一patch时的config/release/diff的保存路径规则 
8. 支持仅Cook Shader类资源
9. 支持CookAdvancedOptions选项
10. 支持输出PakResults.json记录所有打包的资源及获取接口
11. 优化Log输出,非必要不打Error级别的日志
12. 避免Cooked文件检查对资源的加载
13. 支持ChunkAliasName,作为Chunk的别名,支持中文
14. 优化LoadShaderbytecode相关代码
15. 修复从加密pak中导入时的AESKey无效问题
16. 修复在Linux平台资源分析时的逻辑运算符的歧义
17. 添加更多的ProfilingTag
18. 更新MOD的版本
19. 修复UE5.1 Linux编译错误
20. 修复每个Chunk都包含了所有变更的问题
21. 修复GetProjectNotAssetDirConfig中多余的%s
22. 修复TargetPlatform注册时机晚于CDO的问题 

注:本版本暂不支持UE5.2,同时这也应该是支持UE5.1的最后一个版本。因为UE5.2引擎中有实现变化,后续更新的适配中只会支持UE5的最新版本。

2023.02.28 Update v80.1

更新地址:Release v80.1

  • 修复PackageTrackerAsCluster中无效路径导致的ErrorLog
  • 调整Metadata的产出路径
  • 支持获取参与打包的资源列表
  • 优化PackageTracker的追踪实现
  • 修复ForceSkip的Directory/Asset过滤的bug
  • 修复多线程处理PakCommand时的竞争
  • 修复TargetPlatform注册时机晚于CDO的问题
  • 修复PackageTracker的资源没有进包的问题(PackageTracker的资源会进行ForceSkip检测)
  • bSupportWorldComposition默认改为false

2023.01.08 Update v80.0 HotPatcher Modular

更新地址:Release v80.0HotPatcher 的模块化改造和开发规划

  1. 修复Regular相关的Category不显示问题
  2. 优化CmdHandler实现,支持Editor和Runtime的Config Override
  3. HotPatcher的模块化改造,详见HotPatcher 的模块化改造和开发规划
  4. 将ByShaderPatch与ByGameFeature分别创建为独立的Mod
  5. 优化插件的启动流程和优先级,支持模块的扩展
  6. 支持预览当前已安装的模块及检测单个模块的更新

2022.12.30 Update v79.0

更新地址:Release v79.0

  1. 优化基础实现、关闭不必要的Log输出
  2. 优化对依赖加载材质的额外Shader编译, 支持NoPostLoadCacheDDC参数控制(UE4中需要修改引擎才能使用该优化)
  3. 优化CookCluster的分配策略
  4. 优化Pak文件列表收集
  5. 优化资源分析性能
  6. 优化模块的可扩展性
  7. 修复跨引擎版本的兼容性问题
  8. 修复Shipping的C4172 ERROR
  9. 修复不支持WP导致的基础包打包错误(Found mor than one redistered Cook Package Splitter
  10. 支持PakSaveDirRegular,自定义Pak的输出路径
  11. 支持PakPreset/CookAndPak以统一的方式执行
  12. 支持全局的AllowCookPlatforms

源码版引擎的NoPostLoadCacheDDC参数支持需要修改引擎,添加以下[lipengzha]中包裹的代码:

Launcher引擎默认不支持该优化,Cook耗时会慢一些,但对功能无影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Engine/Source/Runtime/Engine/Private/Materials/MaterialInstance.cpp
void UMaterialInstance::PostLoad()
{
// ...
//++[lipengzha] cmdlet option for disable cook in PostLoad
bool bNoPostLoadCacheDDC = FParse::Param(FCommandLine::Get(), TEXT("NoPostLoadCacheDDC"));
if (!bNoPostLoadCacheDDC && TPM && (TPM->RestrictFormatsToRuntimeOnly() == false))
//--[lipengzha]
{
TArray<ITargetPlatform*> Platforms = TPM->GetActiveTargetPlatforms();
// Cache for all the shader formats that the cooking target requires
for (int32 FormatIndex = 0; FormatIndex < Platforms.Num(); FormatIndex++)
{
BeginCacheForCookedPlatformData(Platforms[FormatIndex]);
}
}
// ...
}
// Engine\Source\Runtime\Engine\Private\StaticMesh.cpp
void UStaticMesh::PostLoad()
{
// ...
//++[lipengzha] cmdlet option for disable cook in PostLoad
bool bNoPostLoadCacheDDC = FParse::Param(FCommandLine::Get(), TEXT("NoPostLoadCacheDDC"));
if(!bNoPostLoadCacheDDC)
{
CacheDerivedData();
}
//--[lipengzha]
// ...
}

2022.11.29 Update v78.0

更新地址:Release v78.0

注意:因为UE5仍在早期阶段,Epic每次更新对引擎的变动挺大。所以,HotPatcher对UE5的支持只兼容最新引擎版本,暂不考虑UE5其他版本的兼容性(如UE5 EA/EA2/5.0.3等),请升级至UE5的最新版本或继续使用v77.0UE4.x可更新插件的最新版本。
特殊说明:目前暂未适配对UE5 World Partition的支持,不要用于打包该类型地图。

  • 支持UE5.1.0(UE5的先前版本不再支持)
  • 修复Patch开启PreCachePlatformData的问题
  • 修复在Ediror中Cook因GC导致的Crash
  • 修复Commandlet流程执行卡住的问题
  • 优化跨版本兼容性
  • LICENSE更新,详见README

2022.10.26 Update v77.0

更新地址:Release v77.0

  • 重构插件在UE5中的Cook机制

  • 开启PackageTracker时ForceSkip失效的情况

  • UE5中对目录扫描的问题(/All/Game)

  • 修复目录的资源依赖分析问题

  • 优化资源扫描,支持强制忽略某个资源

  • 支持自定义保存的Cooked目录

  • Cook Cluster计数

  • 优化Log输出

  • 修复跨引擎版本的兼容性问题

  • Chunk不包含文件从Error改为Warning

  • 修复部分HashCaculator未传递问题

  • 细节修复与扩展性提升

  • 2022.09.19 Update v76.3

    更新地址:Release v76.2

  • 支持UE5.0.3引擎

  • 优化分析变动材质的MaterialInstance进包(bAnalysisMaterialInstance

  • 修复一直启用GenerateGlobalAssetRegistry的问题

  • 支持从/Script/UnrealEd.ProjectPackagingSettings下读取bSkipEditorContent控制是否忽略/Engine/Editor*/Engine/VREditor/下的资源。

2022.09.01 Update v76.2

更新地址:Release v76.2

  • 修复Not-uasset文件的diff差异时未计算HASH的问题
  • 修复导出Release时未计算not-uasset文件HASH问题
  • 修复FReleasePakParser中未计算文件HASH问题
  • 修复CryptoKeys文件未执行ReplaceMark
  • 支持给not-uasset目录添加通配符,只会添加匹配的文件

  • 修复bAnalysisFilterDependencies失效的问题
  • 开启bImprtProjectSettings时,若只有一个平台,则把所有文件添加至该平台,若有多个平台,则添加至AllPlatforms
  • 针对PaperSprite的扫描优化,当PaperSprite配置AtlasGroups时忽略SourceTexture进包


  • 修复Toolbar被隐藏的问题,若想要全局屏蔽可以在ProjectDefinitions中添加DISABLE_PLUGIN_TOOLBAR_MENU

2022.07.28 Update v76.1

更新地址:Release v76.1

  1. 支持UMultiCookScheduler_MatCulster的Class过滤
  2. 避免在CookPackage里通过反射获取枚举值(ParallelFor Crash)
  3. 修复FHotPatcherActionManager的IsActiveAction问题
  4. optimize GetAssetPackageGUID
  5. 支持ImportProjectSettings/HotPatcherAssetManager
  6. chunk中支持ForceSkip
  7. 4.21禁用RTTI实现
  8. 添加CmdHandler模块
  9. 跨版本引擎兼容性问题修复
  10. 修复一些crash问题
  11. 停止支持ByOriginal的Cook模式(勾选bCookPatchAssets即可)
  12. 新Mod支持
  13. 支持第三方Mod开发
  14. 优化代码组织方式

2022.03.31 Update v76.0

  • 支持World Composition
  • 修复跨引擎版本的兼容性问题
  • 默认开启bCookPatcherAssets
  • 优化代码、修复4.27中的编译问题
  • 支持非侵入式给HotPatcher开发模块

HotPatcher/Mods下,可以基于HotPatcher二次开发新的打包和资源管理模式,充分利用HotPatcher的框架功能,能够拓展更多的功能:

  • 资源分析
  • 打包
  • 资源扫描、管理、审计
  • 多进程Cook
  • 不同形式的热更新方式

等等,根据业务的实际需求实现真正的定制化。

模块扩展示例

uplugin中添加HotPatcher的插件依赖:

1
2
3
4
5
6
"Plugins": [
{
"Name": "HotPatcher",
"Enabled": true
}
]

在build.cs中添加模块依赖:

1
2
3
4
5
PublicDependencyModuleNames.AddRange(new string[]{
"HotPatcherRuntime",
"HotPatcherCore",
"HotPatcherEditor"
});

在模块的StartupModule中即可注册到HotPatcher中:

1
2
3
4
5
6
7
8
9
10
11
THotPatcherTemplateHelper::AppendEnumeraters<EHotPatcherCookActionMode>(TArray<FString>{TEXT("ByMultiProcess")});
FHotPatcherAction MultiCookerAction
(
TEXT("Cooker"),
LOCTEXT("ByMultiProcess", "ByMultiProcess"),
LOCTEXT("MultiCookerActionHint", "Use multi-process Cook Content"),
FSlateIcon(),
nullptr,
CREATE_ACTION_WIDGET_LAMBDA(SMultiCookerPage,TEXT("ByMultiProcess"))
);
FHotPatcherActionManager::Get().RegisteHotPatcherAction(TEXT("Cooker"),TEXT("ByMultiProcess"),MultiCookerAction);

效果:

基于HotPatcher的核心功能,可以根据需求定制化界面、拓展新功能。

2022.02.15 Update v75.2

Release HotPacther v75.2

  1. 修复GIsRequestingExit警告
  2. Commandlet支持引擎Tick
  3. 支持特定资源类型的Cook/Ignore
  4. 支持GCookLog控制更多的Cook日志
  5. 支持导出Cook过程中进程加载的所有资源
  6. 修复开启CUSTOM_ASSET_GUID时的编译错误
  7. 修复派生类列表问题
  8. 支持CookClassesMode
  9. 修复Filter的路径匹配问题导致的资源进入不同的Pak
  10. 修复Trace file的路径问题
  11. 兼容UE4.21

2022.01.09 Update v75.1

Release HotPatcher v75.1!

  • Fix memory leak when serializing asset registry
  • Fix Info.IndexHash.Hash Compiler error in 4.23

2022.01.26 Update v75.0

本次更新包含大量的内容,修正了一些问题和重构部分功能,提升了跨引擎版本的兼容性。

  • 重构了Cook流程,并支持了几种不同的Cook模式,加速Cook过程
  • 统一编辑器Cook、Patch流程、MultiCooker使用的Cook流程
  • 移除CookManager支持
  • 支持Chunk内资源编译的shader打包,之前是整个Patch打包单个ShaderLib,并且支持给每个Chunk自定义ShaderLib路径、命名
  • 支持排除资源类型
  • 修复IsSkipAsset在ParallelFor Cooking过程中的Crash问题
  • Cook前清理旧Cooked文件
  • 添加了大量的Profiling Tag进行性能分析
  • 在修改引擎模式下,可以控制每个Cooker进程拉起的ShaderCompileWorker数量,避免操作系统进行频繁进程切换开销
  • 支持Patch版本号
  • 创建HotPatcherCore模块,与HotPatcherEditor模块分离,Editor只有编辑器部分逻辑
  • 修复序列化AssetRegistry的Crash问题
  • 修复Sandbox路径转换问题
  • 修复UE4Editor-cmd在非Development及32位模式下的问题
  • 清理冗余代码、接口、优化流程
  • 提升引擎兼容性,最低兼容至4.22(无ContentBrowser菜单相关功能)

2022.01.03 Update v74

  • 重构依赖分析模块,性能提升一个数量级(测试2w资源量提升约70倍)
  • 重构了从Paklist/Pak文件导入Release信息的模块
  • 优化实现,清理了大量冗余接口,整理代码组织方式
  • 移除AssetManagerEx模块,将UFLibAssetManagerHelper函数库移入HotPatcherRuntime
  • 修复4.25及之后的引擎版本中,由于引擎接口变动导致的RecursiveWidgetTree失效
  • 修复当开启基础版本比对时,bRecursiveWidgetTree分析不到部分父级UMG的情况
  • Patch支持PackageTracker,用来追踪不在依赖关系中但在ImportTable中的的资源,如动画序列的BoneCompressionSettings设置,详见Cook时的依赖加载注意:在编辑器中只有资源第一次加载或以Standalone模式执行时生效)。

bRecursiveWidgetTree的规则为:

  1. 若没有指定基础版本,则默认递归分析Patch中UMG资源的所有引用它的父级UMG控件
  2. 若指定基础版本,只会分析基础包中存在的父级UMG控件,避免带入非必要资源

资源依赖分析优化数据:

同时对Release的导出也有巨大提升,2w资源量:

  • 旧版本导出release总耗时568.635s
  • 新版本总耗时57.28s

2021.12.27 Update v73

  • 支持CUSTOM ASSET HASH计算
  • 替换部分即将在UE4.27/UE5中废弃的API
  • Release添加bBackupProjectConfig,支持备份基础包的Config目录
  • 导出Release时支持NoCompileShader,避免因为加载资源导致的Shader编译,加速导出。
  • 优化代码,替换部分FString to FName、资源依赖扫描优化
  • 修复PackageTracker潜在的crash问题
  • 右键CookAndPakAction支持选择是否分析资源依赖

注意:在目前的版本中,获取uasset的HASH值是通过获取引擎内的PackageGUID,但是该属性即将在UE4.27和UE5中废弃,所以我添加了自定义的资源HASH计算支持,会计算原始的uasset文件的MD5值,用来替代即将废弃的PackageGUID(目前插件中并未开启,等UE正式废弃时会替换),对插件功能并无影响,但使用PackageGUID和通过计算MD5的Release*.json,不能通用,不然会造成全部的资源都具有差异。

想要现在就开启的话,可以在HotPatcherRuntime.build.cs中将bCustomAssetGUID=true即可。

2021.12.14 Update v72

Github上的Release记录:v72

  • 修复Mac的SVersionUpdater的Crash问题
  • 修复Mac Cook时开启share shader code异常
  • 修复在Mac上的编译错误
  • 优化Shader收集流程,保证在Cook完毕之后才关闭Shader收集
  • 废弃bIncludeAssetRegistry/bIncludeGlobalShaderCache/bIncludeShaderBytecode三个选项,有更好的替代实现,详见UE热更新:Shader 更新策略

最近在做一个大更新,后续可以使用HotPatcher替换UE的Cook和分包机制,实现多进程甚至多机器的Cook任务分配,在基础包流程就可以使用HotPatcher进行管理,并加速UE的打包过程。

Mac上Cook IOS,左边是UE默认CookCommandlet,右边是HotPatcher的Cook,都开启了ShareShaderCode:

2021.11.21 Update v71

  • 支持ue5-main分支的ZenLoader序列化机制
  • 从4.24起在Cook时开始默认开启WITH_PACKAGE_CONTEXT
  • PackageContexts相关代码移入HotPactherEditor模块
  • 右键菜单的Cook and Pak Action支持PackageContext
  • 修复UE5中右键菜单执行失效的问题
  • 插件配置提供完整的PatchSettings模板
  • 支持Binaries Patch使用项目设置中的key进行解包
  • 优化代码

目前ue5-main和UE5 EA版本已经有较大差异,引擎内部的相关实现细节尤其是序列化相关产生了很多变化,目前用了一些trick方法实现4/5的兼容,等UE5正式版出来之后,如果要同时兼容4/5有非常大差异会考虑单独给UE5一个开发分支。

2021.11.19 Update v70

  • 支持打包GameFeature/插件,在UE4.27/UE5中默认开启,详见文章:UE5:Game Feature预研
  • 重构Pak加密模块,支持从项目设置导入加密配置,并且与基础包加密方式对齐
  • 支持从Project Settings-Crypto的配置生成Crypto.json
  • 修复值类型的未初始化警告
  • 优化代码

注意:UnrealPak通过-encryptionini指定使用项目Ini配置的代码有Bug,会导致Crash,我的实现中完全抛弃了Ini,统一使用Crypto.jon

打包插件包含的文件:

  • 插件中的所有资源
  • 插件的uplugin
  • 插件中资源生成的AssetRegistry
  • 插件资源Cook时生成Shader Library
  • 插件Config/目录

并封装了运行时库:

1
2
3
IPluginManager::Get().AddToPluginsList(TEXT("../../../BlankExample/Plugins/GameFeatures/GF_Feature/GF_Feature.uplugin"));
UFlibPakHelper::LoadAssetRegistry(TEXT("GF_Feature"),TEXT("../../../BlankExample/Plugins/GameFeatures/GF_Feature/"));
bool UFlibPakHelper::LoadShaderbytecode(TEXT("GF_Feature"),TEXT("../../../BlankExample/Plugins/GameFeatures/GF_Feature/"));

2021.11.15 Update v69

  • 支持给Patch中的资源生成AssetRegistry(会从项目配置中读取配置:控制 AssetRegistry 的序列化
  • 修复在UE5上的编译错误
  • 修复Slate、un-initialization vars警告
  • Cook资源由Patch All变为Cook Chunk
  • 修复UE4.26+默认开启shader deterministic但未指定GameOpenOrder产生的错误
  • 支持版本号检测提示更新

Patch中的AssetRegistry支持两种模式:PATCH/PER_CHUNK,区别在于:

  • PATCH:本Patch中只会生成一个AssetRegistry.bin,打包至0号Chunk中,其他的Chunk中不存在;
  • PER_CHUNK:如果Patch中有拆分Chunk,可以根据每个CHUNK中的资源创建出CHUNK_NAME_AssetRegistry.bin并只打包至Chunk的Pak中;

能够自定义AssetRegistry.bin的Mount Point,并且可以自定义AssetRegistry的命名规则,默认是[CHUNK_NAME]_AssetRegistry.bin

插件版本号检测:

2021.10.29 Update

  • 支持Patch中的Shared Shader bytecode

在Cook中收集Patch中所有的Shader并单独生成ShaderBytecode,实现Shader的增量更新。详情见文章:UE热更新:Shader更新策略#更好的方式

2021.08.06 Update

  • 支持BinariesPatch模式匹配
  • 能够匹配/忽略文件大小、后缀
  • 修复从Pak中解压文件问题
  • 优化代码

2021.08.05 Update

  • 打包时自动为各个平台添加-AlignForMemoryMapping参数,解决IOS的Crash问题。

2021.07.30 Update

  • 支持从Pak文件中导入基础包文件列表,与打包Pak的ResponseFile可以互为替代。

2021.07.21 Update

  • 基于二进制patch已经初步实现第一版
  • 给HotPatcher预留了BinariesPatch方案的实现接口(diff/patch的实现是另外一个插件,需要修改引擎,暂不开源,有兴趣的可以更新dev分支代码(已合并至主干),只需要继承IBinariesPatchFeature的接口实现一个二进制Diff/Patch的Feature,即可用插件来打包资源二进制的补丁)

2021.07.16 Update

  • 支持对PrimaryAssetLabel管理的资源进行CookAndPak

2021.07.14 Update

  • 支持从Primary AssetLabel导入Patch或Chunk的配置

2021.07.08 Update

  • 修复crash问题

2021.07.02 Update

  • 忽略对EditorOnly资源的检查
  • 增加Cook EditorOnly的失败提示及Log

2021.06.28 Update

Prject Settings-Plugins-HotPatcher可查看插件的编辑器配置参数。

  • CookAndPak与配置页面打包的流程统一
  • CookAndPak支持同时选择目录和单个资源
  • CookAndPak支持StandaloneMode运行
  • 可选保存CookAndPak的PatchConfig配置
  • 优化Patch流程,保证所有的资源Cook完毕之后才进行打包
  • 优化插件配置项
  • 对无效资源的检测添加保护,不会导致crash
  • 提供Preset功能,可以把在HotPatcher中配置的参数添加至预设配置(AddToPreset)
  • ContentBrowser右键菜单支持Preset任务执行

AddToPreset
配置预设
CookAndPak

2021.06.24 Update

  • 修复CookAndPak的错误,在打包时保证已经Cook完成。
  • 支持PakExternalAction选项

支持在编辑器右键菜单中打包外部文件,

需要在Project Settings-Plugins-Hot Patcher中预先配置:

2021.06.15 Update

  • 优化代码,去除不需要的流程
  • 支持右键菜单CookAndPak开启加密

Project Settings-Plugins-Hot Patcher中进行设置:

注意:在目前(2021.06.15)UE5 EA引擎中存在Bug,不能开启这个功能,不然会Crash。

2021.06.09 Update

  • 支持UE4.27

2021.06.06 Update

  • 修复导出Patch的release.josn中不包含Add/Modify的文件信息

2021.06.04 Update

  • 支持bCreateDefaultChunk,当拆分chunk时,如果有些文件在手动配置的Chunk中不存在,则默认创建一个Chunk用于存储它们。

2021.06.03 Update

  • UE4.26-UE5支持Io Store的Patch生成
  • 修复Paklist分析器的bug
  • 优化部分代码

注意:支持Io Store生成Patch仅支持UE4.26-UE5,目前UE对Io Store的支持仍有bug,在打Patch时有几点需要注意:

  • 只能使用HotCooker集成的Cook,不能开启Patch内的bCookPatchAssets
  • 必须要指定基础包的global.utoc
  • UE5默认开启bAsyncLoadingThreadEnabled,在加载Shader时会存在问题,导致材质丢失,关闭即可恢复(应该是IoStore早期版本的bug)
  • 指定基础包内的其他utocGenerateDiffPatch/PatchSource)(可选)
  • 当patch包含多个chunk时必须开启多个进程来执行Io Store的生成,单个进程生成多个会Crash(UE的Bug)

如果开启了bCookPatchAssets则加载Patch会有以下错误:

在开启IoStore后引擎内Cook和插件提供的Cook的机制有所不同,有时间再详细分析看,看是否可以支持bCookPatchAssets

2021.05.27 Update

  • 修复Patch时生成的Release.json中BaseVersion/VersionId/Date信息缺失问题
  • 支持EA版UE5

不过需要注意的是UE5默认开启了IO Store,目前插件并不支持IO Store的打包,所以可以暂时关闭UE5的 IO Store,不然pak无法挂载,准备有时间给插件做支持。看来UE5的的资源IO压力确实很大,从Oodle到IO Store的引入,应该都是在为支持UE5的资源量暴涨做铺垫。

2021.05.20 Update

  • 支持直接Cook和打包在当前编辑器中创建的资源,对于新创建资源的打包无需重启编辑器了。
  • 梳理Patch/Release,拆分流程步骤,下一步实现多线程版本。

2021.05.18 Update

  • 整理Release/Patch/ShaderPatch的通用代码
  • 优化配置逻辑,生成时不会变动配置中的[PROJECTDIR]等标记符,在执行任务时替换
  • 统一模式间的通用选项
  • Advanced下增加bScanCacheOptimize,可以开启资源依赖扫描缓存优化
  • 增加Relase/Patch输出任务摘要

Release的摘要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2021-05-19 07:38:31:642 : ---------------------HotPatcher Release Summary---------------------
2021-05-19 07:38:31:642 : New Release Asset Number: 7591
2021-05-19 07:38:31:642 : ======== IOS Non-Assets =========
2021-05-19 07:38:31:643 : External Files: 82
2021-05-19 07:38:31:643 : =================================
2021-05-19 07:38:31:643 : ======== WindowsNoEditor Non-Assets =========
2021-05-19 07:38:31:643 : External Files: 81
2021-05-19 07:38:31:643 : =============================================
2021-05-19 07:38:31:643 : ======== Android_ASTC Non-Assets =========
2021-05-19 07:38:31:643 : External Files: 85
2021-05-19 07:38:31:643 : ==========================================
2021-05-19 07:38:31:643 : ======== AllPlatforms Non-Assets =========
2021-05-19 07:38:31:643 : External Files: 1673
2021-05-19 07:38:31:643 : ==========================================

Patch的摘要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
LogMissionNotificationProxy: -----------------HotPatcher Patch Summary-----------------
LogMissionNotificationProxy: =================
LogMissionNotificationProxy: Add Asset Number: 6719
LogMissionNotificationProxy: Modify Asset Number: 49
LogMissionNotificationProxy: Delete Asset Number: 0
LogMissionNotificationProxy: ======== AllPlatforms Non-Assets =========
LogMissionNotificationProxy: Add Non-Asset Number: 975
LogMissionNotificationProxy: Modify Non-Asset Number: 0
LogMissionNotificationProxy: Delete Non-Asset Number: 0
LogMissionNotificationProxy: ==========================================
LogMissionNotificationProxy: ----------------HotPatcher Release Summary----------------
LogMissionNotificationProxy: New Release Asset Number: 6719
LogMissionNotificationProxy: ======== AllPlatforms Non-Assets =========
LogMissionNotificationProxy: External Files: 975
LogMissionNotificationProxy: ==========================================

注意:本次修改有些配置属性的名字产生了变化,SavePathbStorageConfig,对于已经导出的配置需要修改下这两个配置名字。

2021.05.17 Update

  • 修复4.26的警告/4.22的编译错误
  • 添加GScanCacheOptimize的选项(默认开启)
  • 添加Patch/Release/ShaderPatch按钮的ToolTips,显示哪些必要选项没有配置。

Patch

Release

Shader Patch

2021.05.13 Update

  • 修复crash问题
  • SavePath/BaseVersion等路径支持标记符替换

可选标记为:

1
2
3
4
5
6
[ENGINEDIR]
[ENGINE_CONTENT_DIR]
[PROJECTDIR]
[PROJECT_CONTENT_DIR]
[PROJECT_SAVED_DIR]
[PROJECT_CONFIG_DIR]

在执行时会替换为真正的本地目录,配置中所有的路径都可以通过标记符来指定相对路径了,能够导出完全通用的配置文件。

  • 优化依赖扫描的效率

同一项目的相同patch配置:

  1. 用之前的插件版本,分析依赖用了1m46s,优化后33s
  2. 完整的patch时间从4:24s->2:40s(包含cook资源)

插件中还有几处可以优化执行效率的地方,有时间再做。

2021.04.28 Update

BaseEngine.ini中指定的[Pak]ExtensionsToNotUsePluginCompression类型忽略-compress参数。

BaseEngine.ini
1
2
3
4
5
6
7
[Pak]
+ExtensionsToNotUsePluginCompression=uplugin
+ExtensionsToNotUsePluginCompression=upluginmanifest
+ExtensionsToNotUsePluginCompression=uproject
+ExtensionsToNotUsePluginCompression=ini
+ExtensionsToNotUsePluginCompression=icu
+ExtensionsToNotUsePluginCompression=res

目的是,如果打包了这些类型的文件使用自动挂载,可能对应的压缩算法模块还没有启动,导致这些类型的文件加载失败,UE在打基础包时做了检测,插件中也做了相应支持。

2021.04.18 Update

  • 支持编辑器右键Cook平台的白名单配置
  • 支持直接在编辑器中选中资源右键打包Pak

Project Settings-Plugins-HotPatcher具有配置选项:

当开启白名单时,编辑器中右键的平台只会有设置的选项:

右键菜单中新增了Cook And Pak Actions选项,可以右键选中多个资源,直接对选中资源进行Cook并打包成Pak,存储目录默认在Saved/HotPatcher/Paks中,可以通过配置修改。

2021.03.25 Update

  • add bDeterministicShaderCodeOrder for 4.26+

bDeterministicShaderCodeOrder是位于UProjectPackagingSettings中声明,在4.26中加入,用来控制打包时Shader的存储顺序。

Editor/UnrealEd/Classes/Settings/ProjectPackagingSettings.h
1
2
3
4
5
6
7
8
/** 
* With this option off, the shader code will be stored in the library essentially in a random order,
* squarely the same in which the assets were loaded by the cooker. Enabling this will sort the shaders
* by their hash, which makes the shader library more similar between the builds which can help patching, but
* can adversely affect loading times.
*/
UPROPERTY(config, EditAnywhere, Category = Packaging, meta = (EditCondition = "bShareMaterialShaderCode"))
bool bDeterministicShaderCodeOrder;

2021.03.23 Update

  • 修复在4.22上的编译错误
  • 增加HotRelease根据设置的paklist信息自动备份Metadata文件

2021.03.15 Update

  • 增加Release/Patch备份Metadata目录的选项

Release Settings

Patch Settings

会把当前工程版本的Metadata目录拷贝至Release/Patch目录下(BackupMetadatas),可以方便管理DevelopmentAssetRegistry.bin和Shaderbytecode,可以用作版本的资产审计以及Shader Patch中。

2021.02.23 Update

  • ShaderPatch的文件生成提示
  • ShaderPatch的Commandlet(-run=HotShaderPatch
  • 修复Shader Patch的Reset Config错误
  • 代码优化

4.25+生成ShaderPatch会Crash的解决方案:UE4.25中ShaderPatch问题

2021.02.01 Update

2021.01.28 Update

  • 修复DebugGame Editor运行时无法拉起新进程
  • 增加bStandaloneMode选项,可以控制是否拉起新进程执行任务(true会拉起新进程)

2021.01.22 Update

  • HotPatcher的Patch Commandlet可以指定平台

通过-AddPatchPlatforms=WindowsNoEditor,Android_ASTC,IOS方式添加,多个平台使用,分隔。

2021.01.20 Update

  • 基础包分Chunk的情况下,支持Release为某个平台添加多个paklist文件

2021.01.19 Update

  • 支持通用的外部文件指定模式,可以解决在不同的项目路径之间使用通用的配置

在指定外部文件/文件夹时可以使用[PROJECTDIR]在执行时会替换为真正的项目目录。

可选的路径为:

1
2
3
4
5
6
[ENGINEDIR]
[ENGINE_CONTENT_DIR]
[PROJECTDIR]
[PROJECT_CONTENT_DIR]
[PROJECT_SAVED_DIR]
[PROJECT_CONFIG_DIR]

注意,在执行生产过程中会把真实的路径替换到当前的配置中(Patch和Release自动生成导出的配置文件都是绝对路径的,但是可以自己在编辑器内手动导出基于相对路径的配置文件)。

2021.01.18 Update

  • Release/Patch的生成不阻塞Editor
  • 可以直接在Editor中看到Log
  • 统一UE的Notification的创建方式

本次更新是把之前阻塞Editor的方式改成了拉起一个Commandlet的进程任务来执行,不会对当前的编辑器进程造成影响,与UE打包时相同,避免卡住Editor的焦虑感。

2021.01.14 Update

  • 修复Cook Engine目录下插件资源时的路径错误
  • byRelease支持命令行导入PlatformPakList

添加方式为使用-AddPlatformPakList=,后面跟上平台名+PakList文件(可以支持多个文件,使用+分隔),多个平台可以使用逗号分隔。

1
-run=HotRelease -byPaklist=true -AddPlatformPakList=WindowsNoEditor+D:\PakList_FGame-WindowsNoEditor.txt -savepath.path="D:\\"
  • 三个Commandlet均支持替换Config中的参数

  • HotRelease的Commandlet可以不指定config文件,直接指定值(需要指定导入paklist文件)

2021.01.13 Update

  • 修复Patch中包含插件资源的Cook失败
  • 修复Commandlet生成Patch加载不到资源
  • 一些其他优化

2021.01.11 Update

  • 支持从项目中导入配置到Patch和Release的Setting中

Project Settings-Packaging-Additional Asset Directories to Cook会被添加到AssetIncludeFilters中。
Project Settings-Packaging-Directories to never cook会被添加到AssetIgnoreFilters中。
Project Settings-Packaging-Additional Non-Asset Directories To Package会被添加到AddExternAssetsToPlatfotm中(AllPlatform)。

项目中Config/DefaultEditor.ini里的AlwaysCookMapsAllMapsSection下配置的所有地图会被添加至IncludeSpecifyAssets中,并且会勾上bAnalysisAssetDependencies

2021.01.08 Update

  • 支持在ContentBrowser中添加目录到PatchSettings
  • 修复勾选CookAsset后通过Commnadlet生成Patch导致的StaticFindObject的crash错误
1
LogWindows:Error:lllegal call to StaticFindObject() while serializing object data!

2020.12.14 Update

  • 添加UFlibPakReader函数库,可以实现在不Mount的情况下读取Pak中的文件

2020.12.11 Update

  • 支持Shaderbytecode的Patch,通过byShaderPatch页面配置执行;

Shaderbytecode Patch的要求:

  • 备份每次打包的Cooked/PLATFORM/PROJECT_NAME/Metadata目录;
  • 最新版本的Cooked/PLATFORM/PROJECT_NAME/Metadata与旧版本的Metadata进行比对;
  • 生成的ushaderbytecode文件可以通过HotPatcher添加外部文件形式打包,运行时加载;

注意:目前该功能在4.24及之前引擎版本正常,但是在4.25+中会触发异常,具体原因分析在这里:UE4.25 中 ShaderPatch 问题。解决这个问题需要改动引擎代码,可以根据上面笔记中的原因分析来修改。

2020.12.10 Update

  • 修复HotRelease的Commandlet导出失败问题

2020.12.04 Update

  • HotPatcher支持UE4.26!
  • 修复在编辑器中Cook资源后,对其修改保存导致资源在下次加载时失败的问题

2020.11.26 Update

  • 修复在Content Browser中Cook资源时的路径错误
  • 修复在新版本代码中无法预览的问题

2020.11.08 Update

  • 支持对Cook单个资源时进行检测(对于新创建的资源,拿到的UPackage是不完全的, 使用它对资源进行Cook会Crash)
  • ContentBrowser右键Cook资源时支持Cook失败的提示。

注意:如果在工程中新建了资源,直接对这些资源进行Cook是有问题的,因为通过引擎拿到的新创建资源的Package内的数据是不完全的,会导致执行Cook时的Crash,目前插件中的策略是检测要进行Cook的UPackage数据是否正确,如果不正确会忽略掉该资源。

暂时的解决办法时,创建了资源之后重启编辑器,再对这些资源进行Cook或者创建Patch的操作,或者依然通过插件提供的Cook目录和指定地图的功能,不存在上面所说的这个问题,因为它的实现是拉起一个新的UE进程来执行Cook任务,所以本地的资源信息会重新加载)。

2020.11.07 Update

  • 添加bStorageDeletedAssetsToNewReleaseJson:控制ContentBrowser中删除的资源是否存储到新ReleaseJson中去。

其实就是两种版本管理模式:

  1. ReleaseJson中记录的是当前游戏版本中所有的资源(删除的资源,在UFS中依然存在,因为老Pak中的文件不会被删除)
  2. ReleaseJson中记录的是游戏中需要让玩家能够体验到的所有资源(不包含移动目录、删除之后的资源)

真正在游戏中的资源没有区别,区别在于HotPatcher管理的版本信息。

2020.11.01 Update

  • (UE4.23+)支持直接在ContentBrowser中把所选资源添加至Patch Settings;
  • 支持在生成Patch时直接Cook资源(bCookPatchAssets)。需要注意的是,当Patch中资源很多的情况下,Cook十分耗时,并且需要编译Shader,会大大增加Patch 的生成时间,所以在生成Patch时开启Cook可以用在测试打包一些资源或者在ci中执行时开启,在编辑器中SlowTask进度会卡住编辑器;

2020.10.31 Update

  • 支持Cook单个资源(shader code包含在资源内);
  • (UE4.23+)支持在Content Browser中右键选中Assets(支持多选)进行Cook;

2020.10.30 Update

  • PatchSetting支持bForceSkipContent用于强制忽略某些目录中的资源
  • ForceSkipContentRules为指定Patch中忽略的资源目录,默认值为/Engine/Editor/Engine/VREditor,在项目设置中选择Exclude editor content when cooking这两个目录里的资源是不Cook的,所以也无法将他们打包。
  • ForceSkipAssets在Patch版本中忽略指定的资源。
  • 更名DiffPatchVersion等函数为DiffPatchVersionWithPatchSetting,并且传递PatchSetting,方便进行Diff时的选项控制。

增加上述两个选项,一是为了与UE默认打包时不Cook的目录相匹配,二是可以自己控制哪些资源不被打包。
注意:ForceSkipContentRulesAssetIgnoreFilters的区别在于:AssetIgnoreFilters忽略的过滤器是进行资源依赖分析之前的步骤,可以用来设置为AssetIncludeFilters中的子目录;而ForceSkipContentRules是把经过diff之后的结果进行一遍过滤操作,排除这些前缀的资源。

2020.10.27 Update

  • 支持从打包生成的PakList文件中分析出Release
  • 支持导入多个平台的PakList并分析出不同平台的文件差异
  • ReleaseSetting和PatchSetting类从UObject改为USTRUCT
  • 统一使用序列化USTRUCT的方式来处理Import/Export配置
  • 支持在Patch中给特定平台添加特殊的文件(只在指定平台包含)
  • 使用CustomDetailView的方式给Detail面板添加导入PakList的按钮
  • 重构部分代码,适配给不同平台添加特殊文件。
  • Release.json中剔除额外的配置信息
  • 修复MountListener在4.24的错误

本次更新代码变动非常大,并且与之前版本导出的配置文件在当前版本中不通用,所以暂时发布到Dev分支,测试稳定之后合并到master分支,目前经过Relase/Patch/Chunk的流程测试,基本没有问题。

2020.10.17 Update

  • 支持对Widget的WidgetTree进行分析,解决子控件修改父控件不生效的问题

如果一个Widget被修改了,能够通过控制这个选项来是否递归地添加所有包含它的Widget资源,可以解决修改了子控件,打patch父控件不生效的问题了。

2020.08.31 Update

  • 增加导出Release的Commandlet支持
  • 清理重复的代码,整理组织方式
  • 增加控制生成Pak的命名规则
  • 修复Chunk不包含任何文件时也会打出空包的问题
  • 修复UFlibPakHelper::GetMountedPaks在4.25中Crash的问题

2020.06.04 Update

  • 增加Cook导出配置的bCookAllMap属性,当为true时,在Commandlet模式下会Cook工程目录下中所有的地图。
  • 增加ByRelease支持通过PakList*.txt来生成配置,从而可以完全匹配基础包中的所有资源。

2020.06.03 Update

  • 增加插件Cook的Commandlet
  • 增加插件Patch的Commandlet

2020.04.27 Update

  • 增加Chunk的bMonolithic模式下的MonolithicPathMode,用于指定单片模式下的pak存储路径规则。

2020.04.24 Update

  • 增加是否对过滤器中的资源进行依赖分析的选项

2020.04.23 Update

  • 增加可选引用资源的类型

2020.04.18 Update

  • UnrealOptions默认添加-compressionformats参数。
  • 增加PreviewChunk的选项,在开启Chunk的情况下可以方便地知道哪个chunk中有哪些资源。

2020.04.10 Update

  • 增加ReplacePakCommandTexts选项,可以自己根据需求替换PakCommand.txt中的文本,如替换打到pak中的资源的MountPath

2020.04.09 Update

  • 修复在没有选择过滤器时从PatchSetting生成Chunk的问题/对资源重定向器的溯源操作
  • 修复转换Cooked路径时的问题
  • 支持导出所有pak的信息、删除pakversion选项
  • 支持Release和Patch导出资源的依赖关系
  • 给ExportRelease增加FScopeSlowTask进度显示
  • 增加可以指定PakCommand参数的选项

2020.04.08 Update

  • 支持多线程打包Pak,直接调用 ExecuteUnrealPak而不是启动UnrealPak.exe,极大提升效率。
  • 修复PreviewPatch在选中BaseVersion的情况下与Diff信息不一致的问题

2020.04.07 Update

  • 支持bMonolithic模式,可以把所有引用每个资源单独打到一个pak中。
  • 统一了Asset、Cooked的bin、外部文件、ini等所有文件的pak方式。

2020.04.03 Update

  • 完成Patch的Chunk功能,统一Patch和Chunk的打包流程
  • 代码优化、流程梳理
  • 去除IncludePakVersionFilePakVersionFileMountPoint选项

2020.04.02 Update

  • 增加Patch的Chunk功能
  • 修复FPatcherSpecifyAsset序列化与反序列化的问题
  • 优化组织结构

2020.03.28 Update

  • 修复当基于基础版本打patch时导出的*Release.json不全的问题。

2020.03.05 Update

  • 修复当Cook的进程异常退出时没有清掉任务状态的问题。
  • 在代码中增加Cook时可选Engine或Plugin中的地图,在HotPatcherEditor.build.cs中通过控制ENABLE_COOK_ENGINE_MAPENABLE_COOK_PLUGIN_MAP的值来自行开启。

2020.02.14 Update

  • 增加了Patch和Release配置的导入导出
  • 生成Pak的默认命名改成XXX_TARGET_PLATFORM_001_P.pak
  • 修复了一些潜在问题,建议更新。

2019.12.08 Update

  • 新增是否对资源进行依赖扫描的选项,增加diff预览。

2020.02.19 Update

  • 为插件增加了导出release时可以选择添加外部文件和文件夹,对应ue打包时添加的非资源外部文件目录。还支持外部文件的diff(可选),对于指定的外部文件和目录,会检测只有修改或者新增的文件才会打包到pak中。

2020.01.13 Update

  • 新增生成时的错误信息提示,对未Cook资源的扫描以及重复添加的外部文件进行检测,增加可以指定特定资源到Pak中,并且可选是否对该资源进行依赖分析。

2020.01.14 Update

  • 修复会扫描到Redirector会提示Redirector的资源未Cooked,为ExportRelease增加IncludeSpecifyAssets,可以指定某个资源了(如只指定某个地图)。

2020.01.19 Update

  • 增加指定要Cook的目录

更新计划

为了使HotPatcher更易用和更强大,我会在这里记录一些不错的更新建议。

  1. 增加支持多线程扫描资源依赖分析(通过拉起单独的进程执行)
  2. 在UnrealPak下增加直接指定Pak加密参数的选项(开放了可以指定UnrealPak的参数,自己指定加密的参数即可)
  3. 指定Cook单个资源
  4. 把打包出的Pak命名从XX_TARGET_PLATFORM_P.pak改成XX_TARGET_PLATFORM_0_P或者中间的数字可以指定。
  5. Patch和Release配置文件的导入和导出、以及快速地清理配置。
  6. 为release增加包含外部文件的选项,与UE的打包时包含外部文件同步。
  7. 增加对外部文件的Diff,不用每次打包时把所有的外部文件都打包到pak中。
  8. 在一个Patch中打包出多个pak文件,可选哪些资源打到哪个Pak中。
  9. ChunkbMonolithic模式增加多线程支持
  10. 增加Commandlet的支持
  11. 增加导出Release的Commandlet支持
  12. 增加可控制生成Pak的命名规则
  13. 支持打Patch时给特殊的平台添加NoAssets资源
  14. 追踪UMG的子控件被修改后引用到它的Widget资源
  15. 支持给多个从多个平台的paklist中分析基础包的Release.json
  16. 对Patch的最终结果进行过滤
  17. 设置忽略Editor的资源内容
  18. 添加的外部文件以相对路径存储于Release.json中(使用Mountpath来进行版本比对)
  19. 支持打出shaderbytecode的patch
  20. Patch时不阻塞编辑器,使用异步任务实现
本文会持续更新HotPatcher的文档。

微信扫描二维码,关注我的公众号。

本文标题:UE资源热更打包工具HotPatcher
文章作者:查利鹏
发布时间:2020年01月15日 09时41分
更新时间:2020年08月31日 17时27分
本文字数:本文一共有31k字
原始链接:https://imzlp.com/posts/17590/
许可协议: CC BY-NC-SA 4.0
文章禁止全文转载,摘要转发请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!