unity 性能优化方案

1、优化流程

优化是指选择一个应用程序并使其更有效率的过程。对于图形应用程序,这通常是指对应用程序进行修改,使其运行更快。
优化流程包含下列步骤: 
a. 使用分析器测量应用程序。 
b. 分析数据,找到瓶颈。 
c. 确定要运用的相关优化。 
d. 验证优化是否成功。 
e. 如果性能不可接受,请返回至 a ,然后重复该流程。

 

2、Unity 质量设置 

Unity 包含许多可以改变游戏图像质量的选项。部分选项计算量较高,会对游戏性能产生不利影响。 
下图显示了检视面板中的质量设置: 

 

有许多选项可以提高游戏图像质量,代价只是极小幅度地降低性能。

例如,如果游戏的帧率较低,GPU 可能正在处理过多执行复杂图形效果的信息。

可以执行较简单版本的图形效果,例如阴影或光照。

相比而言,这对图形质量产生的影响较小。更简单的效果可以显著降低 GPU 负载,从而提供更高的帧率。 
光照默认设置有时对于移动设备而言过于复杂,因此针对移动平台编写的部分游戏应避免复杂的技术,或者根据每个游戏使用相应的技术。这可能涉及将光照预烘焙为光照贴图的技术,或者用投影纹理代替投射阴影的技术。 

 

在QualitySettings中,有许多可以对游戏性能产生巨大影响的选项: 

a、像素光源数量 
像素光源数量是指可以影响给定像素的光源数量。较高的像素光源数量需要执行大量计算。大部分游戏能够在使用极少量动态实时光源的同时,最大限度降低对质量的影响。如果光照引发了性能问题,请考虑在游戏中使用光照贴图和投影纹理等技术。 

 

b、纹理质量 
纹理质量可以给 GPU 带来负载,但通常不会引发性能问题。降低纹理质量会对游戏的视觉质量产生不良影响,所以请只在必要的情况下降低纹理质量。在冰穴演示中,纹理质量设为全分辨率。 
如果纹理引发了性能问题,可尝试使用纹理映射。纹理映射可降低计算和带宽要求,同时不会影响图像质量。

 

c、抗锯齿 
抗锯齿是一项边缘平滑技术,该技术混合了三角形边周围的像素。这显著提高了游戏的视觉质量。有多种抗锯齿方式,但是此种情况下采用的是多重采样抗锯齿 (MSAA)。4x MSAA 在 Mali GPU 上的运算量较低,应尽可能使用。 

 

d、软粒子 
软粒子需要渲染到深度纹理或在延迟模式下渲染。这会提高 GPU 负载,但可以获得逼真的粒子效果,因此值得采用。在移动平台上,渲染到深度纹理和从深度纹理读取会消耗掉宝贵的带宽,并且使用延迟路径进行渲染意味着你不能使用 MASS。请考虑软粒子是否足够重要到需要在游戏中使用。

 

e、各向异性纹理 
各向异性纹理技术可消除在高梯度下绘制的纹理的失真。这项技术可提高图像质量,但是非常消耗资源。除非失真特别明显,否则请避免使用此技术。 

 

f、阴影 
阴影具有高质量时,计算量较大。如果阴影引发了性能问题,请尝试采用简单的阴影或关闭阴影。如果阴影对于游戏非常重要,请考虑使用简单的动态阴影技术,例如投影纹理。 
 

g、实时反射探测器 
实时反射探测器选项对运行时性能存在显著的负面影响。 
在渲染反射探测器时,立方体贴图的每一面都由探测器原点处的摄像机进行单独渲染。如果考虑相互反射,此过程会在每个反射反弹级别进行一次。在光泽反射情形中,立方体贴图纹理映射也用于应用模糊处理。 

h、剔除遮罩 
在渲染立方体贴图时使用剔除遮罩,从而避免对反射中任何无关几何体进行渲染。 
 

3、应用程序分析

分析工具:
a、Unity Profiler
b、Unity Frame Debugger
c、ARM Mali Graphics Debugger
d、ARM DS-5 Streamline

Unity Profiler以一系列图表的形式提供详细的每帧性能数据,帮助你查找游戏中的瓶颈。 
点击Unity Profiler的一个图表,就会看到垂直切片。如果选择某个单帧,就可以在屏幕底部的显示面板中读取该帧的信息。如果在没有修改所选帧的情况下点击另一图表,面板将显示已选择的分析器的数据。 

 

Profiler.BeginSample() 和 Profiler.EndSample() 方法
Unity 分析器可让你采用 Profiler.BeginSample() 和 Profiler.EndSample() 方法。你可以在脚本中标记一个区域,然后附上自定义标签,此区域将作为单独的条目出现在分析器层级中。通过执行此操作,可以获取特定代码的信息,而无需采用深度分析选项,从而节省计算和内存开销。例:

1

2

3

4

5

Void Update(){

    Profiler.BeginSample(“ProfiledSection”);

    […]

    Profiler.EndSample();

}

 

Frame Debugger 是一款分析工具,可以在每一帧基础上追踪绘制调用。 
Frame Debugger 可以从窗口菜单中选用。 
左窗格中显示该帧中发出的绘制调用树。 
右窗格中显示与选定绘制调用相关的其他信息,如几何体详情以及绘制它的着色器等。 
下图显示了 Frame Debugger 中的 Phoenix 对象:

如果摄像机渲染到所选绘制调用的目标,可以在游戏视图中查看被渲染纹理的视觉呈现。
在一个场景中,对象渲染顺序对性能非常重要。
如果按照任意顺序渲染多个对象,则可能会出现一个对象在渲染之后被其前面的另一对象遮挡。也就是说,渲染被遮挡对象需要的计算全都浪费。
利用 Unity Frame Debugger 可以查看渲染顺序。

 

4、CPU优化列表之使用协程代替 Invoke()

 

Monobehaviour.Invoke() 方法可快速便捷地在时间延迟的情况下调用类中的方法,但存在以下局限性: 
a. 它使用 C# 反射查找调用方法,这比直接调用方法的速度更慢。 
b. 没有针对方法签名的编译时检查。 
c. 无法提供附加参数。 
下列代码显示了 Invoke() 函数:

1

2

3

4

Public void Function(){

    […];

}

Invoke(“function”, 1.0f);

替代方法是使用协程。协程是 IEnumerator 类型的函数,可以使用特殊 yield return 语句将控制权归还给 Unity。可以稍后再次调用函数,它将从之前中断的位置恢复运行。 
可以通过 MonoBehaviour.StartCoroutine() 方法调用协程:

1

2

3

4

5

Public void Ienumerator Function(float delay){

    Yield return new waitForSeconds(delay);

    […];

}

StartCoroutine(Function(1.0f));

从 Monobehaviour.Invoke() 方法转为使用协程,可以在传递至处理动画状态的函数的参数上提供更高的灵活性。 

 

5、CPU优化列表之删除空回调函数 

如果代码包含 Awake()、Start() 或 Update() 等函数的空定义,则将其删除。这会产生不必要的开销,因为引擎在函数为空时仍会尝试访问它们。

 

6、CPU优化列表之避免每帧使用 GameObject.Find()

GameObject.Find() 函数用于循环访问场景中的每个对象。如果它在代码中使用的位置不正确,则会导致主线程大小显著增加。
更好的做法是在启动时调用 GameObject.Find() 并缓存结果,将结果缓存在 Start() 或 Awake() 函数中。

 

7、CPU优化列表之使用 StringBuilder 类连接字符串 

连接复杂字符串时,请使用 System.Text.StringBuilder 类。其速度远快于 string.Format() 方法,并且使用的内存少于通过加号运算符进行连接时所用的内存。
 

8、CPU优化列表之使用 CompareTag代替标记属性 

使用 GameObject.CompareTag() 方法代替 GameObject.tag 属性。CompareTag() 方法的速度更快,并且不会分配额外的内存。
下图显示了 CompareTag() 的用法: 

 

9、CPU优化列表之使用对象池 

如果游戏有许多同类对象在运行时创建和破坏,则可以使用设计模式对象池。该设计模式可避免在动态分配和释放众多对象时产生性能损失。 
如果知道所需对象的总数,则可以直接创建所有对象,并禁用暂时不需要的对象。需要新对象时,请搜索首个未用对象的池并启用该对象。 
不再需要某个对象时,可以将其放回至池中。这意味着将对象重置为默认开始状态并禁用该对象。 
此技术可以与敌人、抛射物和粒子等对象结合使用。如果不知道所需对象的准确数目,则进行测试,找出使用的对象数并创建一个数目稍大于此数的对象池。 

10、CPU优化列表之缓存组件检索

 

缓存 GameObject.GetComponent() 返回的组件实例。涉及的函数调用非常消耗性能。 
Gameobject.camera、Gameobject.rendener 或 Gameobject.transform 等属性是对应 GameObject.GetComponent()、Gameobject.GetComponent() 和Gameobject.GetComponent() 的快捷方式。
考虑缓存 Transform.position 的返回值。即便它是 C# getter 属性,也会在用于计算全局位置的转换层级上产生与迭代相关的开销。 
Unity 5 及更高版本会自动缓存转换组件。

 

11、GPU优化列表

 

a. 使用静态批处理

静态批处理是一种常见的优化技术,可以减少绘制调用数量,从而降低应用程序处理器的使用率。 
动态批处理可由 Unity 以透明的方式执行,但是无法运用至大量顶点组成的对象,因为计算开销过大。 
静态批处理可在大量顶点组成的对象上运行,但是经过批处理的对象在渲染过程中不得移动、旋转或扩大。 
若要使 Unity 能够集合要进行静态批处理的对象,请在“检视面板”中将它们标记为静态。

 

b. 使用细节层次
Unity 引擎可以使用细节层次 (LOD) 技术根据与摄像机的距离渲染同一对象的不同网格。 
当对象更接近摄像机时,几何结构更为清晰。随着对象远离摄像机,细节层次降低。当处于最远距离时,可以使用平面公告板。 必须恰当地设置 LOD 组,以管理要使用的网格以及相应的距离范围。 要访问 LOD 组的设置,请选择:添加组件 > 渲染 > LOD 组。 
在 Unity 5 中,可以设置渐变模式使每个 LOD 层次混合为连续的 LOD。这可以平滑它们之间的过渡。Unity 可以根据对象的屏幕大小计算混合因子,并将它传递到着色器以进行混合。必须在着色器中实施几何体混合。

 

c. 光照贴图和灯光探测器 
运行时光照计算的计算成本很高。一项用于降低计算要求的常见技巧称为光照贴图,它预先进行光照计算并将它们烘焙为名为光照贴图的纹理。 
这意味着会丧失完全动态光照环境的灵活性,但可以生成质量非常高的图像,而不会影响性能。 
在静态光照贴图中烘焙生成的光照

  • 将接收光照的几何体设置为静态。 

  • 将灯光中的烘焙选项设为已烘焙,而不是运行时。 

  • 在光照贴图窗口的“场景”选项卡中,选中已烘焙 GI 选项。 

查看生成的光照贴图:

  • 选择几何体。 

  • 选择窗口 > 光照,以打开光照窗口。 

  • 按对象按钮。 

  • 选择预览选项中的烘焙强度光照贴图。

如果选择了持续烘焙选项,Unity 将烘焙该光照贴图,并在几秒后更新编辑器中的场景。 
若要快速检查光照贴图设置是否正确,可在编辑器中运行游戏,并禁用光源。如果光照仍在,则光照贴图已经正确创建并在使用中。 

使用定向光照贴图:
如果无法针对双重光照贴图使用延迟光照,则另外一种方法是使用定向光照贴图。这能够使你在没有实时光照的情况下使用法线贴图和镜面反射光照。
如果必须保存法线贴图但未提供双重光照贴图,则可使用定向光照贴图。移动设备通常就属于这种情况。

针对游戏中的动态对象使用灯光探测器:
可以使用灯光探测器向进行光照贴图的场景添加一些动态光照。 
下图显示了灯光探测器设置:
 

 

d. ASTC 纹理压缩 

不要在构建设置中以一种格式压缩所有纹理。使纹理压缩保持为请勿覆盖。 
在项目层级中查找纹理并使其显示在检视面板。Unity 通常会以纹理类型导入纹理。该类型仅为压缩提供一定数量的选项。将类型设为高级可显示更多选项。 
下图显示了具有一定透明度的 GUI 纹理的设置。此纹理适用于 GUI,因此 sRGB 和纹理映射已被禁用。若要包含透明度,则需要 alpha 通道。为此,请选中 Alpha 透明方框和覆盖 Android 方框。 
下图显示了高级纹理设置

 

 

e. 纹理映射

纹理映射技术与能够同时提高游戏视觉质量和性能的纹理相关。 
纹理映射是不同大小的纹理的预计算版本。每个生成的纹理称为一个层级,它们的宽度和高度是前一个纹理的一半。Unity 能够自动生成完整的层级,从原始尺寸的第一层级到 1x1 像素版本。 
若要生成纹理映射,需要执行以下操作: 

  • 在项目窗口中选择某一纹理。 

  • 将纹理类型更改为高级。 

  • 在检视面板中启用生成纹理映射选项。

 

下图显示了纹理映射设置:

如果纹理没有纹理映射层级,当具有纹理的表面覆盖的区域(以像素表示)小于纹理尺寸时,GPU 会将纹理缩小至适合更小的区域。但是,此过程中会丧失部分准确性,即便使用滤波器插值像素颜色。 
如果纹理具有纹理映射层级,GPU 将从最接近对象大小的层级中提取像素数据以渲染纹理。这可提高图像质量并降低带宽,因为 GPU 为获得更高质量已经离线扩展了层级,并且 GPU 仅从恰当的层级中提取纹理数据。多级渐进纹理 (mipmapping) 的劣势在于它额外需要 33% 的内存来存储纹理数据

 

f. 阴影

 

阴影有助于增加场景的透视度和真实感。没有阴影,有时很难告知对象的深度,尤其是它们与周围对象相似时。 
阴影算法可能会非常复杂,渲染高分辨率的精确阴影时尤为如此。请确保在游戏中为阴影选择了相应级别的复杂度和分辨率。 
Unity 支持转换反馈,实现了对实时阴影的计算。
Unity 的Edit > ProjectSettings> Quality下包含多个阴影选项,它们可影响游戏的性能: 

  • 硬阴影/硬加软阴影 
        软阴影看起来更为真实,但是计算时间较长。


  • 阴影距离 
        阴影距离选项可定义与出现阴影的摄像机的距离。增大阴影距离会增加可见阴影的数量,从而加大计算量。增大阴影距离还会增加用于阴影贴图中阴影的像素元数量,从而被动地提高阴影分辨率。 

可以使用阴影距离较小且分辨率较高的硬阴影。这会在距离摄像机的适当范围内产生不是很复杂且质量较高的阴影。 
进行光照贴图的对象不会产生实时阴影,在场景中烘焙的静态阴影越多,GPU 执行的实时计算就越少。
 

实时阴影可大幅提高场景的真实度,但是它们的计算量非常大。 
在移动平台上,请尝试限制仅包含实时阴影的光源数量,并尝试使用光照贴图。 
请考虑使用场景对象的网格渲染器组件。如果不想使用它们投射或接收阴影,请相应地禁用投射阴影和接收阴影选项。这可降低渲染阴影的计算量。 
可以在质量设置部分找到更多阴影设置,例如: 

  • 阴影分辨率:可让你选择质量和处理时间之间的平衡值。 

  • 阴影距离:可限制距离摄像机较近的对象生成的阴影。 

  • 阴影级联:可让你选择质量和处理时间之间的平衡值。可以将它设置为零、二或四。级联阴影贴图用于定向光源,可获得非常好的阴影质量,尤其是视距较远时。级联数越高,质量越好,但会增加处理开销。 

你可能感兴趣的:(unity)