在使用UnrealEngine进行项目开发的过程中,经常会开发和接入各种类型的插件来对引擎进行扩展,从而实现不同的需求。对于开发者而言,对运行机制的理解优于工具的使用。所以对于插件的接入和开发,有必要了解其原理。
之前我也开发了一些UE的工具和插件,我希望写一个相关的系列文章,把UE插件与工具开发相关具有共性的技术内容做一些总结,并分享一些我开发插件时的一些思考和功能脚手架。尽可能用最少的代码、最小的侵入式和最佳的实现策略,来实现需要的功能。
在使用UnrealEngine进行项目开发的过程中,经常会开发和接入各种类型的插件来对引擎进行扩展,从而实现不同的需求。对于开发者而言,对运行机制的理解优于工具的使用。所以对于插件的接入和开发,有必要了解其原理。
之前我也开发了一些UE的工具和插件,我希望写一个相关的系列文章,把UE插件与工具开发相关具有共性的技术内容做一些总结,并分享一些我开发插件时的一些思考和功能脚手架。尽可能用最少的代码、最小的侵入式和最佳的实现策略,来实现需要的功能。
随着HotPatcher的开发以及我对于资源管理方面的技术的研究,围绕着HotPatcher实现的功能越来越多,实现也越来越复杂,加上引擎的不断更新,一个大而全的插件对引擎的兼容性越来越难以维护。
随着新一代引擎UE5的到来,HotPatcher同样会跟进UE5中支持,并针对UE5的特性开发新的功能。我希望它不仅仅只是一个资源打包工具,而是包含资源管理、审计、打包、热更新、包体优化、构建提升等等全方位的资源管理方案,并且作为一个开放式的资源处理框架。
本篇文章会介绍HotPatcher的模块化进展,对现有功能的支持。以及如何利用HotPatcher强大的打包能力根据项目需求进行自定义的模块化扩展。最后,会介绍HotPatcher项目后续的开发计划。
2022年的Unreal Open Day是Epic官方以线下活动+线上直播的形式进行的,很开心今年参加了线下的Unreal Open Day活动。
今年我录制了一场线上的技术演讲,也去上海直播现场参加了线下活动,很荣幸再次获得了Epic授予的杰出社区贡献者奖项,对我是认可也是激励,期待UE技术社区能发展的越来越好,成为最为活跃的游戏开发者社区。
本篇文章做一个简单的记录,把 UOD 2022的资料做一下整理,也把我参加 UOD 的视频、演讲 PPT,以及相关的资料做一个总结,还有一些在 UOD 直播现场拍的照片。
UE默认的资源管理较为复杂,默认情况下是根据在ProjectSetting
里配置的地图、目录、PrimaryAsset的配置,以及对一些条件的组合检测来执行资源打包过程的。并且,UE的Cook是根据运行时的动态加载来实时添加资源打到包中的,这导致打包的资源进包过程几乎等同于黑盒。
博客中介绍默认的进包资源规则及基础包拆分的文章:
本篇文章提供了一种新的思路,利用HotPatcher的精确Cook和打包机制,实现了一个HotChunker的Mod,能够对引擎的非侵入式,直接复用UE默认打包过程、简单清晰地进行拆分基础包。本篇文会具体介绍使用方式以及实现原理。
技术文章是能够有效锻炼表达能力和进行技术积累的方法。与单纯的技术笔记不同,我认为的技术文章应该是对实际的问题或新技术思路的解决方案,而不是技术点的简单堆砌。
对于如何写一篇我认为合格的技术文章, 最近做了一些思考,本篇文章会探讨我写文章时的一些思路和步骤,以及工具推荐和CI/CD自动化发布的实现。
ASTC
是Adaptive Scalable Texture Compression
的简称,是在移动端流行的贴图压缩方案。当平台使用ASTC打包时,UE默认使用Intel ISPC Texture Compressor压缩贴图,但它具有一些局限性,只支持8x8
及以上的压缩规格,10x10
和12x12
则不支持,如果在项目中指定它们,也是会使用8x8
的规格。除ISPC外,引擎中也提供了ARM的astc-encoder压缩方式,可以支持8x8
以下的规格,但默认未启用,而且引擎中的集成压缩效率非常低,在大规模资源中,使用astc-encoder压缩贴图对Cook耗时是非常大的挑战。
本篇文章分析UE中贴图使用ASTC压缩的配置以及实现方式,以及引擎中astc-encoder的压缩效率和优化思路。
在大型项目中,资源的规模非常庞大,涉及的制作团队也非常广泛,场景、角色、UI、动画、特效、蓝图、数据表格等等,随之而来就是资源量和资源规范的管理难以把控。
对于制定的资源规格,美术制作人员难以覆盖100%的情况,会存在不经意间漏掉,大多数情况下都是包内发现问题后再处理,而且对于存量的资源,需要耗费大量的人力处理,难以审查和修复。
基于这种痛点,我之前开发了一个资源扫描工具,可以方便地编辑规则对项目内的资源进行扫描。
近期,我对插件做了全方面地升级,增强了编辑时和自动化检查的能力,本篇文章会介绍如何利用ResScannerUE实现编辑时、提交时、CI定时或Hook任务、Cook时等各个阶段的资源扫描,把错误地资源尽可能地在制作时暴露出来并提示解决,避免包内资源异常。
在插件的具体实现上,也针对扫描速度做了很多优化,尽可能把检查变成一个无感知的行为,文章内会具体介绍。
在文章基于 ZSTD 字典的 Shader 压缩方案中,我介绍了一种利用ZSTD字典压缩UE的ShaderCode的方法,可以极大地提升ShaderLibrary的压缩比。但训练字典和使用字典进行压缩的流程仍然比较复杂,并不是一个高效的工程实现:
根据上述的流程,需要变动引擎才能实现Dump ShaderCode;其次是流程的割裂,Dump ShaderCode之后需要拉起zstd
程序执行训练才能得到字典;最后,仍需要再Cook一遍工程,使用训练出的字典压缩Shader。并且在关掉Shader的压缩后会导致使用LZ4压缩的DDC Cache Miss,重复Cook执行的时间开销巨大,在海量Shader的项目中耗时无法接受。
基于这种痛点,我研究并实现了一种高效的字典训练方法,无需修改引擎,并且十分快速地训练字典和基于字典压缩。能够直接从ushaderbytecode中训练字典,并生成使用ZSTD+字典压缩的ushaderbytecode,极大地提升了处理效率,完全Plugin-Only的实现,接入成本几乎为零,后续将作为HotPatcher的扩展模块发布。
Pak是UE中的UFS中的一环(Unreal File System),是在应用层构造的一种虚拟文件系统。用于把游戏相关的资源、文件打包至一个Pak文件中,避免在运行时对游戏资源的访问创建出大量的文件句柄,并且可以做读缓存(PakCache),提升加载效率。
并且,在UFS中,可以控制每个Pak的优先级,可以用来控制文件系统中文件的优先级。在通过UFS加载文件时,优先级高的Pak中的文件会被首先命中,就可以替换掉低优先级的文件,这也是UE实现热更新的关键,详见之前的热更新系列文章。
但默认情况下,Pak的打包都是在UE端进行的,PakUtilities
和UnrealPak
都是开发端的功能,运行时不存在,这意味着不能在运行时创建出Pak文件。但Pak本身是Archive的文件形式,理论上是可以进行运行时重组的。
本篇文章就从Pak的创建、文件格式、UFS分析、运行时重组可行性等方面着手,探讨运行时重组Pak的实现细节以及应用方向。
随着项目规模的日益增大,UE里Shader的变体数量逐渐累增,往往能够达到数百万的Shader变体,虽然UE为了避免Shader的重复存储提供了Share Material Shader Code
功能,可以把Shader序列化到一个独立的ushaderbytecode
文件中,但也会占用几百M的包体大小。而UE默认情况下,把这些NotUAsset文件默认进Chunk0,即必须进基础包,对于移动端的基础包影响很大,几百M的空间,可以放很多资源了。
为了解决这个问题,只能从三个方面入手:
第一种方式需要TA和美术协同实现,想要有显著的提升较为困难。第二种方案详见之前的热更新系列文章(Unreal Engine#热更新)。本篇文章从第三种方式入手,为Shader实现了一种特殊的压缩方式,可以有效地降低shaderbytecode的大小,大幅度提升Shader的压缩比,并且可以与方案2结合使用,在拆分shaderbytecode的同时,大幅度提高压缩率。