优化 Niagara | 02 可扩展性和最佳实践

科技   科技   2024-07-15 09:02   上海  


概述

本文档中概述的策略的主要目标是减少粒子系统在个体和总体层面上所做的工作量。第一个教程中的指导应该会指出哪些地方需要做额外的工作,而本教程应该会为您提供在这些方面进行更改的工具和选项。在减少总体工作量时,我们可以避免不必要的工作,也可以选择开销较小的解决方案。


实例计数:减少关卡中的系统数量

如果某个关卡中有足够多的系统,即使是经过优化的系统也会影响性能。默认情况下,我们使用 Niagara World Manager 批量勾选同一系统的实例,但系统的实例越多,游戏线程上需要完成的工作就越多。一般来说,在更多实例上模拟相同数量的粒子在工作量方面会降低性能,但拥有更多实例可以让 Niagara 在更精细的级别上剔除粒子,因此在少量大规模实例和大量小规模实例之间需要权衡


实例计数减少策略

总体而言,您可以通过控制关卡中生成的系统数量,或在生成系统后更积极地剔除它们来减少实例数量。这两种方法都有各自的用处,我们为它们都提供了工具,但通常最好先为您的项目设置一些核心效果类型,并确保所有 Niagara 系统都分配了一个。

可扩展性和效果类型

我们在 Niagara 中提供了许多可扩展性选项,包括可重复使用的资产,这些资产可通过我们的效果类型资产应用于任何系统,以及直接在 Niagara 资产中覆盖系统、发射器和渲染器级别。它们允许基于可扩展性级别(例如中、高和 Epic)和每个平台进行控制,因此您可以区分每个级别对于项目目标平台的含义。其中许多设置将通过剔除来减少级别中的 Niagara 系统实例数量,但也可用于缩减生成的粒子数量、禁用昂贵的渲染器或完全禁用发射器和系统。


系统即服务

减少实例数量的另一种方法是充分利用现有的系统。对于像抛射物和撞击这样的粒子效果,通常在集中区域中短时间内生成多个实例。可以在一定程度上利用池化来防止重新分配这些实例的组件,但重新激活它们仍然会产生开销,并且依赖于先前的实例完成并返回到池中。系统即服务方法旨在将新粒子添加到现有系统,而不是将新系统添加到某个级别。5.4 引入了新功能来简化此工作流程,但在旧版本中可以使用用户参数。下一教程将更深入地介绍此策略。


发射器数量:减少资产层面的开销

在构建 Niagara 系统时,尤其是当您从 Cascade 切换时,为系统中的每个独特视觉元素添加新的发射器或对行为进行细微调整是很自然的。然而,这可能会对性能产生负面影响,因为每个发射器都会产生开销。

Niagara 使用虚拟机在 CPU 上运行脚本。我们这样做主要有两个原因:可扩展性和并行化。借助模仿 GPU 的 SIMD 特性的 VM,我们可以默认让所有 Niagara 脚本同时适用于 CPU 和 GPU。从一开始就将它们构建为脚本可以降低希望创建自己的脚本的用户的入门门槛,提高可扩展性,而为 SIMD 设计脚本可以让 Niagara 更容易地在 CPU 上并行执行脚本。

此 VM 的缺点是每个发射器都会产生开销。即使将粒子定位为 GPU 模拟,我们仍然会在 CPU 上运行系统和发射器脚本,以便它们可以与游戏线程交互。这意味着开销是固定的,避免它的唯一方法是减少系统中的发射器数量或关卡中的实例数量。

对于 5.4,我们有实验性的轻量级发射器,它们放弃了可扩展性和其他功能,以追求性能。在未来的版本中,它们将成为减少发射器数量的许多用例中的可行替代方案,因为这些发射器不会产生 VM 开销。 


缓解策略

以下是一些可用于减少系统中发射器数量的策略。一般的想法是将它们合并,因为模拟的行为或多或少是相同的,唯一的区别是视觉元素(渲染器)或初始化数据(如起始位置)。


生成索引

生成索引可用于在发射器中创建具有共同行为或起始数据的粒子组。粒子会将其生成索引保存为参数,该参数可用于在 Niagara 脚本中动态选择不同的数据。一个常见示例是创建用于对网格的不同部分进行采样的组,否则这些部分将具有相同的行为。例如,Fortnite 中的尾迹从角色的手和脚进行采样。在 Cascade 中,为每个尾迹创建一个发射器,但在 Niagara 中,为整个效果创建一个发射器,其中包含四个生成组,每个组设置为对角色骨架上的不同骨骼或插槽进行采样。


多个渲染器

使用 Niagara,单个发射器可以有多个渲染器,因此可以从发射器模拟的每个粒子创建多个视觉元素。一种常见的用例是将光渲染器与精灵或网格渲染器结合使用,以便粒子可以发光并且仍然具有相关的几何图形。这也可以用于通过随机选择不同的网格或精灵表示来改变几何图形。这还可用于根据距离从网格过渡到精灵。您可以将不同的参数绑定到不同的渲染器,以允许在模拟中进行细微的变化。例如,您可以为每个渲染器设置不同的位置绑定,以给一个渲染器一个偏移量,但仍然让它跟随另一个渲染器。

网格渲染器允许指定网格数组,并具有网格索引绑定,用于控制从数组中渲染哪个网格。这可以代替多个渲染器,以获得更广泛的网格形状,而无需复制渲染器并设置它们的启用和禁用。可见性标签和网格数组都有相关成本。总的来说,这些应该比使用另一个发射器更好,但在多个发射器或这些策略之间做出决定时,您的项目可能会有不同的性能特征。如果您的项目需要进一步优化,您可能需要比较两者。


池化:内存管理和减少分配

Niagara 函数库允许在通过位置生成系统和附加生成系统时选择池化方法。池化后,基于相同资产的 Niagara 组件不会像平常一样分配和垃圾收集。相反,池中会保留不再使用的已分配组件,并在生成使用相同资产的新组件时重新使用。这避免了频繁使用的组件的分配和垃圾收集成本。

Niagara 系统可以在性能下的系统属性中控制池大小和启动。启动池可以减少运行时分配,但如果资产是动态加载的,则可能导致故障。


模拟成本:优化 Niagara 脚本

GPU 与 CPU

如前文关于发射器数量开销的部分所述,所有 Niagara 模拟都会产生 CPU 开销。选择 CPU 还是 GPU 模拟只会改变粒子模拟的目标,也就是说,只有粒子生成、粒子更新和模拟阶段中的脚本会根据为发射器选择的模拟目标而改变。

粒子脚本具有最大的并行化机会,因此它们从针对 GPU 中获益最多,而且在大多数情况下,GPU 模拟性能更高,并且允许更多粒子。对于粒子数量较少的发射器,CPU 模拟可能更适合,因为 GPU 资源无法如此精细地划分。确切的细分取决于硬件,但 1 个粒子的模拟可能占用与 64 个粒子的模拟相同的资源。 

还要注意的是,在某些项目和某些平台上,GPU 是瓶颈,CPU 模拟可能更合适。这在 GPU 内存较少的平台(如移动设备)上尤其常见。反之亦然,受 CPU 限制的项目仍可能受益于将模拟(即使是粒子数量较少的模拟)移至 GPU。这是在开发项目时验证这些性能假设很重要的众多原因之一。 


其他最佳实践

对项目进行性能分析将为您提供有关项目瓶颈所在位置的最具体数据,这是查找性能问题的最佳方法,但最佳实践可以大大避免在内容创作过程中常见或容易忽略的错误。这些最佳实践是 Epic 特效艺术家在 Fortnite 等项目中长期积累的,代表了我们团队共享的一般建议。此建议也有例外,最终必须根据每个项目做出决定,以确定在哪些方面牺牲性能以换取功能和视觉效果。


固定与动态界限

一般来说,固定边界比动态边界性能更好,因为它需要的工作更少。但是也有例外,例如,一个相对较小但传播距离较大的效果,比如子弹轨迹穿过一个较大的关卡。它的固定边界会比实际视觉效果大得多,但大多数时候效果会超出视野范围,但由于其边界,它仍然可能具有相关性。

除了改变边界类型之外,我们还有 cvar 来减少动态变换更新频率

  • fx.Niagara.EmitterBounds.DynamicSnapValue

  • fx.Niagara.EmitterBounds.DynamicExpandMultiplier

  • fx.Niagara.EmitterBounds.FixedExpandMultiplier


预热

最好避免粒子系统的预热,因为预热中的每一帧都需要按顺序进行评估,并且很容易导致故障。


网格资产清理

简化 Niagara 使用的静态网格资源将使生成和渲染这些网格的性能更佳,而无需更改其几何形状。例如:

  • 从静态网格资产中移除碰撞。

  • 如果不需要阴影,请关闭 Niagara 使用的 LOD 上的“投射阴影”。例如,使用透明材质时。

  • 通过将 LOD 的距离场分辨率比例设置为 0.0 来关闭距离场

  • 确保网格没有多余的 UV 通道。


大量粒子爆发

如果需要创建大量粒子,则在一帧中生成所有粒子可能会导致故障。将生成分散到多个帧可以分散工作量并避免这些故障。


当前帧数据

对于不依赖最新游戏数据的粒子,禁用“需要当前帧数据”将允许 Niagara 尽可能早地在帧中开始其刻度,从而将其工作分散到更长的时间段内。对于不移动或采样移动物体的粒子系统,通常可以禁用此功能,但即使一些移动粒子也可以采样最后一帧的数据并且仍然看起来不错。尝试禁用此标志并查看是否有明显的变化会很有用。


将复杂操作移至堆栈上

对于每个粒子或发射器来说,复杂的工作都是相同的,通常可以将其移至堆栈的上部,这样工作就不会那么频繁地重复。此外,通过读取发射器和系统脚本,与数据接口和 Niagara 参数集合的交互可以提高性能。即使模块工作的全部范围对于每个粒子来说都是不同的,但采样方面通常可以分开,这仍然可以提高性能。


数据接口

与复杂工作类似,发射器和粒子中存在重复的数据接口会占用不必要的内存。如果可以将数据接口移至堆栈中更高的位置,则性能会更高。

作为用户参数的数据接口也会使用更多的内存,因为每个 Niagara 组件都会创建一个新的 UObject,或者每次在现有 Niagara 组件上调用 Set Asset 时都会创建一个新的 UObject。


避免事件

使用属性读取器数据接口的粒子读取通常比事件具有更高的性能,并且通常可以实现相同的行为。

 

排序

默认情况下,排序功能处于禁用状态,但启用后,排序任务默认在 GPU 上运行,这会增加 GPU 的开销,并占用索引缓冲区中的额外内存。这可能会导致绘制性能不佳。

CVars 可以强制 CPU 发射器按 CPU 排序

  • Niagara.GPUSorting.CPUToGPUThreshold

  • Niagara.GPUCulling.CPUToGPUThreshold



近期焦点
通过游戏动画示例项目获取500多种免费动画
UOD Awards 2024 作品征集,启动!
虚幻引擎5.4现已发布
GDC 2024:来自State of Unreal的重大新闻
欢迎来到全新的虚幻引擎网站
我们将在四月下旬更新虚幻引擎、Twinmotion和RealityCapture的定价


扫描下方二维码,关注后点击菜单栏按钮“更多内容”并选择“联系我们”获得更多虚幻引擎的授权合作方式和技术支持;选择“招聘”,即可了解最新招聘信息。

长按屏幕选择“识别二维码”关注虚幻引擎
“虚幻引擎”微信公众账号是Epic Games旗下Unreal Engine的中文官方微信频道,在这里我们与大家一起分享关于虚幻引擎的开发经验与最新活动。


虚幻引擎
Epic Games 旗下 Unreal Engine 虚幻引擎官方订阅号
 最新文章