英文原文:https://resources.unity.com/games/introduction-universal-render-pipeline-for-advanced-unity-creators?ungated=true
性能高度依赖于您正在处理的项目。 在整个开发周期中始终分析和测试您的游戏。 通过 Window > Analysis > Profiler 打开 Profiler,并按照本章中的建议进行操作。
本节介绍了提高游戏性能的七种方法:
- 管理您的光照
- 光照探头
- 反射探头
- 摄相机设置
- 管线设置
- 帧调试器
- Profiler
本教程也介绍了这些优化。
在 URP 中优化光照和渲染
URP 在构建时考虑了优化的实时照明。 URP 前向渲染器支持每个对象最多 8 个实时灯光,桌面游戏每个摄像头最多 256 个实时灯光,以及移动和其他手持平台的每个摄像头 32 个实时灯光。 URP 还允许在 Pipeline Asset 内对每个对象进行可配置的灯光设置,以对灯光进行精确控制。
正如光照章节中所解释的,烘焙光照是提高场景性能的最佳方法之一。 实时照明可能很昂贵,而烘焙灯可以帮助您恢复性能,假设场景中的灯光是静态的。 烘焙的光照纹理被批处理到单个绘制调用中,无需连续计算。 如果您的场景使用多个灯光,这将特别有用。 烘焙照明的另一个重要原因是它允许您在场景中渲染反弹或间接照明并提高渲染的视觉质量。
全局光照在光照部分也有类似的介绍。 这个过程模拟光线在环境中反弹并用反弹的光照亮附近的其他物体。 下图显示了同一场景的三种光照设置:无烘焙光照数据、烘焙光照和应用后处理。
烘焙时,场景中的阴影区域会接收到反射光并被照亮。 它可能很微妙,但这种技术可以更逼真地在场景周围传播光线并改善其整体外观。
在上图中,您可以看到烘焙时地面上的镜面高光丢失了。 烘焙灯仅包含漫反射照明。 只要有可能,实时计算直接光照贡献,并让全局光照来自基于图像的光照 (IBL)/阴影贴图/探针。
灯光烘焙对阴影的影响:左边烘焙前,右边烘焙后
烘焙灯光时使用尽可能低的光照贴图分辨率和光照贴图大小; 转到Window > Rendering > Lighting > Scene。 这有助于降低纹理内存要求。
设置光照贴图分辨率和最大光照贴图大小
光照探针
如照明部分所述,Light Probes 在烘焙期间对场景中的照明数据进行采样,并允许动态对象在移动或更改时使用反射光信息。 这有助于他们融入烘焙照明环境并感觉更自然。
Light Probes 为渲染添加了自然主义,而不会增加渲染帧的处理时间。 这使得它们适用于所有硬件,甚至是低端移动设备。
渲染动态物体时使用Light Probes的效果:左边有Light Probe,右边没有
反射探针
您还可以使用反射探针来优化您的场景。 反射探针将环境的一部分投影到附近的几何体上,以创建更逼真的反射。 默认情况下,Unity 使用 Skybox 作为反射贴图。 但是通过使用一个或多个反射探头,反射将更接近地匹配其周围环境。
在光滑表面上使用反射探头的效果:左边有反射探针,右边没有
烘焙反射探针时生成的立方体贴图的大小取决于相机与反射对象的距离。 始终确保使用适合您需要的最小地图尺寸来优化您的场景。
调整反射探针立方体贴图的大小
相机设置
URP 使您能够禁用相机上不需要的渲染器进程以优化性能。 如果您在项目中同时针对高端和低端设备,这将非常有用。 禁用昂贵的过程,例如后处理、阴影渲染或深度纹理,会降低视觉保真度,但会提高低端设备的性能。
遮挡剔除
另一种优化相机的好方法是使用遮挡剔除。 默认情况下,Unity 中的相机将始终绘制相机视锥中的所有内容,包括可能隐藏在墙壁或其他对象后面的几何体。 绘制玩家看不到的几何图形是没有意义的,这会占用宝贵的毫秒时间。 这就是遮挡剔除的用武之地。
Occlusion culling 最适合在大量对象出现在它们和相机之间时可能会被遮盖的场景。 蜂窝走廊迷宫类型的游戏是使用遮挡剔除的理想候选者,如下图所示。
左侧图像中的截锥体剔除,右侧图像中的遮挡剔除
通过烘焙遮挡数据,Unity 会忽略场景中被遮挡的部分。 减少每帧绘制的几何图形可显着提升性能。
要在场景中启用遮挡剔除,请将任何几何体标记为 Occluder Static 或 Occludee Static。 遮挡物是可以遮挡标记为遮挡物的对象的中型到大型对象。 要成为 Occulder,对象必须是不透明的,具有 Terrain 或 Mesh Renderer 组件,并且在运行时不能移动。 被遮挡物可以是具有渲染器组件的任何对象,包括在运行时同样不会移动的小而透明的对象。
您可以使用通常的下拉菜单设置静态属性。
遮挡数据中包含的对象的设置
打开 Window > Rendering > Occlusion Culling,然后选择 Bake 选项卡。 在 Inspector 的右下角,按 Bake。 Unity 生成遮挡数据,将数据保存为项目中的资产并将资产链接到当前场景。
遮挡剔除 Bake 选项Tab
您可以使用“可视化”选项卡查看遮挡剔除。 选择场景中的相机并使用场景视图中的遮挡剔除弹出窗口来配置可视化。 弹出窗口可能隐藏在小的相机视图窗口后面。 如果是这种情况,请右键单击双线图标并选择折叠。 移动弹出窗口,然后使用右键单击展开恢复相机视图。
当您移动相机时,您应该会看到物体弹出和关闭。
遮挡剔除的效果在左图关闭,在右图开启
管线设置
虽然之前已经介绍了更改 URP 资产设置和使用不同Quality tiers的效果,但这里有一些额外的提示,用于试验质量层以获得项目的最佳结果:
- 降低阴影分辨率和距离以获得性能提升。
- 禁用项目不需要的功能,例如深度纹理和不透明纹理。
- 启用 SRP Batcher 以使用新的批处理方法。 SRP Batcher 将自动批处理使用相同着色器变体的网格,从而减少绘制调用。 如果场景中有大量动态对象,这可能是提高性能的有用方法。 如果 SRP Batcher 复选框不可见,则单击三个垂直点图标 ( : ) 并选择 Show Additional Properties。
帧调试器
使用帧调试器可以更好地了解渲染过程中发生的情况。 要在 Frame Debugger 窗口中查看其他信息,请使用 URP Asset 调整调试级别。 与 SRP Batcher 复选框一样,这仅在启用了 Show Additional Properties 的 Inspector 中可见。
调整调试级别会影响性能。 不使用帧调试器时,请务必将其关闭。
帧调试器显示在渲染最终图像之前进行的所有绘制调用的列表,并且可以帮助您查明为什么某些帧需要很长时间才能渲染。 它还可以确定为什么您的场景的绘制调用计数如此之高。
通过转到 Window > Analysis > Frame Debugger 打开 Frame Debugger。 玩游戏时,选择启用按钮。 这将暂停游戏并让您检查绘图调用。
单击渲染管道(左窗格)中的阶段将在游戏视图中显示此阶段的预览。
帧调试器在游戏视图中显示渲染过程的每个步骤——在本例中,是 SSAO 生成步骤。
Unity Profiler
与 Frame Debugger 一样,Profiler 是确定在项目中完成一个帧周期需要多长时间的好方法。 它提供了渲染、内存和脚本的概述。 您可以识别需要很长时间才能完成的脚本,从而帮助您查明代码中的潜在瓶颈。
通过 Window > Analysis > Profiler 打开 Profiler。 在播放模式下,该窗口提供游戏整体性能的概览。 您还可以暂停实时取景并使用层次模式来获得完成单帧所需时间的细分。 Profiler 将向您显示 Unity 在该帧中所做的每个调用。
要进行更详细的分析,请使用低级原生插件 Profiler API。 您可以使用此 Profiler API 来扩展 Profiler,并分析本机插件代码的性能,或准备分析数据以发送到第三方分析工具,例如用于 Sony Playstation 的 Razor、用于 Microsoft(Windows 和 Xbox)的 PIX ,以及 Chrome Tracing、ETW、ITT、VTune 或 Telemetry。
下面是一个使用低级原生插件 Profiler API 的示例:
#include <IUnityInterface.h>
#include <IUnityProfiler.h>
static IUnityProfiler* s_UnityProfiler = NULL;
static const UnityProfilerMarkerDesc* s_MyPluginMarker = NULL;
static bool s_IsDevelopmentBuild = false;
static void MyPluginWorkMethod()
{
if (s_IsDevelopmentBuild)
s_UnityProfiler->BeginSample(s_MyPluginMarker);
// Code I want to see in Unity Profiler as "MyPluginMethod".
// ...
if (s_IsDevelopmentBuild)
s_UnityProfiler->EndSample(s_MyPluginMarker);
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
s_UnityProfiler = unityInterfaces->Get<IUnityProfiler>();
if (s_UnityProfiler == NULL)
return;
s_IsDevelopmentBuild = s_UnityProfiler->IsAvailable() != 0;
s_UnityProfiler->CreateMarker(&s_MyPluginMarker, "MyPluginMethod", kUnityProfilerCategoryOther, kUnityProfilerMarkerFlagDefault, 0);
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
s_UnityProfiler = NULL;
}
其他资源
如果您对在 Unity 中构建高级分析技能感兴趣,请先下载免费的电子书,即分析 Unity 游戏的终极指南。 本指南汇集了有关如何在 Unity 中分析应用程序、管理其内存以及从头到尾优化其功耗的高级建议和知识。
Nik 推荐的其他一些有用资源包括 Catlike Coding 的 Measurement Performance 和 Gamedev Guru 的 Unity Draw Call Batching。
完结