🚀 Unity 性能优化完全指南:从入门到大师的优化体系

💡 性能优化的价值

  • 游戏帧率上不去,玩家体验差?
  • 不知道从哪里开始优化,感觉无从下手?
  • CPU、GPU、内存、UI,到底该优先优化哪个?
  • 工具一大堆,不知道该怎么配合使用?

这篇文章! 将建立完整的 Unity 性能优化体系,从宏观指标到具体工具,从优化策略到团队规范,助你系统掌握性能优化!


一、优化资源

1.1 官方资源

资源类型 链接 说明
Unity UPR upr.unity.cn Unity 官方性能优化工具
Unity 官方 developer.unity.cn 性能专题文档
Unity Learn learn.u3d.cn 移动游戏优化教程
Unity 文档 docs.unity3d.com/cn/current/Manual/analysis.html 分析器文档
优化视频 Bilibili BV1RQ4y1C7v8 电子游戏优化终极指南

1.2 第三方资源

资源 链接 说明
UWA 官方 uwa4d.com 专业的性能优化服务
UWA 优化视频 百度网盘 (提取码: 61d1) 系列优化视频教程
UI 优化视频 百度网盘 (提取码: covu) UI 专项优化视频
优化文章 thegamedev.guru 游戏优化技术文章
Lua 工具 Miku-LuaProfiler Lua 性能分析工具

二、编程代码规范

2.1 基本规范

规范 说明
脚本行数 单个脚本不超过 500 行
多语言版本 不同语言版本独立 Copy 一份代码
声音配置 由策划写在 Excel 中
链式语法 使用 C# 扩展方法提升可读性
平台测试 代码必须在多平台测试通过

2.2 规范调整

💡 提示:代码规范不是一成不变的,需要根据团队规模和代码风格进行有效调整。


三、检测工具

3.1 Unity 内置工具

工具 用途 链接
Profiler 性能分析 Unity 文档
Frame Debugger 帧调试 Unity 文档
Physics Debugger 物理调试 Unity Editor 内置
Memory Profiler 内存分析 Unity Package Manager

3.2 第三方工具

工具 平台 用途
UPR 通用 Unity 官方性能报告工具
UWA 通用 专业性能分析和优化建议
Xcode iOS GPU 性能和内存分析
Android Studio Android GPU 和内存分析

⚠️ 重要:君子善用其器,一定要先了解工具再进行使用。


四、宏观性能指标

4.1 目标指标

指标 目标值 检测工具
FPS 帧率 >30 帧 Profiler
PSS 内存 越低越好 Xcode/Android Studio
Mono 峰值 <40MB Profiler Memory
温度均值 越低越好 设备监控
能耗均值 越低越好 设备监控
网络上传 控制频率和大小 网络监控
网络下载 控制频率和大小 网络监控

4.2 Unity 官方建议

资源类型 建议值
Reserved Mono 峰值 <80 MB
DrawCall 峰值 <250 次
平均帧率 >25
纹理资源峰值 <50 MB
网格资源峰值 <20 MB
动画资源峰值 <15 MB
音频资源峰值 <15 MB
Tris 峰值 <200,000 面

五、微观性能关注点

5.1 分阶段关注点

模块 前期 中期 后期&上线
渲染模块 DrawCall、Triangle、Vertex 不透明、半透明、Culling 图像后处理
逻辑代码 插件、第三方库调研、bug CPU、堆内存、调用次数 bug
UI 模块 全屏、半屏、组织结构 overdraw、重建 CPU DrawCall
UGUI API Canvas.BuildBatch、SendWillRenderCanvases EventSystem.Update RenderSubBatch
加载模块 缓存池、序列化第三方库 关注调用频率 关注耗时
加载 API Loading.UpdatePreloading、Resources.UnloadUnusedAssets GameObject.Instantiate GC.Collect
资源使用 分辨率、格式、顶点数、骨骼数 数量、Mipmap、利用率、冗余 调用次数
内存占用 资源、AB 包、Mono、Lua 内存峰值、堆内存 内存泄露
粒子系统 使用指标 总体数量、active 数量 Overdraw
粒子 API ParticleSystem.Update、SubmitVBO、Draw ScheduleGeometryJobs -
动画系统 数量、AC 制作、CPU Animator.Update、Animation.Update MeshSkinning.Update、Animator.Initialize

六、代码优化

6.1 避免产生 GC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ❌ foreach 产生 GC
foreach (var item in list) { }

// ✅ 使用 for 替代
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
}

// ❌ 字典遍历产生 GC
foreach (var kvp in dictionary) { }

// ✅ 使用枚举器
var enumerator = dictionary.GetEnumerator();
while (enumerator.MoveNext())
{
var element = enumerator.Current;
element.Value.Update();
}
enumerator.Dispose();

6.2 字符串拼接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ✅ 少量拼接不产生 GC
string result = "Hello" + " " + "World";

// ❌ 大量拼接产生 GC
for (int i = 0; i < 100; i++)
{
result += i.ToString();
}

// ✅ 使用 StringBuilder
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for (int i = 0; i < 100; i++)
{
sb.Append(i);
}
string result = sb.ToString();

6.3 Struct vs Class

特性 Struct Class
内存分配
GC 影响
适用场景 轻量数据 复杂对象、抽象层次
1
2
3
4
5
6
7
8
9
10
11
// ✅ 轻量数据使用 Struct
public struct Point
{
public float x;
public float y;
}

// ✅ 修改后记得重新赋值(Struct 是值复制)
Point p = new Point();
p.x = 10; // ❌ 修改的是副本
// 需要重新赋值给原变量

6.4 集合选择

集合类型 特点 适用场景
数组 连续存储,索引快 大小固定
ArrayList 动态伸缩,非类型安全 已过时
List<T> 类型安全,动态扩展 通用集合

6.5 避免闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ❌ 闭包生成额外类
for (int i = 0; i < 10; i++)
{
StartCoroutine(() => DoSomething(i)); // 每次创建新类
}

// ✅ 提取为独立方法
for (int i = 0; i < 10; i++)
{
StartCoroutine(DoSomethingCoroutine(i));
}

IEnumerator DoSomethingCoroutine(int value)
{
// 使用 value
}

七、MonoBehaviour 优化

7.1 Update 优化

技巧 说明
缓存组件 Start 中缓存 Find 结果
降低频率 隔帧执行
使用协程 替代 Update
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ✅ 降低更新频率
void Update()
{
if (Time.frameCount % 6 == 0)
{
DoSomething();
}
}

// ✅ 使用 InvokeRepeating
void Start()
{
InvokeRepeating("DoSomething", 0.5f, 1.0f);
}

// ✅ 使用协程
IEnumerator Start()
{
while (true)
{
DoSomething();
yield return new WaitForSeconds(1.0f);
}
}

7.2 协程优化

1
2
3
4
5
6
7
8
9
10
// ❌ yield return null 每帧产生 9 字节 GC
yield return null;

// ✅ 预生成 Wait 对象
private WaitForSeconds waitOneSecond = new WaitForSeconds(1f);

IEnumerator TestCoroutine()
{
yield return waitOneSecond;
}

7.3 禁用优化

1
2
3
4
5
6
7
8
9
10
// ✅ 不可见时禁用组件
void OnBecameVisible()
{
enabled = true;
}

void OnBecameInvisible()
{
enabled = false;
}

八、Component 优化

8.1 使用内建值

1
2
3
4
5
6
7
// ❌ 每次创建新对象
transform.position = new Vector3(0, 0, 0);

// ✅ 使用内建常量
transform.position = Vector3.zero;
transform.localScale = Vector3.one;
transform.localRotation = Quaternion.identity;

九、GameObject 优化

9.1 缓存组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ❌ 每次查找
void Update()
{
var render = GetComponent<Renderer>();
}

// ✅ 缓存组件
private Renderer cachedRenderer;

void Start()
{
cachedRenderer = GetComponent<Renderer>();
}

void Update()
{
if (cachedRenderer != null)
{
// 使用缓存的组件
}
}

9.2 标签比较

1
2
3
4
5
6
7
8
9
// ❌ 产生 180B GC
if (go.tag == "Enemy")
{
}

// ✅ 不产生 GC
if (go.CompareTag("Enemy"))
{
}

9.3 避免 SendMessage

1
2
3
4
5
6
// ❌ 性能开销大
gameObject.SendMessage("DoSomething");

// ✅ 使用委托或直接调用
IDoSomething handler = go.GetComponent<IDoSomething>();
handler?.DoSomething();

十、UI 资源规范

10.1 图集规范

规范 说明
最大尺寸 1024×1024
同界面同图集 减少 DrawCall
公用资源 Common 多界面复用
九宫格 减小原图大小
关闭 Mipmaps UI 不需要
利用率 >1/3,否则合并

10.2 原图处理

处理方式 说明
全屏原图 按比例缩放最长边到 500
长条原图 拆分拼接
复用资源 使用顶点色区分品质

十一、Shader 优化

11.1 基础优化

优化项 说明
Fog { Mode Off } 关闭雾效
Alpha 剔除 剔除 Alpha=0 的像素
Fill Center 九宫格中心镂空

11.2 OverDraw 优化

优化项 说明
减少层级 减少 UI 重叠
隐藏元素 Disable 或移出裁剪区域
避免空 Image 不使用 Alpha=0 的响应区域

十二、CPU 优化

12.1 DrawCall 优化

策略 说明
合批绘制 相同图集合并
相邻同图集 避免穿插
Text 分层 避免打断合批
线框模式检测 Scene 视图 Wireframe

12.2 Mask 组件

1
2
3
4
5
// ❌ Mask 使用 Stencil Buffer,打断合批
// Unity 5.2+ 建议使用 RectMask2D

// ✅ 使用 RectMask2D
var rectMask = gameObject.AddComponent<RectMask2D>();

十三、Profiler 详解

13.1 重要函数

函数 说明 优化方向
WaitForTargetFPS Vsync 等待时间 检查 Vsync 设置
Camera.Render 相机渲染准备 优化渲染内容
Shader.Parse Shader 解析 预加载 Shader
Reserved Total 系统申请内存 控制内存分配
GC.Collect 垃圾回收 减少内存分配

13.2 优化重点

类型 重点 检测项
GC Alloc 一次性分配 >2KB Profiler Memory
GC Alloc 每帧分配 >20B Profiler Memory
Time ms 占用 >5ms Profiler CPU
ManagedHeap 移动游戏 <20MB Profiler Memory
Device.Present GPU 等待时间长 检查 Shader 复杂度

十四、优化检查清单

14.1 代码优化

  • 避免使用 foreach
  • 使用字典枚举器
  • 字符串使用 StringBuilder
  • Struct 替代 Class(轻量对象)
  • 避免闭包和匿名函数
  • 缓存组件引用
  • 使用 CompareTag 替代 tag 比较
  • 避免 SendMessage
  • 降低 Update 频率
  • 预生成 Wait 对象
  • 禁用不可见 GameObject

14.2 UI 优化

  • 图集 ≤1024×1024
  • 关闭 Mipmaps
  • 同界面同图集
  • 使用九宫格
  • 移除 Fill Center
  • 减少 Mask 使用
  • 动静分离
  • 禁用 Raycast Target

14.3 资源优化

  • 纹理使用压缩格式
  • 及时释放资源
  • 合并图集
  • 移除重复资源
  • 压缩音频文件
  • 使用 Force to Mono

十五、参考资料


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1487842110@qq.com