怎么看Unity 2021.2 在编辑器工作流上的改进?
这里介绍一下Unity编辑器核心功能优化上的最新动态。这些改进涵盖了从资源导入到游戏的构建与部署等各个方面,可以帮助用户在开发的每个环节实现快速迭代。[*]Unity编辑器启动时间优化
Unity 编辑器在处理大多数内容时,需要先将源文件转换为适用于游戏或实时应用的格式。在资源导入后,引擎会将这些转换后的文件与相关数据储存在 Asset Database(资源数据库)中。这时,如果某个文件修改了磁盘路径,Unity 会刷新这个数据库;如果脚本经过了修改,则引擎会重新加载整个 C# 域。在项目部署到目标平台时,Unity 的构建系统将其打包成二进制文件,用于在目标平台上分发和运行。整个流程如下图所示。
在所有这些步骤中,Asset Database 是实现可靠、高性能和可扩展导入流程的核心技术。但除此之外,编辑器迭代时间还受许多部分的影响,包括导入程序、压缩工具、编辑器核心代码及构建管线。
鉴于 Asset Database 占用了主要的项目启动流程,我们可以通过优化数据库的代码来测试其实际影响。Unity的Asset Database 团队的高级工程师 Javier Abud 和 Jonas Drewsen 合作使用一个包含 90 万个资源的测试项目建立了一个基准测试框架,借此提出了一系列启动时间的优化和改进。两人还开发了一套自动化数据记录工具,用于记录数据库对 Unity 编辑器性能的影响。
"有许多成果目前就在我们手边,但有些时候我们也需要一些发散性思维。我们每周能在测试项目上减少大约 15 秒的启动时间,这些优化接着会应用到 22 个真正的项目中进行验证,以此来保证这些卓有成效的优化不会在真正的项目中适得其反,”Javier Abud 表示。举例来说,团队有效地减少了线程或排序时的内存分配,并推出了项目文件及文件夹并行处理的方法。在 Unity 2021.2 中,一个包含 90 万个文本资源的项目其启动时间成功从 3 分 36 秒减少到了 1 分 17 秒,而小型项目的启动时间平均加快了 8.7%。
2. 模型和纹理在Unity编辑器中的处理速度提升
2.1 Import Activity(导入活动)窗口
Javier 还开发了一个称作“Import Activity Window”的新工具,可显示出资源导入的原因、导入过程的耗时,以及可能作为依赖项被导入的资源。
如果将编辑器的启动流程以饼图表示,我们发现模型和纹理的导入通常会占有最大的比重。这里,我们来尝试导入《Book of the Dead: Environment(死者之书)》 项目所有的纹理、模型、预制件和场景。
源数据(包括 346 种纹理、133 个模型、214 个预制件、6 个场景)的大小为 2.25GB。时间统计在配备 Windows 操作系统、AMD ThreadRipper 1950X(16 线程)和 SSD 硬盘的设备上完成上,测试分别比较了 Unity 2020.3.10、2021.1.9 和 2021.2 alpha(a19)。
在默认设置下,2021.2 alpha 导入时间仅为 114 秒(相较 2021.1 快了 1.27 倍)。如果再启用四个导入程序形成并行资源导入,导入时间将缩短为 77 秒。并行资源导入的设置可在 Project Settings > Editor > Refresh 下找到。
如果再到 Build Settings 窗口中启用 Force Fast Compressor(强制快速压缩)选项来减少迭代时间,所有资产的导入时间将仅为 38 秒——相比于 2021.1 版整整快了 3.8 倍!整个优化不会改变纹理的大小或格式,而是用更少的运算生成了尽可能好的压缩纹理像素。
2.2 模型导入
优化团队的 Richard Kettlewell 自进入 2021 年周期以来一致专注于加快模型导入速度。“(该领域)有许多问题和相应的方案,但都并不显眼,”他解释说。“举个例子,逐个为每个顶点分配内存在处理大型网格表面时速度会非常缓慢,而部分算法可通过运行一个预处理通道来计算某块网格所需的总内存,然后以块为单位分配内存。此外,很多导入流程都会处理文件的每个表面、顶点、动画或材质。如果能将其拆分为独立的部分再并行导入,导入速度便会有极大的提升。”
"我们还采用了更快的内存分配程序用于给导入时的暂时性内存",他继续说,“这给各个阶段都带来了些许速度提升。我们还要感谢所有在百忙之中分享问题模型给我们的艺术家们,如果没有这些内容,我们就无法进行测试并优化!"
Unity 2021.2 现在可以为文件中的多个网格模型同时生成法线、切线和光照贴图 UV。在测试中,某文件原先需要花 33 分钟导入(其中 30 分钟耗费在生成光照贴图 UV 上),而在优化后总导入时间可被降低至 11 分钟,减少 66%。包含多个网格模型的文件将受益于此优化,原本缓慢的导入流程将有极大的速度提升。
我们还将其他模型导入流程进行了多线程处理,包括:
[*]FBX 动画的导入
[*]顶点缓存优化程序的运行
[*]网格三角变化(将多边形转变为三角形)
[*]SketchUp 顶点处理
2.3 纹理导入的优化
Quality of Life 团队负责了纹理导入部分的优化,继续推进 2021.1 周期初期的既定目标。在 2021.2 中,团队再一次更新了 ASTC 压缩程序,进一步提速 30%,并提高其在不同 CPU 上的运行稳定性。另外,BC7 的压缩速度约为原先的 2 至 3 倍。
Build Settings 的 Force Fast Compressor(强制快速压缩)选项也是团队的优化举措之一。Aras Pranckeviius 解释说:“如果纹理质量并非特别紧要,你可以使用更为精简的压缩流程(‘Force Fast Compressor’),或者设定限制全局的导入纹理大小。” “如果我现在将 2GB 的纹理导入成安卓 ASTC 格式,与原先的 20 分钟相比,整个导入流程可在 2 分钟内完成,唯一的缺点是画质的损失会稍微多一点。但它仍非常适合快速的迭代。”
3. Unity编辑器打开大型、扁平层级的场景将快 90% 以上
场景根目录(即层级视图顶层的 GameObjects)通常会按顺序存储为一个相互关联列表,因此其加载和合并会耗费不少性能。此前,场景在打开时编辑器会依次将每个根对象添加到列表中。每一条目会在场景中加载时会被添加到列表中,而每个新 GameObject 都必须在列表里新建一个条目。但现在,新添加的根对象将作为 dynamic_array 储存,列表仅在需要时会进行排序并相互关联。由此,编辑器打开测试场景的时间可以减少 90%——从 17 秒减少到仅 1.45 秒。
3.1 编辑器的小提升带来性能优的大胜利
Performance Optimization 团队的是 Unity官方帮助客户与内部大项目优化编辑器使用的主力。随着游戏越来越大,原本几秒钟的等待可能会逐渐发展成一个大问题。
Peter Hall 是 Unity 2021.2 中性能优化的主要负责人,在他的众多速度优化方案中,其中一个是对大型场景对象拖拽与选取的流程优化。在内部的测试场景中,整个流程花费了 78 秒,作为优化的基准参考。“在 Profiler 中的数据记录显示,大部分时间都花在了从 GameObjectTreeViewDataSource.RevealItems 中调用来的 BaseHierarchyProperty::Find 上。函数会将层级中的所有父对象写入到根目录下,但对象仅会被逐条写入。如果使用 IHierarchyProperty.FindAllAncestors,这段运算的耗时可降低到 50 毫秒左右,速度可提高约 1400 倍。”
编辑器内还有其它地方也有了提升,运行大型项目的速度已经变得更快,比如新建材质快了 2 倍、场景对象全选快了 1.6 倍、复制/粘贴游戏对象快了 50%。
3.2 Unity版本构建
在进入测试和优化阶段时,游戏在设备上的迭代速度会变得非常关键。因此,Unity投入了大量的时间和精力来全面优化了软件包构建管线。例如,Unity 2021.2 的 Scriptable Build Pipeline(可编程构建管线)与 Build Cache(构建缓存)运行速度有所提升。
优化的一个主要重点在于让运行版构建流程仅打包新添的改动,而非整个项目内容。我们最近就改进了 Unity 本身的构建方式,并将同样的方法应用到了运行版构建和脚本编译中。由此,Unity 2021.2 Beta 测试版现在支持 Windows、macOS、Android、Linux 和 WebGL 的增量式版本构建,并支持 C# 脚本方案的增量式编译。这项改进将在未来逐步推广到剩下的平台上。
"Unity 在构建运行版时做了很多事情。首先,我们将所有场景、资源及游戏管理程序序列化为数据文件来创建运行数据。该流程由原生 C++ 代码完成,"脚本团队的 Jonas Echterhoff 解释说。"当数据创建完成后,我们再调用一个后期处理方法。每个平台都有各自的方法代码。后处理程序因平台而异,但一般都包含二进制运行文件和相关文件的复制与内存分配、IL2CPP 代码到原生数据库的编译、以及符合平台要求的数据压缩和打包等。这种后处理逻辑便是新构建系统中新添的内容。" 新系统对每次构建的输入输出及相互间的依赖都有记录,因此只会重新运行必须的构建步骤,并在可能时以多线程完成构建。
3.3 Unity源代码IL2CPP 速度提升
全新的 IL2CPP 源码加密功能可生成最少 50% 的代码。降低构建耗时与可执行文件的体积。由于加密方法稍有不同,新功能可能会轻微影响运行时性能,因此其最适用于减少团队内部的迭代时间。
在 2020.3 中,IL2CPP 便经历过一次大修,使其能够利用多核 CPU 来生成 C++ 代码,用于运行版的构建。IL2CPP 团队的 Michael Voorhees 表示:“(IL2CPP)代码完成度较高,我们的修改工作也因此受到了诸多限制。我们不得不在库中删除大量的静态字段,然后根据拆分法(divide and conquer)将代码重构。我们还重构了内部 API 来适应并行和串行编译模式,借此来降低新优化的应用风险。并且,我们还创建了耐用的压力测试场景,再花约一个月进行有效性测试,直到并行编译满足成为默认编译方法的要求。”多亏了核心硬件使用的提高和优化,IL2CPP 编译时间在整个 2021.1 有了进一步减少。
而在 2021.2 中,团队着手将编译中最为耗时的步骤——泛型集合的编译并行化。Michael 表示:“为了打开新局面,我们用自己的数据模型替代了 Cecil。这些改动,外加上许多其它的小优化,使得 IL2CPP 在 2021.2 中的编译速度比 2021.1 快了两倍。”
构建速度有了巨大的改变,特别是对移动端开发者而言。举例来说,最新的 2D 示例项目《Dragon Crashers》在 Unity 2020 LTS 中采用的是非增量构建法,如果脚本有了改动,要为 ARMv7 和 ARM64 构建将耗时 91 秒。而在 Unity 2021.2 中,新的增量构建工具仅花了 44 秒,不到前者的一半。
在 Unity 2021.2 技术更迭版中,AssetBundle 加载也更加高效,还有 Unity 在工作流改进上的未来计划。
大家可以在Unity技术专栏中查看更多的信息:
https://developer.unity.cn/projects/behind-the-scenes-speeding-up-unity-workflows
页:
[1]