《夜莺传说》的跃升之旅,从UE4到UE5的技术升级

时间:2023-10-26 21:34:46 来源:电竞网

Inflexion Games是一家位于加拿大埃德蒙顿的游戏工作室,由一群行业老兵于2018年联手创立。工作室在成立后不断发展壮大,如今,上百名斗志昂扬的开发者聚集于此,他们的背景各不相同,既有来自3A级工作室的专家,也有入行不久的新人,众人团结一致,致力于打造富有深度、历史感和无限可能性的游戏。部分开发者还曾参与制作一些备受赞誉的游戏系列,如《质量效应》、《龙腾世纪》、《反重力赛车》和《孤岛惊魂》。在腾讯的支持下,该工作室即将推出首款自主发行的作品——共享世界生存合成类游戏《夜莺传说》。

我们是Inflexion的两名开发者,Jacques Lebrun和Noel Lukasewich。我们和其他几位开发者曾致力于将我们即将推出的《夜莺传说》项目升级到虚幻引擎5中。

去年,UE5首次发布,我们团队迫不及待地想要利用它所带来的新功能和新机遇。然而,最初,想要将项目从虚幻引擎4迁移到虚幻引擎5中似乎是一项艰巨的挑战。在这篇文章中,我们将深入探讨在生产环境中升级项目所要做的工作,并提供一些或许可以帮助你成功迈出这一步的建议。

关于源代码控制工具的说明:在我们的案例中,我们通过Github获取引擎更新,然后通过Perforce维护和控制我们自己的源代码,然而,即使你使用的是其他配置方式,仍可从本文中获益。

计划和准备

在探讨升级流程之前,有必要谈谈我们的动机,以及我们为什么愿意付出额外的努力,在UE5发布初期就开始使用它。

最吸引我们的激励因素是,Lumen和Nanite能够相辅相成,使创造更强大的视觉效果成为可能。起初,鉴于所有资产都是在未考虑Nanite的情况下创建的,我们认为将项目迁移到Nanite中是不可能的(最终我们还是转向了Nanite,稍后会详细介绍),然而,单单是Lumen所展现出的改进,就足以吸引我们将升级纳入考虑范围。另外,我们预见到,在开放世界系统、资产管理以及整体开发效率方面,工作流程即将迎来大量改进。

最后,随着我们的项目进入“抢先体验”阶段和“游戏即服务”生命周期,我们知道,我们的玩家社区迟早会驱使我们改进技术和视效,这只是时间问题。

确定动机之后,我们开始考虑升级的总体成本。Epic估算,相较于完成UE4的小版本升级,从UE4升级到UE5所需的成本大约是前者的四倍。我们曾经花费一两个月时间升级小版本,因此,我们预计这次大概可能需要六个月。结果,这个预估非常准确。

此外,我们发现,确定阻碍的最简单方式就是直接开始,并检查出现的问题。在我们的案例中,主要问题来自从物理引擎向Chaos物理系统的迁移,但考虑到我们的游戏并没有太多自定义物理功能,因此,我们认为这种风险是可控的。

用于管理引擎升级的流程

对于蓝图项目,升级引擎应该非常简单:没有需要更新的代码,只需在新的引擎版本中加载项目,看看出现了哪些资产错误,然后修复引擎抛出的问题。

升级代码项目涉及更多事项,我们将在此处探讨。关键在于对引擎的定制程度。如果你从未修改引擎,升级将同样非常简单;然而,如果你大幅修改了引擎,那么,你需要付出的努力就瞬间增多了。我们介于两者之间,采用以下做法管理升级流程。

管理引擎差异

标记并跟踪你对引擎的更改将起到帮助作用,这将简化合并代码冲突的过程。对于《夜莺传说》,我们遵循以下流程:

对引擎做出的所有更改都需经由一组审批人员审查,在我们的案例中,这些审批人员就是负责引擎升级的程序员,因此,他们可以指出将难以维护的更改。

我们鼓励尽可能多地将更改推送给Epic,请参阅《为虚幻引擎贡献代码》。这有助于我们在采用未来版本时消除代码差异。

所有更改都会标记在代码中,并通过Jira工单跟踪。例如:

// NTGL_BEGIN - NTGL-1234 - [改进] 修复未初始化的变量

// int IntVar;

int IntVar = 0;

// NTGL_END

差异分为以下几类:

[改进] - 适合提交给Epic的更改

[临时] - 仅为临时需要所做的更改,使用期限通常截至引擎推出下一次主要更新

[预先迁移] - 从未来更新中拉取的更改

[差异] - 我们需要做出这项更改才能发布我们的游戏,但它并不适合推送给Epic(我们通常应该避免做出这类更改)

Jira工单允许我们跟踪与更改相关的额外背景信息。例如,我们可以将更改链接到UDN,或是链接到需要添加或移除此项更改的其他任务。

当差异难以合并到引擎更新中时,我们通常会放弃我们的更改,并在新代码的基础上重新实现它,或者完全舍弃它。

整合流程

更新引擎在一开始可能很简单,只需从Epic的Github获取更新,替换Engine文件夹下的所有内容,然后通过P4V协调离线工作;然而,随着你不断对引擎代码做出更改,这种方式将迅速变得难以管理。

我们利用Perforce的流仓库建立了以下分支:

仓库 / 流 描述

//ue4/release-4.27 未经修改的UE4/UE5版本镜像

//ue5/release-5.0

//ntgl/dev 主开发流,团队的大部分成员将在这里工作

//ntgl/integrate 开发流的子流,你将在这里合并引擎更新

在所有问题都得到解决之前,该流预计会处于损坏状态

开始升级至UE5之前,你需要从UE4的最终版本(//ue4/release-4.27)完成向整合流的合并,以建立修订历史。如果你还未使用4.27版本,可能会考虑一次跨越多个版本进行升级。但根据我们的经验,采用渐进方式,每次只升级一个版本通常是比较简单易行的。

接下来,你可以按照以下方式,建立release-5.0分支:

p4 copy //ue4/release-4.27 -> //ue5/release-5.0(最初作为4.27的副本创建)

基于官方版本更新//ue5/release-5.0的内容

更新和合并步骤现在变为:

1、将开发流中的所有更改合并到整合流中

如果内容更改之间存在任何冲突,始终接受来自开发流的更改。以避免丢失内容创作者的任何工作结果

2、将所需的虚幻版本镜像同步到单独的Perforce仓库中(例如//ue5/release-5.x)

该镜像应保持原样,不进行修改,用于跟踪Perforce修订历史中的引擎更改,以便为合并步骤提供帮助

3、从//ue5/release-5.x合并/整合到//ntgl/integrate

4、解决合并冲突并提交

这些步骤全部都可以手动完成,但如果投入一些精力,通过编写脚本实现自动化,你将享受到极大的益处。

在合并更新后,你可以将引擎升级任务分解为以下几个不连续的步骤:

5、修复与代码项目生成相关的警告和错误

6、修复编译和链接错误

7、修复编辑器和烘焙错误

8、修复自动化测试失败错误

9、修复游戏漏洞

自动化

在自动化方面的投入有助于大幅简化升级流程。在理想状况下,你应该拥有一套可重复执行的构建流程,可针对你的整合流运行,并在合并到开发流之前验证一切是否正常。还有一些方面,也能够起到帮助作用:

投资并维护一套全面的自动化测试套件,在尚未开始执行任何手动测试之前,你就能通过它捕捉到许多问题。在我们的案例中,当我们最初迁移到UE5时,我们的自动化测试就能够标记出UE4物理引擎与UE5 Chaos物理系统之间的许多不一致。

对于引擎版本的镜像复制,以及各种合并步骤的执行,你可以通过编写脚本大幅加速流程。

在烘焙游戏之前,通过添加额外的自动化检查,以运行资产验证器并编译所有蓝图(-run=CompileAllBlueprints),将有助于捕捉到资产中的其他问题。

经常在整合流中执行你用于开发流的那套构建流程,有助于确保在最终合并之前捕获所有潜在的边缘情况。

投资建立系统,用来分发整合流的测试构建,这将允许你展开更大规模的游戏测试,以便尽早发现游戏问题。

提示和技巧

在升级过程中,我们遵循以下各种简化流程的技巧。

对引擎进行重大升级时,尽管大部分文件都会自动得到解析,但你仍需要面对一份包含数万更改的更改列表。下面的p4命令可以将需要手动解析的文件分离出来,形成单独的更改列表:

p4 -F %localPath% resolve -n | p4 -x - reopen -c [new changelist #]

修复编译和链接错误时,使用-DisableUnity进行编译。这将关闭虚幻编译工具中的编译优化(将多个.cpp文件合并成一个)。编译将花费更长的时间,但是跟踪编译问题会变得更容易,这也将让你捕捉到include语句缺失的问题。

如果你通过github获取虚幻引擎,就需要决定如何填充从GitDependencies.exe获取的文件。你可以让开发人员单独更新这些文件,或者和我们一样,将这些文件合并到镜像自动化脚本中,然后将这些文件提交到我们自己的Perforce镜像中。

密切关注虚幻引擎的废弃警告,因为这些警告通常会为你指明升级项目的正确方向。将编译警告数量降至0,这样可以让你更轻松地跟踪并处理这些废弃功能。

在整合流中包含所有资产,这样一来,你将能够根据需要升级单个资产。虽然我们不需要经常做这样的工作,但如果时常在主开发流修改这些资产,管理起来将非常繁琐。对此,我们可以提供一些有帮助的建议:

如果你能仔细挑选一些最小的引擎更改纳入开发流,并在开发流中更新资产,将消除发生冲突的可能性。

如果你能够使用命令行升级资产,则可以创建一条在每次合并后运行的命令行,以确保所有相关资产都是最新的。在许多情况下,你只需在最新版本的编辑器中重新保存资产。

即使引擎版本尚未进入抢先体验状态,Epic仍允许你访问该版本分支。这允许你提前开始合并即将发布的版本,并缩小一次合并的代码量。同样,日常从开发分支进行合并,能让你在遇到存在困难的合并时立即中止,以便与相关开发人员合作解决问题。

如果你依赖来自商城或其他供应商的第三方插件,在插件更新之前,最好等待。我们经常会希望在这些插件得到更新之前就进行升级,这意味着,需要花费额外的精力来更新插件。然而,如果你再等一段时间,就可以“免费”获得这些插件。

引擎每次升级都会带来一些非常有用的功能。尽管立即开始使用新功能很有吸引力,但我们始终会首先推送对游戏或开发人员工作流程几乎不产生实质更改的引擎更新。仅当我们在开发流中确定这次升级具有稳定性后,我们才会开始尝试新功能。

虚幻引擎5的优势

升级到Lumen和Nanite带来了令人兴奋的可能性。谁不想获得更精确的反射光照,谁不想大幅增加游戏的多边形预算?

虽然开启Lumen和Nanite很容易,但《夜莺传说》的准备工作还是花了一些时间,因为游戏最初是为UE4优化的。《夜莺传说》在管线的所有组件中都严格地遵守了PBR规则,因此在集成Lumen后,它迅速地让我们的游戏变得更闪耀了;另一方面,将网格体转换到Nanite之后,我们能够实现额外的优化。

将项目转换到Nanite花了更长时间,因为我们也希望利用虚拟阴影贴图。虚幻引擎5支持Nanite和非Nanite资产互通,得益于此,我们可以逐步转换,这让我们在过渡期间仍能确保游玩体验完整。也就是说,随着越来越多的资产转向使用Nanite,你将看到虚拟阴影贴图提升了性能,因此,这个转换过程将让你了解游戏将有怎样的性能表现,从而起到一定的激励作用。

单个资产的转换过程往往可以归为以下几类:

有些资产的保真度已经足够高,我们只需为网格体启用Nanite。

有些资产需要以更高的保真度重新创作,才能从中受益,因此我们以Nanite为标准重新构建了这些资产。

由玩家建造的建筑结构有一个自定义着色器,当玩家放置建筑结构时,会将其渲染为透明。由于Nanite只支持不透明对象,因此我们实现了一个系统,当网格体处于这种特殊的放置模式时,我们会回退使用支持透明度的非Nanite网格体。

另一个对我们工作流程帮助极大的方面是引入关卡实例和打包的关卡Actor。在UE4中,我们一直在努力实现各种预制组件,但打包的关卡Actor为我们创造了新的可能性,使我们能够在《夜莺传说》中以程序化方式组装环境。

随着版本从5.0更新到5.2,我们看到引擎的许多功能都得到了改进,例如体积云渲染,以及Lumen的植被渲染。最后,Nanite、Lumen和虚拟阴影贴图的组合带来了相当震撼的视觉效果。

在经历了UE5的改造后,我们对《夜莺传说》的外观感到非常满意。如果没有Lumen和Nanite,我们不可能实现如此高的保真度,我们期待通过《夜莺传说》和虚幻引擎5的未来更新将游戏外观推向新高度。

1/1页