Unity项目优化
相关概念
- Drawcall:CPU对底层图形程序的调用
- Fragment:有可能成为像素的东西,即潜在的像素
- Batching:将批处理前需要多次调用Drawcall的物体合并
- 内存的分配:Unity的内部内存和Mono的托管内存
优化方向
CPU方面
1. Drawcall
思路:减少渲染次数,多个物体一起渲染
方法:Draw Call Batching批处理
- 需要批处理的物体使用同一材质,可以将多种纹理打包成图集
- 使用静态批处理或动态批处理
2.1. Static Batching静态批处理(推荐使用)
批处理静止的,在游戏中永远不会移动、旋转、缩放的物体。勾选Inspector中的Static复选框即可。
2.2. Dynamic Batching动态批处理(约束比较多)
动态批处理是引擎自动执行的。 - 仅支持小于900顶点的网格物体;
- 若着色器使用顶点位置、法线和UV,只能处理300顶点以下的物体;若使用顶点位置、法线、UV0、UV1和切向量,只能处理180顶点以下;
- 尽量不要使用缩放。Scale(1,1,1)与(2,2,2)的物体将不进行批处理,但Scale(1,2,1)和(1,3,1)可以批处理;
- 统一缩放的物体不会和非统一缩放的物体进行批处理;
- 使用不同材质的实例化物体将使批处理失败;
- 拥有lightmap的物体将不进行批处理;
- 多通道的shader会妨碍批处理;
- 预制体的实例化会自动使用相同的网格模型和材质;
- 运行后,点击Stats查看批处理效果
2. 物理组件
思路:减小每一帧的执行检测的开销
方法:
- 设置合适的Fixed Timestep:即合适的物理计算频率
- 尽量不适用mesh collider组件
3. 内存
思路:不要频繁触发GC
原因:GC是Mono运行时的机制,管理Mono的托管堆,不处理引擎的内存释放
方法:
- 减少字符串连接的处理
- 用for语句代替foreach语句
- 不要直接访问gameobject的tag属性,换成
if(go.CompareTag("cube")){}
- 使用“池”
- 最好不用LINQ,它们会分配临时空间
4. 代码质量
方法:
- 只访问一次Transform,之后将它的引用保留
- 不要频繁使用GetComponent,尤其在循环中
- 使用OnBecameVisible()和OnBecomeInvisible()来控制物体的update()函数的执行开销
- 使用内建数组
- 使用ref
GPU方面
1. 减少绘制的面数
- 材质的数目尽量少
- 使用纹理图集
- 用Render.sharedMaterial代替Render.material
- 用lightmap代替实时光
- 使用LOD,忽略远处的细节
- 遮挡剔除(Occlusion culling)
- 使用mobile版的shader
2. 优化显存带宽
- OpenGLES2.0用ETC1格式压缩
- 使用Mipmap存储图片
内存方面
Unity的内存内存分布
- Unity内部内训:位Unity3D的底层代码所分配的内存
- Mono:即托管堆。Mono运行时在运行游戏脚本时所需要的内存,这部分内存是有GC的。
- GfxDriver:GPU显存开销,尽可能地减少或释放Texture和mesh等资源,即可降低GfxDriver内存。
- FMOD:音频的内存开销
使用Unity Profiler工具检测内存
Window - Anlysis - Profiler