前言

本文仅作为性能优化的导读,依靠本文可以了解到一些Unity性能优化的方法,以及学习性能优化需要了解的知识,以此来入门如何性能优化。本文同时提供了很多参考阅读供读者阅读。

关于AOI,可参考我的另外一篇文章

关于Resources System,可参考这篇文章,资源优化中也有更加详细的内容

由于文章太长,性能优化上篇可参考这篇文章

资源优化

资源类型

  • 模型
  • 动作
  • 纹理
  • 声音
  • 字体
  • 场景
    • 地形
    • 光影
  • UI
    • 图集
  • 粒子系统

资源制作规范和确定

注意:下面的标准仅供参考,主要还是美术资源需要有一个标准,每个项目的情况不同也会有不同的优化标准。

Mesh:

动态模型:面片数<3000,材质数<3,骨骼数<50,时长,帧率

静态模型:顶点数<500,UV,LOD

Audio:

长时间音乐(背景音乐): (压缩格式,不经常播放) mp3    压缩方式:Compressed In Memory

短时间音乐(音效): (非压缩格式,经常播放) wav         压缩方式:Decompressed on load

Texture:

贴图长宽<1024

格式要求

Shader:

尽量减少复杂数学运算,减少discard操作。

discard

美术风格:

写实? 像素? 卡通?

视角:

2D/3D/2.5D

固定/自由

场景/地图:

无缝大地图?超大规模?

玩法:

单人/多人

休闲/棋牌/动作/冒险

更多:

unity优化—资源优化

Unity性能优化 - 内存

制作优化

可读写(Read/WriteEnable):

开启后数据在内存中保存两次,GPU一次,CPU一次,因为大多数平台上GPU内存回读的速度极慢,所以将数据从GPU内存读入临时缓冲区以供CPU代码使用

如果不开启则数据内存中只保存一份。

实际开发中可以写一个工具来设置这个选项是否设置正确。

Unity 基础优化 纹理资源Read/Write剖析

纹理压缩:

纹理压缩格式:

  1. ETC:最初是为移动设备开发的格式,如今是安卓标准压缩方案
  2. DXT:原名S3TC,由S3Graphics开发的一种与组块油管的有损算法,又被称为DXTn或者DXTC,主要用于PC。
  3. PVRTC:由Imagination公司专为PowerVR显卡核心设计,一般只用于苹果的设备,部分安卓支持
  4. ASTC:由ARM和AMD联合开发,一种新的压缩格式
  5. Crunch:一种基于DXT或ETC的有损压缩格式,构建慢但是读取快。

平台默认压缩格式:

  1. 安卓:
    1. RGB Compress ETC[RGB 24bit]
    2. RGBA Compress ETC[RGB 32bit]
  2. IOS
    1. RGB Compress PVRTC 4bit
    2. RGBA Compress PVRTC 4bit

如果平台不兼容指定的压缩格式会怎么办?

  1. 对资源进行重新解压为RGBA32(耗时)
  2. 对之前解压的不支持部分和新解压部分都储存(耗内存)

对尺寸有什么要求:

理想状态长宽都是2的幂,则符合POT格式。

如果尺寸不是2的幂,如果平台支持则纹理大小所需内存增加,采样可能比较慢;如果平台不支持,则对纹理进行缩放和填充达到下一个2的幂大小,占用更多内存,加载速度变慢

如何选择:

  1. 根据纹理用途,比如单通道,多通道
  2. 权衡文件的质量和大小(调整ResizeAlgorithm,可参考这篇文章的线性差值部分

模型导入优化:

  1. 模型压缩(在保证可接受的质量的前提尽量选择压缩率高的)
  2. 网格优化(一般可以开启,在网格层面对GPU进行优化)
  3. 可读写(不需要操作模型的时候不用勾选)
  4. LightMap UV(自动为模型生成光照贴图 UV,不需要时不勾选)
  5. 动作导入(模型没动作的时候不用勾选)

动作导入优化:

  1. 动画压缩(减少关键帧进行压缩)
  2. Rig->优化游戏对象(动作的骨骼节点数减少为只有一个子节点)

纹理导入优化:

  1. 导入Unity支持的格式(BMP,TGA,GIF,JPG,PNG等)否则不支持二次处理
  2. 纹理格式(在保证可接受的质量的前提尽量选择压缩率高的)
  3. 制作成符合POT要求的形式(2的幂),否则就是NPOT格式,资源占用大
  4. 可读写
  5. Mipmap(2D的UI不需要开启)
  6. 纹理大小
  7. 压缩选项

UI制作优化:

  1. 能用九宫格就用九宫格
  2. 使用图集

多平台优化:

针对不同平台选定不同的设置比如资源的压缩格式

  1. Standalone
  2. IOS
  3. Android
  4. ......

减少冗余资源与重复资源:

  1. Resources目录下的资源不管是否被引用,都会被打包进安装包,不使用的资源不要放在Resources目录下。
  2. 不同目录下的相同资源文件,如果都被引用,那么也都会被打包进资源包,造成用余应该保证同一个资源文件在项目中只放在一个目录位置。
  3. 关于Resources System,具体可参考这篇文章
  4. 关于重复资源,可以参考Unity游戏性能优化重复资源的危害重复资源如何查找

优化流程的自动化: 快速有效的进行资源监测和优化

继承AssetPostprocessor来制作自动化优化脚本

Unity:资源优化和内存优化

资源监测与分析

  1. 导入资源时进行检查,降低项目冗余度
  2. 使用前面前言中提到的Profiler等性能分析工具和方法
  3. 第三方检测,比如UWA是一家做性能优化的公司,其里面的工具可以对游戏安装包大小和性能做优化。

https://www.uwa4d.com/

https://blog.csdn.net/uwa4d/article/details/73466142

GPU优化

优化方向

  • 减少绘制的数目
    • 保持材质的数目尽可能少。这使得Unity更容易进行批处理。
    • 使用纹理图集(一张大贴图里包含了很多子贴图)来代替一系列单独的小贴图,它们可以更快地被加载,具有很少的状态转换,而且批处理更友好。
    • 如果使用了纹理图集和共享材质,使用Renderer.sharedMaterial 来代替Renderer.material 。
    • 使用光照纹理(lightmap)而非实时灯光。
    • 使用LOD,好处就是对那些离得远,看不清的物体的细节可以忽略。
    • 遮挡剔除(Occlusion culling)
    • 使用mobile版的shader,因为简单。
    • 动静分离(防止面片的重复渲染,其实是GPU优化,当然也减少了dc)
  • 优化显存带宽
    • OpenGL ES 2.0使用ETC1、PVRTC格式压缩等等,在打包设置那里都有。
    • 使用mipmap

Unity优化之GPU优化:https://zhuanlan.zhihu.com/p/47056964

LOD 技术

LOD技术即Levels of Detail的简称,意为多细节层次。LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。

在需要加入LOD的位置创建空物体并增加LODGroup组件,在对应的LODn中的Renderers中加入不同精细度的模型即可实现LOD分层,可通过拖拉鼠标调节每个LOD层级的占比。

https://docs.unity3d.com/Manual/LevelOfDetail.html

遮挡剔除Occlusion Culling

介绍:

只渲染视锥体内的物体,视锥体外或者是椎体后的不渲染。

视锥体剔除能减少顶点和面的个数,从而降低GPU的负担,和CPU的工作量,提高性能。

请注意,如果使用了 LOD 组,则 Unity 会使用静态遮挡物的基础细节级别游戏对象 (LOD0) 来确定要遮挡的对象。

如果游戏对象的轮廓在 LOD0 和其他 LOD 级别之间变化很大,这个游戏对象可能不适合设定为静态遮挡物。

要被设定为静态遮挡物,游戏对象必须满足以下条件:

  • 具有 Terrain 或 Mesh Renderer 组件
  • 不透明
  • 在运行时不移动

遮挡剔除步骤:

  • 选中要渲染的物体,将其Static属性设置:
    • 静态遮挡物 (Static Occluder)(这些游戏对象不会移动,但会阻挡后面的游戏对象)或
    • 静态被遮挡物 (Static Occludee)(这些游戏对象不会移动,但会被静态遮挡物遮挡)
    • 一个游戏对象可以同时是静态遮挡物和静态被遮挡物
  • Camera组件选择好Occlusion Culling选项为真
  • 打开设置面板Window->Render->OcclusionCuling
  • 选中面板的Visualzation,点击Bake.
  • 选中Cameras,点击Bake

官方文档:https://docs.unity3d.com/Manual/OcclusionCulling.html

https://www.bilibili.com/video/BV1qt411i7sC?share_source=copy_web

光照贴图Lightmapping

介绍:

Unity中的光照贴图其实就是把场景中的静态物体做间接光的计算,并把计算结果存储到图片上,这些图片会附在相应的物体上,光照贴图会跟随相应的物体。

Lightmapping实现步骤:

1.首先确认渲染的物体,将其Static属性设置为LightMapStatic

2.设置参与Bake的渲染光源的Mode改为Baked

3.Window->Lighting->Setting->点击Generate Lighting,生成光照贴图

官方文档:https://docs.unity3d.com/cn/current/Manual/lighting-window.html

Mipmap

介绍:

  • 如果纹理过大,会产生远处会出现摩尔纹,近处会出现锯齿,可以使用Mipmap来优化。
  • Mipmap中每一个层级的小图都是主图的一个特定比例的缩小细节的复制品。
  • 因为存了主图和它的那些缩小的复制品,所以内存占用会比之前大。
  • 同时可以根据实际情况,选择适合的小图来渲染。
  • 所以,虽然会消耗一些内存(33%),但是为了图片渲染的质量(比压缩要好),这种方式也是推荐的。

mipmap步骤:

mipmap2

  • 在屏幕空间中取当前像素相邻的像素并查询其对应的uv坐标。
  • 计算出当前像素点与其他像素点距离的最大值L。
  • 根据最大值L通过上面公式计算得到该点所处的层数D。

https://www.lengyueling.cn/archives/37

什么时候用?

纹理在场景中是否有深度变化?

  1. 有变化:各种模型
  2. 没变化:游戏UI、SkyBox

有深度变化的情况按情况使用:

深度变化细微则不需要启用,如果深度变化打则可以使用

OverDraw

减少OverDraw区域:http://t.csdn.cn/mUjzx

介绍:

  • 单位像素在单位时间内,被多次渲染
  • UWA分析报告中,以总填充总数来表达一帧内渲染的像素数量,过多Overdraw可能会引起GPU过载,影响动画的播放和界面响应速度。

减少OverDraw: 优化OverDraw的方向就是尽可能的减少不同UI的重叠区域

  • 使用rect mask 2d代替mask组件,因为mask组件自带2层overDraw
    • Mask合批规则:mask内的元素可以和mask内的其他元素进行合批,不能和非mask元素进行合批
    • 之所以不能合批,是因为不同的材质不能合批,mask用的是stencil模板材质,非mask用的是default uimat材质
    • rectmask2d合批规则:只能合批自己遮罩范围内的ui对象,不会像mask一样额外生成两个drawcall
    • 本质区别:mask是通过gpu模板剔除实现,rectmask2d是通过cpu顶点剔除实现的,因此如果当前GPU瓶颈,反而需要使用mask而不选择retmask2d
  • 使用Text组件的OutLine和Shadow,Shadow会增加一层OverDraw,而OutLine是复制了四份Shadow实现的
  • 对于弹出窗口,位于底层的窗口如果被上层遮挡,请将它从Camera渲染层级里移除并将不可见的Canvas设置enable = false,不在Camera渲染层级里的Canvas.enable = true,它下面的UI仍然会产生OverDraw
  • UI上的特效粒子,尽量简单,如果可以请用序列帧动画实现
  • 不使用空白或透明的Image,尽管alpha = 0,还是会渲染并增加一层OverDraw
  • CanvasGroup中Alpha=0 不参与绘制,没有drawcall和overdraw,顶点不会参与重建,而SetActive会把他的顶点和材质弄成脏标记,会导致重建(Canvas 和 Canvas Group:https://www.jianshu.com/p/3a32e01a0bb1

编译优化

Unity3D研究院新方法加快代码编译速度:https://www.xuanyusong.com/archives/4474

Unity的程序集Assembly与加快代码编译速度:https://blog.csdn.net/u012685888/article/details/121747831

内存优化

内存占用组成

  • Unity(native堆,unity资源)
    • 纹理Texture
      • 大小
      • 格式
      • mipmap
      • 压缩
      • 图集
    • 网格Mesh
      • 顶点数
      • 骨骼数
      • 压缩
      • 合批
    • Animation
      • 长度
      • 关键帧数量
      • 压缩
    • Shader
    • Font
    • ......
  • Mono(写的C#代码,注意GC)
  • GfxDriver(显卡驱动,渲染时使用的纹理材质Shader等)
  • FMOD(Unity使用的音频引擎资源)
  • Profiler(性能分析器本身也会占用内存)
  • ......

内存GC

优化要点:

  • 逐一定位,逐一分析
  • 避免频繁的对象创建
  • 尽量避免装箱拆箱
  • 善用缓存
  • 使用对象池
    • 内存(逻辑对象)对象池
    • 游戏物体对象池

关于GC,可以参考我的另外两篇文章: