在之前的文章中,主要在介绍HotPatcher如何应用在热更新流程里。但是HotPatcher并不只是能实现热更的需求,更是一个灵活的资源打包框架。
当项目开发进行到一定阶段,海量的资源需要进包,等待一次完整出包的时间会很久。如果真机出现问题,修复->打包->验证,这个串行流程就会变动极为冗长。经常会遇到脚本、数据或者某些的资源错误,导致包的异常。
这种情况下,再完整出一个包就等待数个小时的时间,导致测试无法进行冒烟跑测。就算重新出包也难保一定没有其他遗漏的问题,否则又要重来一遍。
基于这种痛点,我们迫切地需要一种在开发阶段能够快速地修复包内资源问题,进行快速验证的方法。而HotPatcher提供了这样的功能,如果能充分利用起来,就不必等待完整出包。
本篇文章会介绍,如何利用HotPatcher提供的编辑器功能,来快速打包预设配置和特定资源。加速资源在真机上的验证流程,大幅提升测试效率。
Preset Actions
HotPatcher提供了一种叫做Preset Actions
的功能,可以把自定义的Patch配置添加到项目设置中。在编辑器里可以快速唤起,执行打包过程。
配置方法:
- 打开HotPatcher的主界面
- 编辑Patch的配置,不指定基础版本
- AddToPreset
以打包lua为例,需要把位于项目中的某个目录,以外部文件的形式打包出pak。则可以这么配置:
它的配置文件为:
1 | {"bByBaseVersion":false,"baseVersion":{"filePath":""},"versionId":"LUA","bImportProjectSettings":false,"bBinariesPatch":false,"binariesPatchConfig":{"binariesPatchType":"None","encryptSettings":{"bUseDefaultCryptoIni":false,"cryptoKeys":{"filePath":""}},"baseVersionPaks":[],"matchRules":[]},"bIncludeEngineIni":false,"bIncludePluginIni":false,"bIncludeProjectIni":false,"bEnableExternFilesDiff":true,"ignoreDeletionModulesAsset":[],"addExternAssetsToPlatform":[{"targetPlatform":"AllPlatforms","addExternFileToPak":[],"addExternDirectoryToPak":[{"directoryPath":{"path":"[PROJECTDIR]/Source/Script"},"mountPoint":"../../../FGame/Source/Script","bWildcard":false,"wildcardStr":""}]}],"bIncludePakVersionFile":false,"pakVersionFileMountPoint":"../../../FGame/Versions/version.json","bEnableChunk":false,"bCreateDefaultChunk":false,"chunkInfos":[],"bCookPatchAssets":true,"cookAdvancedOptions":{"bCookParallelSerialize":false,"numberOfAssetsPerFrame":100,"overrideNumberOfAssetsPerFrame":{"Class'/Script/Engine.World'":2},"bAccompanyCookForShader":false},"cookShaderOptions":{"bSharedShaderLibrary":false,"bNativeShader":true,"shaderNameRule":"CHUNK_NAME","customShaderName":"","shaderLibMountPointRegular":"[PROJECTDIR]/ShaderLibs"},"serializeAssetRegistryOptions":{"bSerializeAssetRegistry":false,"bSerializeAssetRegistryManifest":false,"assetRegistryMountPointRegular":"[PROJECTDIR]/AssetRegistry","assetRegistryRule":"PATCH","bCustomAssetRegistryName":false,"assetRegistryNameRegular":"[CHUNK_NAME]_AssetRegistry.bin"},"ioStoreSettings":{"bIoStore":false,"bAllowBulkDataInIoStore":false,"ioStorePakListOptions":[],"ioStoreCommandletOptions":[],"platformContainers":{},"bStoragePakList":true,"bStorageBulkDataInfo":true},"unrealPakSettings":{"unrealPakListOptions":[],"unrealCommandletOptions":[],"bStoragePakList":true},"defaultPakListOptions":["-compress"],"defaultCommandletOptions":["-compress","-compressionformats=Zlib"],"encryptSettings":{"bUseDefaultCryptoIni":false,"cryptoKeys":{"filePath":""}},"replacePakListTexts":[],"pakTargetPlatforms":[],"bCustomPakNameRegular":false,"pakNameRegular":"{VERSION}_{CHUNKNAME}_{PLATFORM}_001_P","bCustomPakPathRegular":false,"pakPathRegular":"{CHUNKNAME}/{PLATFORM}","bStorageNewRelease":true,"bStoragePakFileInfo":true,"bIgnoreDeletedAssetsInfo":false,"bStorageDeletedAssetsToNewReleaseJson":true,"bStorageDiffAnalysisResults":true,"bStorageUnrealPakList":true,"bEnableProfiling":false,"storageCookedDir":"[PROJECTDIR]/Saved/Cooked","assetScanConfig":{"bPackageTracker":true,"assetIncludeFilters":[],"assetIgnoreFilters":[],"bIncludeHasRefAssetsOnly":false,"bAnalysisFilterDependencies":true,"assetRegistryDependencyTypes":["Packages"],"includeSpecifyAssets":[],"bRecursiveWidgetTree":true,"bAnalysisMaterialInstance":true,"bSupportWorldComposition":false,"bForceSkipContent":true,"forceSkipContentRules":[{"path":"/Game/__ExternalActors__"},{"path":"/Game/__ExternalObjects__"},{"path":"/Engine/Editor*/"},{"path":"/Engine/VREditor/"}],"forceSkipAssets":[],"forceSkipClasses":[]},"bStorageConfig":true,"savePath":{"path":"[PROJECTDIR]/Saved/HotPatcher/"},"hashCalculator":"MD5","bStandaloneMode":false,"additionalCommandletArgs":[]} |
执行AddToPreset,会将这个配置添加到项目设置中,在ProjectSettings
-Plugins
-HotPatcher
-PresetConfigs
:
它是一个数组,可以添加多个预设。也可以在项目设置中编辑预设的参数,与HotPatcher主界面里的配置项完全相同。
然后就能够在ContentBrowser里的空白处点击右键,在Preset Actions
中就能看到添加的预设了。
选中名字,再选择平台,就能快速打包:
打包完后会在引擎中弹出一个提示:
点击超链接就会打开pak所在的文件夹,方便放入手机中测试:
可以将脚本、ini、项目数据等内容都单独配置为一个独立的Action,这样对他们的修改可以快速地打包出来,直接进行验证。
Cook And Pak
对于资产的打包而言,大多数情况下,资源出现问题没有办法提前预知,也不好添加为一个固定的Preset-Action配置。
比如某个贴图引用丢失、客户端本地修改了UMG、美术或策划想要临时跑测一个地图,等等。都需要精确地把某些资源给打包了,所以针对UASSET资源,我为HotPatcher提供了另一组功能,叫做CookAndPak。
在Content Browser中,直接选中资源或目录,右键,就能看到底部有几个选择:
- Cook Actions,顾名思义只执行COOK,目的是验证Cook之后资源,通常用来分析资源参数对序列化大小的影响。如贴图压缩规格、动画压缩配置等。
- Cook And Pak Actions:执行Cook并且把结果打包为PAK
- Add To Patch Settings:将选中资源添加到HotPatcher的配置主界面中
通常针对资源的快速打包,都使用CookAndPak模式:
然后选择对应的平台,以及是否开启依赖分析,大多数情况下是要开启的,除非你能明确知道它们不需要。
关于CookAndPak,我还提供了两种方式:
- 在当前Editor进程内执行,会阻塞编辑器
- 拉起新的Cmdlet进程执行,不阻塞当前编辑器
对于资源较少的情况,在当前进程内执行速度更快,但是对于地图等具有大量依赖的资源来说,还是拉起单独的进程比较好。
是否拉起独立的进程,可以在ProjectSettings
-Plugins
-HotPatcher
-TempPatchSetting
-StandaloneMode
来控制。
在当前Editor执行,打包完毕后会弹出提醒生成的文件,点击即可跳转到目录:
拉起独立的Cmdlet执行,会弹出一个正在执行的持久性提醒,执行完毕会提醒:
需要等待执行完毕,这个过程不会卡住编辑器,可以做其他的编辑操作。
执行的耗时取决于引用的资源量,以及所选择的资源之前有没有执行过打包(DDC)。
执行完毕之后,会在项目的Saved/HotPatcher/Paks/{EXECUTE_TIME}/Android_ASTC
下面创建出一个对应的 .pak 文件,这个 pak 文件就是打包资源的补丁包,文件名中包含了平台名,不同平台的 pak 文件不能混用。
放入真机
本地验证可以将Pak放入引擎自动挂载的路径,默认有三个:
- Engine/Content/Paks
- GAME_DIR/Content/Paks
- GAME_DIR/Saved/Paks
通常在移动端我们会放到Saved/Paks
下面,Windows则都可以。
Windows
Windows包需要将这个Pak文件放到以下目录中:
1 | WindowsNoEditor\PROJECT_NAME\Content\Paks |
若不存在Paks目录,可手动创建。
Android
在Android中,需要将这个 pak 文件放到下面目录中:
1 | UE4Game/PROJECT_NAME/PROJECT_NAME/Saved/Paks |
如果修改了数据目录到沙盒路径(UE源码分析:修改游戏默认的数据存储路径),则是这个路径:
1 | Android/data/com.xxxx.yyyy/files/UE4Game/PROJECT_NAME/PROJECT_NAME/Saved/Paks |
如果没有Paks目录,可以手动创建一个。
IOS
IOS则要复杂一些,需要用3utools或iMaZing等IOS管理工具传递文件。
放入 文稿 - PROJECT_NAME - Saved - Paks下,若不存在Paks目录,可手动创建。
检查挂载情况
当将pak文件放入上述目录之后,就可以启动游戏了。
如果为了确认pak文件是否生效,可以从Log中查看:
1 | LogPakFile: Display: Found Pak file ../../../PROJECT_NAME/Saved/Paks/2022.10.18-13.02.53_IOS_001_P.pak attempting to mount. |
有这样的Log,就代表资源包被引擎读取成功,可以直接使用,就像它被打进了基础包中一样。
注意事项
手动打包Pak的优先级高于基础包内的资源,意味着一个资源如果补丁包和基础包中同时存在,就会替换基础包内的,就像热更新逻辑。
- 不同平台的pak不能混用!
- 测试完毕之后最好把设备上的pak文件删除,不然后面新打的包可能会出现资源表现错误。
结语
本篇文章详细介绍了HotPatcher提供的快速打包功能的使用方法,可以在开发阶段无需等待完整包构建,按需打包资源和文件进行验证。最大限度地提升资源验证效率,快速创建补丁,避免等待。当补丁被验证之后,再启动完整包的构建流程也未尝不可,保证变动没有引起其他的问题。
另外,我们还会将资源检查一起结合进来,最大限度地保证构建时的资源合规。
博客中有一批文章介绍:
- UE 中利用反射为资产建立属性缓存
- UE 中资源自修正的设计与实现方案
- UE 中多阶段的自动化资源检查方案
- 基于 ResScannerUE 的资源检查自动化实践
- UE 资源合规检查工具 ResScannerUE
它们分别从两个不同的维度提升版本稳定性和修复效率:
- 资源检查保证进入打包流程的资源可靠;
- HotPatcher在资源出现异常时快速创建修复补丁;
总的来说,项目中的游戏资产管理是一个非常庞杂的工作,需要接触到项目的各个地方。做得好了可以提升效率,避免问题。做的不好,将要花费大量的时间去排查资源问题。