在Unity性能优化之场景资源优化篇里,主要对场景资源内存的优化,下面介绍一些常用的优化方法。总之性能优化是有利也有弊的,总是牺牲一个方面,去成全另一个方面。可根据项目的具体情况选择合适的优化方案。
1.场景的静态合批
静态合批的主要作用是将多个静态物体(在运行时不会移动、旋转或缩放的物体)的网格合并为一个更大的网格,从而减少DrawCall的数量,提高渲染性能。合批方法为将Static里的BatchingStatic勾选上,如下图:
静态合批的条件:
(1)物体标记为(静态)Static状态
(2)相同材质
(3)共享顶点格式,合批的网格需要具有兼容的顶点格式。例如,如果一个网格具有顶点颜色信息,而另一个没有,它们可能无法合批。
(4)未发生变换,在游戏运行过程中,被合批的物体不能移动、旋转或缩放。
静态合批的缺点:
(1)内存增加,由于将多个物体的网格合并为一个,可能会导致合并后的网格数据变大,从而增加内存的占用。
(2)灵活性受限,合批后的物体在运行时不能单独进行移动、旋转或缩放操作,这在某些需要动态变化的场景中会限制设计的灵活性。
(3)材质共享限制,要求参与合批的物体使用相同的材质,如果为了合批而强行统一材质,可能会损失一些视觉效果的多样性。
2. 场景的动态合批
动态合批是一种在运行时自动合并小型网格物体的技术,以减少 DrawCall 数量来提高性能。动态合批的工作原理是在每一帧中,Unity 会检测可以合并的小型动态物体(可以移动、旋转或缩放),并将它们的网格组合在一起进行渲染。所以Unity会帮我们进行处理。
动态合批的优点:
(1)实时优化:能够在运行时根据物体的状态和位置自动进行合批,无需提前设置。
(2)灵活性:适用于会移动、旋转或缩放的物体。
动态合批的缺点和限制:
(1)顶点数量限制:每个合批的物体顶点总数不能超过一定数量(通常是 900 个顶点)。
(2)材质限制:合批的物体必须使用相同的材质。
(3)增加 CPU 负担:动态合批需要在每一帧进行计算和判断,可能会增加一定的 CPU 开销。
3. 启用GPU Instancing(GPU 实例化)
在 Unity 中,GPU Instancing(GPU 实例化)是一种用于优化渲染大量相同或相似物体的技术。通过在GPU端一次性处理多个相同网格和材质的物体实例,大大减少了CPU向 GPU发送的指令数量(DrawCall),从而显著提高渲染效率。
优点:
(1)性能提升,减少DrawCall
(2)减少内存占用:多个实例可以共享相同的网格数据和材质,避免了重复存储,节省了内存。
(3)灵活性:支持物体的变换(位置、旋转、缩放)以及一些材质属性的变化。
例如,在一个森林场景中,大量相同类型的树木可以通过 GPU Instancing 进行高效渲染。
缺点:
(1)材质和网格要求:物体需要使用相同的网格和材质,虽然可以有一些材质属性的变化,但有一定的限制。
(2)图形 API 支持:并非所有的图形 API 和设备都能完全支持 GPU Instancing,需要考虑兼容性。
(3)复杂的材质计算:某些复杂的材质计算可能不适合 GPU Instancing,或者需要特殊处理。
4.使用遮挡剔除技术(Occlusion Culling)
遮挡剔除的核心思想是在渲染场景时,不渲染那些被其他物体完全遮挡住的物体。
在使用时需要对游戏物体进行Static处理,可根据实际情况进行选择勾选某项,如下图:
使用OcclusionArea组件设置遮挡剔除的范围,当摄像机处于该区域时才会触发遮挡剔除的效果,设置完后需要进行烘焙Bake。
使用Occlusion Portal组件可以控制是否启用遮挡剔除的功能。
遮挡剔除的缺点:
(1)内存占用:遮挡数据会占用一定的内存。为了进行遮挡判断,Unity 需要存储关于场景中物体的遮挡关系和相关数据。这些数据可能包括物体的包围盒信息、层次结构以及可见性状态等,这都需要一定的内存来保存。
(2)预处理开销:生成遮挡数据的预处理过程可能较为耗时,尤其对于大型和复杂的场景,这可能会增加开发时间。
5.光照的优化
(1)控制光源数量:尽量减少场景中的光源数量,只保留必要的光源。过多的光源会增加计算复杂度。
例如,如果可以通过一个点光源和环境光达到相似的效果,就避免使用多个点光源。
(2)选择合适的光源类型:根据场景需求选择合适的光源类型。例如,对于大面积的照明,使用方向光可能更合适;对于局部照明,使用点光源或聚光灯。
比如,模拟太阳光时使用方向光。
(3)烘焙光照:对于静态物体,可以使用光照烘焙技术将光照信息存储在纹理中,减少实时计算。
在室内场景中,将静态的灯光效果烘焙到纹理上,可以显著提高性能。
(4)调整光源参数:合理设置光源的强度、范围、衰减等参数,避免过亮或过暗的区域。
比如,对于一个小房间的灯光,调整其范围和强度以获得均匀的照明。
(5)利用 Light Probes(光照探针):在动态物体经过光照变化较大的区域时,使用光照探针来获取近似的光照信息,减少实时计算。
例如,在角色移动经过不同光照区域时,通过光照探针提供平滑的光照过渡。
(6)优化材质:使用对光照计算效率高的材质,避免使用复杂的光照模型。
某些简单的材质可能不需要复杂的光照计算就能达到较好的视觉效果。
(7)阴影优化:调整阴影的分辨率和距离,避免过高的质量设置。
例如,对于远处的物体,可以使用较低分辨率的阴影。
6.MipMap
Mipmap 的主要原理是为原始纹理生成一系列逐渐缩小的版本。当物体在屏幕上所占的像素较少时(即距离摄像机较远),Unity 会自动选择使用较小的 Mipmap 级别来渲染纹理,从而减少了采样时的计算量和可能出现的走样现象。
说白了就是会根据摄像机到场景中图片的距离大小,来显示不同清晰度的图片,距离越近显示的图片越清晰,距离越远显示的图片越模糊。
MipMap的缺点:
(1)增加内存占用:因为需要存储不同清晰度的纹理。
(2)可能导致模糊:在某些情况下,特别是当物体在两个 MipMap 级别之间切换时,可能会导致纹理看起来稍微有些模糊。
7.LOD
在Unity中,LOD(Level of Detail,细节层次)是一种用于优化渲染性能的技术。
LOD的核心概念是根据物体与摄像机的距离或屏幕上所占的像素大小,使用不同细节程度的模型来表示同一个物体。也就是说会根据摄像机与游戏物体的距离远近,来显示不同的清晰度模型。
使用时,为一个物体创建多个具有不同细节级别的模型,从高细节到低细节。
在运行时,根据设定的条件(如距离、屏幕占比等),Unity 自动切换使用相应的LOD 模型。
LOD缺点:
(1)增加内存:需要为一个模型创建好多种不同细节级别的模型。
(2)视觉过渡问题:在不同LOD级别之间切换时,如果处理不当,可能会出现明显的视觉跳跃。
8. AssetBundle加载资源的优化
使用AssetBundle加载资源后要及时的卸载资源,避免占用资源内存。
AssetBundle.Unload(false):内存中的AssetBundle对象包含的资源会被销毁。
AssetBundle.Unload(true):不仅仅内存中的AssetBundle对象包含的资源会被销毁。根据这些资源实例化而来的游戏内的对象也会销毁。
版权归原作者 清秋Ccc 所有, 如有侵权,请联系我们删除。