Unity渲染性能优化总纲

概述

本篇是Unity渲染性能优化官方文档中的渲染性能优化总纲,主要是让我们知道从哪些方面着手优化,都有哪些优化手段。

在优化之前要先定位出问题所在

在我们进行优化之前,要先分析出我们的应用的性能问题出在哪里。如果我们没有找出真正问题所在之前,就直接进行优化,很可能这部分优化工作是无效的,并且甚至可能会让问题更糟。而且,渲染性能问题可能是由CPU或者GPU引起的,对于不同原因引起的性能问题,处理方式也是不一样的,所以在我们进行优化之前一定要找出性能问题的真正原因。

减少CPU在渲染方面的消耗

一般情况下,对CPU渲染性能消耗影响最大的部分是发送渲染命令到GPU,渲染命令包括DrawCall(绘制几何图形的命令),和绘制几何图形之前的渲染状态设置的切换命令。如果是因为这个原因引起的性能问题,可以考虑下面几个操作:

1. 减少需要绘制的对象数量

        a. 减少场景中的对象总数,比如,用天空盒来实现远景效果,这样子就可以减少远景对象
        b. 执行更严苛的剔除,让Unity绘制更少的对象
            i. 使用遮挡剔除来减少被物体遮挡的对象的绘制
            https://docs.unity3d.com/Manual/OcclusionCulling.html
            ii. 减小相机的远裁剪平面距离(far clip plane),这样可以让更多的远处的物体在相机的视野之外,从而不用绘制
            iii. 还有一个更细的方法,就是把对象放到一个单独的层级,然后通过Camera.layerCullDistances设置不同层级的剔除距离
            https://docs.unity3d.com/ScriptReference/Camera-layerCullDistances.html

2. 减少渲染每个对象的次数

        a. 在合适的地方进行光影信息的烘培(预计算),用光照贴图代替实时光照。这会增加构建的时间、运行内存和存储内存,但是可以提高运行时的性能
        b. 如果使用的是前向渲染(Forward rendering),要减少能照射到对象的逐像素实时灯光的数量。
        https://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html
        c. 实时阴影性能消耗很大,所以一定要谨慎有效的使用
        https://docs.unity3d.com/Manual/ShadowPerformance.html
        d. 如果使用了反射探针,要优化使用方法
        https://docs.unity3d.com/Manual/RefProbePerformance.html

3. 减少准备和发送渲染命令的大量工作

    通常是通过更高效的批处理的方式发送渲染命令道GPU来进行优化,也就是我们常说的“合批”
    https://docs.unity3d.com/Manual/DrawCallBatching.html

许多上述中的方法也是可以同时减少GPU的工作,比如,减少一帧内Unity渲染的物体总数同时可以减少CPU和GPU的工作量。

减少GPU渲染消耗

主要有三种情形会导致GPU性能消耗过高

1. Overdraw过高

    即填充率过高,GPU需要绘制的像素过多,可以考虑以下方法:
        a. 减少程序中overdraw重复绘制过高的地方
        大部分时候引起Overdraw的主要因素是透明的对象,比如UI,粒子和Sprites。在编辑器模式下,我们可以通过查看OverdrawDrawMode来找出重复绘制过高的地方
        https://docs.unity3d.com/Manual/ViewModes.html
        b. 减少Shader中片元函数的计算消耗
        片元函数(fragment)是逐像素计算的,减少其中的计算(比如可以的话转移到顶点函数中)可以减少消耗
        https://docs.unity3d.com/Manual/SL-ShaderPerformance.html
        c. 如果我们使用的是Unity的内置shader,尽量的使用Mobile或者Unlit目录下的Shader使用
        这些Shader也能在非移动平台使用,但是经过了简化和更复杂的shader也是比较接近的
        d. 动态渲染分辨率
        Unity支持动态的缩放独立的渲染目标(Render targets)
        https://docs.unity3d.com/Manual/DynamicResolution.html

2. GPU内存带宽不足

    GPU的读写速度有限,需要读写的数据过多,一帧里则处理不了那么多的数据。这通常是因为贴图太多或者太大。这种情形可以考虑以下处理方法:
    https://docs.unity3d.com/Manual/class-TextureImporter.html
        a. 开启贴图的Mipmaps
        mipmap可以使一个对象在运行时使用不同大小的贴图进行显示(在3D场景中,大部分的贴图都可以使用)。开启mipmap会增加一定的内存和存储空间(需要生成不同大小的贴图),但可以提高运行时GPU的性能
        b. 使用合适的压缩格式
        压缩贴图来减少贴图在内存中的大小,可以让加载更快,内存占用更小,并且提高GPU的渲染性能。相比没有压缩的贴图,压缩后的贴图所需的内存带宽也更小。

3. 需要处理的顶点过多

    一帧内需要处理的顶点太多,也会导致GPU性能不足,可以考虑以下方法处理:
        a. 减少顶点函数的计算处理
        类似片元函数,但是这次没地方转移,只能从其它方面入手优化
        https://docs.unity3d.com/Manual/SL-ShaderPerformance.html
        b. 优化模型
        减面,减少不需要的面数,尽可能降低 UV 贴图接缝和硬边(双倍顶点)的数量
        一般来说,移动端不超过10万个顶点
        https://docs.unity3d.com/Manual/ModelingOptimizedCharacters.html
        c. 使用LOD
        https://docs.unity3d.com/Manual/LevelOfDetail.html

减少渲染的频率

我们还可以通过降低渲染的频率的方式来减少消耗,这不会降低一帧的CPU或者GPU的消耗,但减少了渲染的频率,而且不会影响其它操作的执行(比如脚本,因为只是让渲染的频率下降了)。
我们可以在某些时候降低帧率或者整个游戏都降低帧率。降低帧率可以减少不必要的电量消耗,延长电池续航,并且防止设备温度过高,导致CPU被降频。
要调整渲染帧率,我们可以使用OnDemandRendering接口,这个接口特别适合配合Adaptive Performance package一起使用。
https://docs.unity3d.com/ScriptReference/Rendering.OnDemandRendering.html
https://docs.unity3d.com/Packages/[email protected]/manual/index.html
在以下情况,我们可以考虑降低帧率:
    1. 菜单
    比如应用程序入口点或者暂停菜单,菜单往往是相对简单的场景,不需要那么高的帧率
    2. 等待输入的时候
    比如一些游戏在等待玩家输入的时候,比如象棋,玩家花时间等待其他用户操作或者思考自己的操作
    3. 内容大部分时候是静态的
为了防止输入延迟,我们可以在输入持续时间内临时增加渲染帧率(OnDemandRendering.renderFrameInterval = 1),以便移动、按钮等仍可迅速响应
注意:VR应用不支持用OnDemandRendering,因为VR应用需要非常低的延迟,如果渲染的画面跟不上头的运动,就可能增加晕动症出现的风险。

本文

https://blog.csdn.net/ithot/article/details/122520580?spm=1001.2014.3001.5501

参考

https://docs.unity3d.com/Manual/OptimizingGraphicsPerformance.html
另外发现这一篇的中英文差别有点大,Unity的中文文档有些是翻译的,有些会拗口,有些像这篇加了很多自己的理解或者说就是作者的总结,和英文文档偏差较大,也挺令人混乱的
https://docs.unity3d.com/cn/current/Manual/OptimizingGraphicsPerformance.html

扩展阅读

Unity官方性能优化教程
https://learn.unity.com/tutorial/fixing-performance-problems-2019-3/?tab=overview&uv=2019.4
 

猜你喜欢

转载自blog.csdn.net/ithot/article/details/122520580