搜索 Unity

如何在摄像机上优化游戏性能:第二部

2021年10月14日 类别 游戏 | 7 分 阅读
Accelerate Success Logo
Accelerate Success Logo
涵盖的主题
分享

Is this article helpful for you?

Thank you for your feedback!

欢迎来到摄像机优化系列第二篇,第一篇可在此处查看。现在我们将从上次结束的地方开始,扒一扒分析器里的分析结果!

内置渲染管线的性能

在内置渲染管线中,Camera.Render 分析器标记会标出主线程每个摄像机的处理时间。

 Profiler timeline view
分析器的主线程上包含了两个摄像机

每个摄像机都会被标记为一个单独的Camera.Render,而所有测试结果都总结在了下表中。

Time spent processing Cameras on the main thread
主线程处理摄像机的时间(越少越理想)。

在高负荷测试中,我们为每个设备设置了不同的负荷量,让每帧的处理时间不至于太长。高符合测试的可靠性有限,因为额外摄像机的性能成本会被帧的性能变化所掩盖。

Time spent processing Cameras on the main thread
主线程处理摄像机的时间(越少越理想)。

图中的趋势很明显:Camera.Render的处理时间直接受摄像机数量的影响。在第四个场景中,即便新摄像机不渲染任何东西,Camera.Render仍旧会受到影响。

通用渲染管线的性能

在测试通用渲染管线(URP)时,分析器的时间轴上最明显的区别是出现了许多蓝条(脚本),而非绿条(渲染)。绿条表示的是引擎运行C++渲染代码所花费的时间,内置渲染管线所有的渲染代码就是存为了C++。而URP是一种可编程渲染管线,大量的渲染代码都被转移到了C#中,使用者在渲染流程上有着更多的控制权。

Inl_UniversalRenderPipleine.RenderSingleCamera标记的就是摄像机在主线程上的渲染时间。更方便的是,每个标记条的名称会以摄像机名称作为后缀。

Profiler timeline view of the main thread with two Cameras
本图的主线程包含了两个摄像机

然而,如果我们像在内置渲染管线那样标出这些摄像机,测试会不能准确反映URP的总体性能。从上图可以看出,我们还应注意到Inl_Context.Submit标记也花费了大量时间。这一块是绘制命令缓冲的创建时间,这些缓冲在内置渲染管线上被包含在了Camera.Render 标记内。为了让图表更直观,我们只需比对RenderPipelineManager.DoRenderLoop_Internal标记即可,它包含了所有三块渲染相关的标记。

Time spent processing Cameras on the main thread
主线程处理摄像机的时间(越少越理想)。

为了与前者保持一致,我们将测试的负荷量设成了与内置渲染管线测试相同。

Time spent processing Cameras on the main thread
主线程处理摄像机的时间(越少越理想)。

同样的,渲染代码的运行时间也直接受摄像机数量的影响。与内置渲染管线类似,如果添加一个无渲染的新摄像机,Camera.Render仍会受到影响。

到这里,如果你仔细比较内置渲染管线与URP的性能特点,可能会注意到一些奇怪的地方。你看得没错。在高负荷测试中,URP在Galaxy S7 Edge上的渲染效率要比内置渲染管线高得多,但在iPhone机型上则不然。出于篇幅和切题考虑,我们将在另一篇博文中探讨这个问题。

摄像机使用模式反例

我们接着来看看几个多摄像机场景的实例,并讨论其替代方案。

通常来说,将UI画布摆放在Scene视图的场景中心会干扰编辑。部分用户的解决方法是添加一个额外的UI摄像机。摄像机的位置较远,渲染对象则是设置成“Screen Space - Camera”的画布。自Unity 2019版起,Unity编辑器支持在层级视图中显示/隐藏子游戏对象,遮挡场景的画布也可以这种方式进行隐藏。画布也可使用Unity工具栏的Layers下拉菜单来隐藏。

Hiding UI canvases using the Layers drop-down menu
在Layers下拉菜单中隐藏UI画布

也有部分用户借助摄像机为UI画布排序,但摄像机并不是排序用的工具,请使用画布自带的Sort Order或Plane Distance。并且,嵌套的画布还有一个“Override Sorting(覆盖排序)”选项可用于编辑画布的顺序。

我们见过的另一种情况是使用单独的摄像机和剔除遮罩来渲染不同部分的UI,以此来做到界面的显示/隐藏。这里,正确的做法是启用/禁用游戏对象,或使用Canvas组件的启用选项。

最后一个例子与UI无关:有些项目会使用多个摄像机来实现视角的切换。这种情况最为糟糕,当所有摄像机都被启用时,如果确定摄像机的渲染顺序(即Depth字段,用于确定窗口上的主摄像机)并未提前设置妥当,所有的摄像机都会完整地渲染出镜头中的画面,造成极大的性能浪费。这里的解决方法是禁用游戏窗口以外的摄像机。不过,我们仍旧建议在场景中只使用一个摄像机作为当前游戏的主视角。这样就可以避免多个摄像机同时激活的情况出现,还能让摄像机的编辑更为简便。

何时使用多台摄像机

虽然我们建议不要使用多台摄像机,但有时多摄像机是最好甚至是唯一的解决方案。一般来说,如果你需要以下内容,使用多个摄像机可能是正确的选择:

  • 多个摄像机输出。包括多个渲染面(Display、RenderTexture)和矩形视窗。
  • 多分辨率。单个摄像机只能输出一种分辨率的图像。而渲染管线处理中的摄像机数据能以任意的分辨率进行渲染并输出,例如HDRP的Low-Resolution Transparent(低分辨率透明)通道。
  • 多个镜头视角、位置和方向。这些参数确定了视锥剔除的范围。但Unity在渲染XR内容时采用了一些小技巧:两只眼睛接收的图像会由两个相互靠近的摄像机渲染。

这些情况下使用多个摄像头是比较合适的。

在高分辨率的新款(移动)设备上,提高GPU性能的一个常见做法是先以低分辨率渲染场景,然后将其放大成最终分辨率。在这种情况下,许多游戏会在原分辨率下渲染部分UI,并非在高分辨率下渲染,这样可让UI上的精灵和图像更加清晰。此类渲染需要使用一个额外的摄像机,因为单个摄像机只能渲染一种分辨率。

并且镜头或分辨率不同的子图像也需要用多个摄像机渲染。类似的例子有《光环》中的分屏游戏,多个玩家可以独自移动各自的视角。

一张组成场景一部分的动态展牌(billboard)需要使用一张RenderTexture作为纹理,而RenderTexture的生成又需要用上另一个单独的摄像机。

结论

这一次,我们检测了Unity内置渲染管线和通用渲染管线中多摄像机的性能成本。结果清楚地表明,多余的摄像机会产生一定的性能消耗,而我们可以用几种简单的办法来切实提升项目性能。

最后你可能会问,为什么没渲染的摄像机也有这么大的影响?第一个主要的原因是,Unity需要经过大量的计算后才能得知摄像机里其实什么都没有。第二个原因,直接点说,就是Unity并不能很好地应对优化欠缺的摄像机配置。如果要针对这些问题进行优化,原本配置良好的游戏可能会变得更慢,占用的内存可能变得更多,这样就容易“捡了芝麻,丢了西瓜”。

如果你想进一步了解Accelerate Solutions Games团队及其游戏优化服务,可访问我们的主页 ,或联系Unity销售代表来洽谈项目优化方面的合作。 

如果你喜欢Accelerate Success系列内容,请不要错过Accelerate Success网络教学:The Unity UI Makeover的录播,本次教学由Unity的两名团队负责人Andrea和Sebastian主讲。在视频演示中,Andrea和Sebastian将用实例来讲解UI改进的技巧和最佳实践,让你的游戏能运行得更快、更高效。 

2021年10月14日 类别 游戏 | 7 分 阅读

Is this article helpful for you?

Thank you for your feedback!

涵盖的主题
相关文章