虚幻引擎:《无畏契约》的基石

Marcus Reid, 《无畏契约》技术主管, Riot Games

Marcus Reid

作为Riot Games为《无畏契约(VALORANT)》提供内容支持的技术主管,Marcus Reid在一个程序团队中工作,负责游戏引擎工作,并支持整个《无畏契约》开发团队中的非程序内容开发者(设计师、美术师等)的工作。在2017年加盟Riot Games之前,Marcus曾在The Coalition工作两年,以工程师身份参与开发了《战争机器4》和《战争机器终极版》。 
大家好,我是Marcus Reid,《无畏契约》内容支持团队的技术主管。在6月2日,我们发布了这款基于角色的5v5策略类FPS。依靠虚幻引擎提供的可靠基准,我们的团队得以集中精力做好游戏的关键特色。我们针对自身的具体情况对引擎做了有针对性的重大改进,并且经常升级到新的引擎版本,以充分利用Epic和社区提供的功能。这种做法使我们这个比较小的程序团队也能支持在编辑器中构建游戏的大量内容开发者。我们的大多数编程周期都用来开发游戏性和服务功能,而不是构建已经由虚幻引擎提供的功能。

我们许多较大的引擎修改是在《无畏契约》严格的性能要求驱动下完成的。我们测量了客户端在各种硬件配置下的性能,还评估了服务器在目标节拍率和并发性方面的性能(换句话说就是每个核心运行的游戏局数)。以下示例详细说明了我们为追求性能目标而修改引擎的两个领域。
使用“Dismiss”,Reyna每次击杀后就可获得暂时的隐身能力,可以用来包抄或逃离对手。

针对低端GPU定制渲染器

我们的客户端最低规格目标是在Intel HD Graphics 4000上达到30 FPS(每帧时间为33.3毫秒),这是一款2012年初上市的集成GPU。玩家为了改善帧时间会调整画质,而我们必须在不同的画质设置水平下保持竞技的公平性。重要的是,不同的配置不能影响游戏中准星的清晰度。

要达成这些目标,就必须严格控制游戏中每种内容的美术预算,还要让美术师付出巨大努力和创造力,在不降低最低规格性能的前提下使游戏画面美观。达成性能目标是我们程序团队负责的任务,而美术师是此过程中的关键合作伙伴。

我们对引擎的渲染层下了很大功夫,包括但不限于:
  • 基于虚幻引擎的移动渲染路径定制前置渲染器。
    • 我们的实现要早于UE4.14中为台式机添加的前置着色渲染器。
  • 编写唯一基本通道着色器,使用尽可能少的指令和纹理采样,仅支持我们需要的功能。
    • 当材质质量设置为“低”时,基本环境材质的像素着色器仅使用41条指令和一次纹理查找。
  • 把通常仅限于静止和可移动光源的少数功能以极低开销移植到静态光照路径。
    • 例如:每张地图都有一个能在第一人称手臂和武器上投射动态阴影的静态定向光源。
    • 《无畏契约》的游戏性环境仅使用静态光照。
  • 对贴花进行各种调整,包括根据朝向剔除,以及通过自定义可视性查询进行遮蔽剔除,简化顶点雾支持,和自定义光照贡献。
  • 聚合由每张地图中大块部分(墙壁、地板等)的简化几何体组成的、由构建烘焙的Z轴预处理网格体来绘制出纵深,而不是使用通常的深度通道。
    • 我们的测量显示,在场景中采用聚合网格体,相比个别网格体深度绘制调用有显著进步。
    • 这种方法将来可能被从GPU场景合并自动绘图调用取代——每次用Epic支持的新引擎功能取代自定义功能时,我们总是欢欣鼓舞。
综合我们的引擎修改与美术师的努力,我们在最低规格上保持了30 FPS或更好的性能。这些优化也意味着配备现代GPU的机器往往能获得仅有1-3毫秒的全帧渲染时间。
身轻如燕的Jett用她的“Blade Storm”发射匕首进行反击。

降低游戏服务器上的动画开销

《无畏契约》的游戏服务器以每秒128个节拍的速度单线程运行,每个CPU核心运行三局游戏,因此每个服务器实例的帧时间预算仅有2.6毫秒。要达成这个目标需要对整个游戏进行大量优化,角色动画就是这方面相关工作的一个好例子。

游戏服务器会跳过命中注册中未涉及的所有骨架网格体的动画。当无法进行战斗时(例如,在每回合的武器购买阶段),会完全禁用动画。

为了准确检查命中,任何可能被武器射弹命中的Actor都必须评估动画和设置正确的骨骼位置。当一支枪开火时,游戏服务器会将服务器模拟倒回至客户端开火的时间点,并考虑网络延迟和客户端/服务器帧时间。倒回会根据子帧服务器时间偏移在主要骨骼位置之间插值,然后对照可成为目标的Actor检查命中以计算伤害。在检查过命中以后,倒回器将服务器模拟恢复到当前时间并继续推进。

测量显示,在我们的一个角色上进行动画更新和评估最多可能耗时0.1毫秒。如果我们每个服务器帧都生成所有10个角色的动画,那么就会用掉近40%的总计帧预算。大部分成本来自评估步骤,更新步骤相比之下开销很少。

最初,我们尝试每隔几帧就对动画限速,并在每次评估后捕获最终骨骼位置的快照。倒回总是会强制对当前帧进行动画评估和快照捕获,我们在间隔最近的两个快照之间插值以进行命中检测。

接下来,我们添加了逻辑,通过排除不可能被某次射击命中的Actor来剔除不必要的倒回。这就消除了针对不相关Actor的强制动画评估。为了确定相关性,服务器会发送一个足够大的球体,从玩家沿其武器的瞄准矢量射出,以捕获任何最新的运动和武器误差。然后对任何与这个球体碰撞的角色进行倒回和评估。
正在奔跑的Cypher必须经过倒回,以评估射击的玩家是否射中了他。Sova站得足够远,因此服务器不需要全面评估Sova的骨骼位置来确定他是否可能被击中。
通过剔除倒回,我们只对可能被命中的角色按需执行动画评估,但这还是要付出定期评估的开销来为所有角色的骨骼位置创建快照。为了省去这些评估,我们运行更新步骤,捕获每个动画图标节点的输入快照,而不是捕获最终骨骼位置的快照。然后我们可以将动画图表倒回到以往的任意时间点,评估图表来获取骨骼位置。

对动画图表节点输入生成快照是重大的引擎修改,因为这需要理解每种节点类型的必要状态,但就我们的情况而言,由此带来的速度提高是值得的。在实施了所有这些优化后,我们现在每个服务器帧平均只需要0.3毫秒来处理动画。

心得

虚幻引擎提供了优秀的工具和一套可靠的性能,成为《无畏契约》的坚实基础。我们的程序团队没有花时间从零开始,而我们的内容开发者使用编辑器工作的效率也非常高。虚幻引擎使我们能够对游戏中的特色部分进行快速迭代。

    立即获取虚幻引擎!

    获取全球最开放、最先进的创作工具。 
    虚幻引擎包罗万象,并提供完整的源代码访问权限,开箱即用,诚意十足。