面向英特尔® x86 平台的 Unity* 优化指南: 第 3 部分

目录

返回至第 2 部分教程:
面向英特尔® x86 平台的 Unity* 优化指南: 第 2 部分


编辑器优化

遮挡剔除

遮挡剔除是 Unity 的一种特性,可帮助您剔除被摄像头可视范围内其他物体遮挡的物体。我们以奇幻 MMORPG 为例来做简单说明。如果玩家前往一座具有延绵大城的巨大城堡,那么您真的希望将系统资源用于渲染城墙内所有被遮挡住的商店/玩家吗?答案是否定的。遮挡剔除可帮您解决这个问题(图 21)。

Occlusions explained
图 24. 遮挡说明

遮挡剔除可通过整体减少绘制调用的发送来缓解 GPU 的处理压力(如果遮挡剔除计算可相比保存驱动程序调用花费更少的时间,则可能还会减轻 CPU 负载)。 在设置遮挡剔除时,了解 Unity 使用的一些术语会比较有帮助,因为这可以帮助您设置执行剔除的场景。

  • 遮挡物 (Occluder) – 充当屏障的任何物体,可防止对可视范围内被遮挡的物体(被遮挡物)进行渲染。
  • 被遮挡物 (Occludee) - 由于被遮挡物遮挡而无法被渲染到屏幕上的任何物体。

您碰到的大部分物体都有可能会成为被遮挡物或遮挡物,具体取决于摄像头方向和游戏边界。比较值得推荐的做法是,通览全部场景,选择多个应该包含在遮挡剔除计算中的物体,并将其标记为“静态遮挡物 (Occluder Static)”或“静态被遮挡物 (Occludee Static)”。

How to set occluder and occludee in Inspector
图 25. 如何在检视面板中设置遮挡物和被遮挡物

增加遮挡剔除流程的最后一步是烘培场景。

这可通过打开遮挡剔除窗口(位置:Window>Occlusion Culling)来完成。 您将会看到一个如图 20 所示的窗口,其中具有从较高性能 / 较低准确率到较低准确率 / 较高性能的各种不同的调整技巧。 您应该在您的应用中使用“最低有效量”技巧。

The Occlusion window and Bake button
图 26. 遮挡窗口和调整按钮

设置完遮挡剔除系统之后,请认真设置您的遮挡区域。在默认情况下,Unity 将整个场景作为遮挡区域,这可导致没有意义的计算。 为确保不使用整个场景,需手动创建遮挡区域,并环绕仅包含在计算中的区域。

Unity 可支持您形象地看到遮挡剔除系统中的每一部分。 要想查看您的相机卷、可见性线和门户,则只需打开遮挡剔除窗口 (Window > Occlusion Culling) 并点击 Visualization 选项卡便可。 这样您便可形象地看到场景视图中的所有这些要素了。

Occlusion Culling visualization in the scene view
图 27. 场景视图中的遮挡剔除可视化图

更多信息请访问:http://docs.unity3d.com/Manual/class-OcclusionArea.html

LOD:细节级别

细节级别 (LOD) 组件可支持游戏对象在不同的细节级别上转换网格,具体取决于物体与摄像头的距离。 LOD 特性可帮助显著降低一个帧对内存的要求,同时几乎不会对视觉逼真度产生影响。 通过在较低的 LOD 级别上提供较少的几何图形,调整 LOD 可缓解输入装配器和顶点着色器的压力。

您可以通过查看 Unity 分析器来确认 LOD 特性是否已启用。 具体方式为:打开“CPU 使用”分析器,并向下导航至 Camera.Render > Drawing > Culling,然后检查是否显示 “LOD.ComputeLOD”。

Verifying LOD usage in the Unity Profiler
图 28. 在 Unity 分析器中核实 LOD 的使用

您还可以使用 GPA 捕捉一个帧,选择模型相应的绘制调用,然后点击 Geometry 选项卡,进而验证是否启用正确的模型。您将能够借此清晰地看到提交的实际模型的几何图形以及其他有用的统计数据(如顶点数)。您可以验证顶点数是否与在摄像头捕捉距离内使用的理想模型相一致。

细节级别通常取决于顶点。 如果每个顶点需要过多的计算的话,则会阻碍其性能。使用移动版 Unity 着色器可显著减少每个顶点所需的计算。 如果物体偏小或偏远,则可在不需要这些细节时限制 LODGroup 中的顶点数。

To add an LOD component to a game object click Component->Rendering->LOD Group
图 29. 要想为游戏对象添加 LOD 组件,则需点击 Component->Rendering->LOD Group

Adjusting in the LOD Group
图 30. 在 LOD Group 中调整

High Quality
图 31. 高质量

Low Quality
图 32. 低质量


阴影

阴影能够占用大量的 GPU 性能。要想了解阴影所占用的系统资源量,请查看 Profiler > GPU > Shadows 部分。您可以通过多种优化方式来最大限度地提高阴影性能,具体取决于您的场景布局。例如,如果大部分场景阴影因平行光而起,则缩短阴影距离(设置路径:Project Settings > Quality)可显著提升阴影性能。 阴影距离大多与片段着色器的性能紧密相关。在 GPA 帧捕捉中,您可以选择一个从阴影贴图中采样的绘制调用,然后查看片段着色器执行单元的停止/激活指标和采样器的读取/写入指标。阴影距离值可在代码中动态设置。 对于点光灯来说,调整阴影分辨率有助于降低内存带宽开销,因为这在移动网络上成本非常之高。

以下简要介绍了 Project Settings > Quality 提供的每种阴影选项(更多信息请参考《Unity 质量设置指南》):

  • 阴影过滤 – 用于过滤阴影的一种方法
    • 硬阴影 - 当从阴影贴图中采样时,Unity 会选择距离最近的阴影贴图像素
    • 软阴影 - 取几个阴影贴图像素的平均值,创建更平滑的阴影。 这种方法成本更高,但是可以打造更自然的阴影
  • 阴影分辨率 – 生成的阴影贴图的分辨率
    • 如果使用多个点光灯/聚光灯,则会显著影响其性能
  • 阴影投射 – 用于投射阴影的一种方法
    • 稳定 - 渲染分辨率较低的阴影,摄像头移动时不会引起颤动
    • 紧密配合 - 渲染分辨率较高的阴影贴图,摄像头移动时可轻微颤动
  • 阴影级联 – 在级联阴影贴图中使用的平行碎片的数量(距离观者越近的级联分辨率越高,以便提升质量)
    • 可严重影响平行光的性能

Zero Shadow Cascades Enabled.
图 33. 未启用任何阴影级联

Four Shadow Cascades Enabled
图 34. 启用四个阴影级联

  • 阴影距离 – 距离投射阴影的物体的最大距离
    • 如果使用平行光,则会严重影响片段着色器的性能
    • 可通过脚本动态更改

性能结果将会有所变化,因为 GPU 的使用取决于场景以及投射/接收阴影的物体数量。 而有一点始终至关重要,即应该使用所需的最低质量设置来获得理想的外观。 通常建议将默认的阴影距离更改至一个较低的值。

FPS based on shadow distance within Unity Bootcamp demo.
图 35. Unity Bootcamp 演示中基于阴影距离的 FPS。

要想查看 Unity 生成的阴影贴图,您可以捕捉场景的其中一帧,然后在 GPA 帧分析器中进行查看。 前往最终的渲染目标,并导航至 Textures 选项卡查看阴影贴图。

Generated cascaded shadow map as seen in GPA Frame Analyzer
图 36. 生成的级联阴影贴图在 GPA 帧分析器中的视图

坚持使用一个摄像头

有时候为了达成某些特定的效果,使用多个摄像头也能够理解。例如,如果您想创造视差效应,那么其中一种方法便是使用以不同速率移动的多个摄像头。 但您可能没意识到的是,每个摄像头都需要一组独立的 Clear 调用来连接显卡 API 和新渲染目标。如果使用 3 个摄像头和一个 UI 摄像头(canvas 物体需要一个额外的摄像头)从简单场景中捕获其中一帧,则仅 Clear 就会占据 5.4% 的场景。

The draw call timeline associated with a scene with 4 total cameras. Color / depth / stencil clears circled in red.
图 37. 与 4 个摄像头拍摄所得的某一场景相关的绘制调用时间表。红色中的色彩 / 深度 / 模板清除循环。

渲染队列排序

图形编程中有一个概念叫做过度绘制,是指一个像素被不必要地绘制了多次,从而导致显卡资源浪费。 Unity 提供了一种方法来确定不同模型的渲染顺序,即渲染队列属性。渲染队列属性是一个可通过网格渲染器材质进行设置的数值。

为了解该特性的优势,我们来绘制一个上面具有大量物体的地面。 首先对地面进行渲染,确保半个屏幕上的每个像素点都有涉及。 接下来所有物体都将在这个地面上进行渲染。 这产生了许多不必要的工作。 在这个例子中,与任何物体接触的任何像素都被绘制了两次。

A Normal scene with a switchable render queue ordering method (default or smart).
图 38. 通过可切换的渲染队列排序方法(默认或智能)所获得的正常场景。

Overdraw visualization of the same scene with the default render queue ordering mode using GPA System Analyzer.  Grey areas indicate overdraw.  Notice that the floor in the previously shown screenshot is drawn before the floating green quad.
图 39. 在默认的渲染队列排序模式下使用 GPA 系统分析器时,同一场景的过度绘制可视化图。灰色区域表示过度绘制。 注意,之前所示屏幕截图中的地面在形成绿色漂浮方形区之前进行了绘制。

Overdraw visualization of the same scene with the smart render queue ordering mode using GPA System Analyzer.  Grey areas indicate overdraw.  Notice that the only overdrawn section is the floating green quad that extends beyond the floor quad.  With some
图 40. 在智能渲染队列排序模式使用 GPA 系统分析器时,同一场景的过度绘制可视化图。灰色区域表示过度绘制。注意,唯一过度绘制的部分是超出地面方形区的绿色漂浮方形区。通过认真地手动排列问题绘制调用顺序,您可以避免大量的像素计算。

光照贴图

光照贴图是指针对场景中的物体,首次将所有场景灯光烘培到一个从着色器中采样的光照贴图(带有预计算灯光数据的纹理),而非在着色器中动态计算灯光值。在内存带宽 / 采样器的使用都不会成为阻碍的情况下,这种方法可显著提升性能。Unity 可支持您通过这种方式将灯光烘培到场景中。

Unity 还支持您通过使用灯光探测器为动态物体生成烘培的灯光数据。 灯光探测器是您放在场景中的点,可对周围的灯光和阴影条件进行采样。 当一个动态物体经过受灯光探测器限制的区域时,则会对这些灯光探测器产生的数据进行采样。 经过的物体所使用的灯光/阴影值可在所有周围探测器之间进行插值替换。 放在场景周围的探测器能够形成一个三维体,并在动态物体可能覆盖的区域周围更加密集地分散开来。

 Intensity lightmap generated by Unity. (As shown in the GPA Frame Analyzer.)
图 41. 左侧:Unity 生成的平行光照贴图。右侧:Unity 生成的密集光照贴图。(如 GPA 帧分析器所示。)

为烘培灯光数据,请在检视面板(“遮挡剔除”部分所提及的检查框)中将所有静态几何图形标记为静态,并将灯光探测器放在场景周围,形成一个三维体以覆盖即将接收灯光数据的动态物体的所有潜在路线。 物体标记完成并且灯光探测器到位以后,通过 Wndow->Lighting 打开光照贴图窗口,并点击 “Bake Scene” 按钮。

Baking a scene from Lightmapping
图 42. 通过光照贴图烘培场景

您将会在窗口右下方看到一个小型加载进度条。烘培完成之后,便大告成功了!您可以移除/禁用场景中不需要的所有动态灯光,但如果您在检视面板中将灯光标记为“烘培”的话,就不必费此一举了。烘培的灯光将会自动加以应用。跟踪场景中烘培灯光的一种简单方法便是将其全部置于一个空白游戏对象下,以便在需要重新烘培时快速激活/停用。如果您选择这种方式,则请确认您的光照贴图烘培工作流模式未设置为自动模式。

针对复杂模型,使用简单的碰撞器代替网格碰撞器

对于可碰撞的复杂物体来说,使用原型碰撞器组合非常重要,而不是简单地将网格碰撞器投掷在一切之上。 原型碰撞器是一个简单的三维体(容器、球体、盒装等),而网格碰撞器是您试图启用碰撞的网格。 如果可能的话,请选择原型碰撞器,而非网格碰撞器。

Three primitive colliders used for this massive structure. Far greater performance than using the mesh collider.
图 43. 三个原型碰撞器用于这种大型结构。其性能远超网格碰撞器。


继续学习第 4 部分教程:
面向英特尔® x86 平台的 Unity* 优化指南: 第 4 部分

有关编译器优化的更完整信息,请参阅优化通知