🛠️ Unity UWA 性能优化工具完全指南:从分析报告到实战优化
💡 UWA 工具的价值:
- 不知道如何系统分析性能问题?
- UWA 性能报告怎么看?
- CPU、内存、资源加载,如何针对性优化?
- 想学习专业团队的优化方法?
这篇文章! 将全面解析 UWA 性能优化工具,从报告解读到优化策略,让你的游戏性能更上一层楼!
一、UWA 工具概览
1.1 官方资源
1.2 性能报告示例
访问在线演示:UWA 性能分析演示
二、性能总结指标
2.1 核心性能指标
| 指标 |
说明 |
目标值 |
| 总体帧数 |
10分钟测试的理想帧数范围 |
16000~18000帧 (30fps) |
| GC 次数 |
垃圾回收调用次数 |
>1000帧/次 |
| CPU 均值 |
平均每帧 CPU 占用 |
越低越好 |
| CPU 占用占比 |
超过 33ms 的帧数占比 |
<10% (UWA 建议) |
| 堆内存 |
Mono 堆内存占用 |
<150MB (移动端) |
2.2 Mono vs IL2CPP 内存特性
| 特性 |
Mono |
IL2CPP |
| Reserved Total |
只升不降 |
可以下降 |
| 内存回收 |
不返还给系统 |
可以返还给系统 |
1 2 3 4 5 6 7 8 9
| 内存占用分配建议: ┌─────────────────────────────────────┐ │ 纹理资源 33% │ │ Mono 内存 26% │ │ 网格资源 13% │ │ 动画片段 10% │ │ 音频片段 10% │ │ 其他 8% │ └─────────────────────────────────────┘
|
三、高 CPU 占用函数
3.1 渲染相关
| 函数 |
说明 |
优化方向 |
| Camera.Render |
相机渲染准备 |
优化渲染内容,减少渲染对象 |
| MeshSkinning.Update |
蒙皮网格更新 |
降低骨骼数量,优化网格 |
3.2 UI 相关
| 函数 |
说明 |
优化方向 |
| UIPanel.LateUpdate() |
NGUI 网格重建 |
动静分离,控制动态元素数量 |
| UICamera.Update() |
NGUI 输入处理 |
减少事件监听 |
| UIRect.Update() |
NGUI 矩形更新 |
减少动态变化 |
3.3 动画相关
| 函数 |
说明 |
优化方向 |
| Animators.Update |
动画控制器更新 |
减少 Animator 数量 |
| Animation.Update |
动画组件更新 |
使用 AnimationClip 压缩 |
3.4 加载相关
| 函数 |
说明 |
优化方向 |
| Loading.UpdatePreloading |
场景预加载 |
优化资源大小,使用异步加载 |
| LoadingManager.Update() |
加载管理器 |
分帧加载 |
3.5 物理相关
| 函数 |
说明 |
优化方向 |
| Physics.Processing |
物理模拟处理 |
减少物理对象,简化碰撞体 |
| NavMeshManager |
导航网格管理 |
优化寻路频率 |
3.6 其他高频函数
1 2 3 4 5
| UnityEngine.SetupCoroutine() Destroy TweenEffectBase.Update() SoundManager.Update() AINormalWarrior.Update()
|
四、高堆内存分配函数
4.1 核心问题函数
| 函数 |
问题 |
优化方案 |
| UIPanel.LateUpdate() |
UI 网格重建分配内存 |
动静分离,减少重建 |
| UnityEngine.SetupCoroutine() |
协程启动分配 |
避免频繁创建协程 |
| UICamera.Update() |
每帧分配 |
优化事件处理逻辑 |
| iTween.Update() |
补间动画分配 |
替换为更高效的方案 |
| Instantiate |
实例化分配 |
使用对象池 |
4.2 堆内存分配原则
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void Update() { List<int> list = new List<int>(); }
private List<int> cachedList = new List<int>();
void Update() { cachedList.Clear(); }
|
五、CPU 优化篇
5.1 渲染模块优化
Draw Call 优化
| 策略 |
说明 |
| 减少材质种类 |
合并相同材质的物体 |
| Draw Call Batching |
使用批处理减少 DC 数量 |
| 带宽平衡 |
Draw Call 与总线带宽的天平平衡 |
⚠️ 注意:DrawCall 越小越好是误区!决定渲染性能的除了 DrawCall 还有总线带宽。
资源简化
| 优化项 |
说明 |
| 三角形面片数 |
降低模型面片数 |
| 纹理分辨率 |
使用合适的分辨率 |
| 网格资源 |
优化 Mesh 数据量 |
5.2 UI 模块优化
UIPanel.LateUpdate 优化
1 2 3 4 5 6 7 8 9 10 11
| NGUI 优化原则: ┌─────────────────────────────────────┐ │ 1. 动静分离 │ │ → 动态/静态 UI 分离到不同 UIPanel│ │ │ │ 2. 同步性划分 │ │ → 运动频率不同的 UI 分离 │ │ │ │ 3. 控制动态元素数量 │ │ → 每组 UIPanel 5~10 个动态 UI │ └─────────────────────────────────────┘
|
UI 优化技巧
| 技巧 |
说明 |
| 动静分离 |
UI 重建以 UIPanel 为单位 |
| 同步分组 |
运动频率一致的放在同一 Panel |
| 数量控制 |
每组 Panel 动态元素 5~10 个 |
| 概率优化 |
从概率上降低单帧重建开销 |
5.3 加载模块优化
场景卸载开销
| 函数 |
开销来源 |
优化方案 |
| Destroy |
OnDestroy 回调代码 |
优化 OnDestroy 逻辑 |
| Resources.UnloadUnusedAssets |
资源卸载检测 |
减少资源数量,预清理 |
场景加载开销
| 函数 |
开销来源 |
优化方案 |
| 资源加载 |
纹理/网格/材质大小 |
压缩资源格式 |
| Instantiate |
实例化 + 序列化 |
预加载,对象池 |
| SerializedField |
序列化开销 |
减少序列化字段 |
加载优化建议
1 2 3 4 5 6 7
|
Instantiate(prefab);
|
5.4 代码效率优化
性能”二八原则”
80% 的性能开销集中在 20% 的函数上
| 高开销函数类型 |
优化重点 |
| Camera.Render |
渲染内容优化 |
| MovementScript.FixedUpdate() |
物理移动优化 |
| ParticleSystem.Update |
粒子数量控制 |
| Physics.Simulate |
物理对象减少 |
六、内存优化篇
6.1 内存分类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Unity 内存结构: ┌─────────────────────────────────────┐ │ Unity 资源内存 70%+ │ │ ├─ 纹理 (Texture) │ │ ├─ 网格 (Mesh) │ │ ├─ 动画 (AnimationClip) │ │ └─ 音频 (AudioClip) │ │ │ │ 引擎模块内存 │ │ ├─ GameObject / Component │ │ ├─ WebStream │ │ └─ SerializedFile │ │ │ │ 托管堆内存 │ │ └─ Mono / IL2CPP │ │ │ │ 第三方插件内存 │ │ └─ toLua 等脚本引擎 │ └─────────────────────────────────────┘
|
6.2 纹理内存优化
纹理格式选择
| 平台 |
推荐格式 |
备选方案 |
| Android |
ETC2 (OpenGL ES 3.0+) |
ETC1 + Alpha8 (ES 2.0) |
| iOS |
PVRTC 4BPP |
ASTC |
| PC |
DXT / BC7 |
RGBA16 |
纹理优化策略
| 问题 |
解决方案 |
| 色阶问题 |
减少色差范围,使用硬件压缩格式 |
| ETC1 无透明 |
分离 RGB 和 Alpha 为两张 ETC1 |
| 尺寸过大 |
降低分辨率,够用就好 |
| Mimap 开启 |
UI 纹理关闭 Mipmap |
| Read & Write |
默认关闭,节省内存 |
6.3 网格内存优化
顶点属性优化
| 属性 |
内存影响 |
优化建议 |
| Position |
必需 |
保留 |
| UV |
必需 |
保留 |
| Normal |
增加 |
按需使用 |
| Tangent |
增加 |
按需使用 |
| Color |
增加 |
按需使用 |
⚠️ 批处理注意:不同顶点属性的网格拼合时,会补齐所有属性,大幅增加内存!
网格优化建议
6.4 引擎模块内存
WebStream 和 SerializedFile
| 类型 |
来源 |
优化方案 |
| WebStream |
AssetBundle 原始+解压数据 |
使用 LoadFromFile |
| SerializedFile |
AssetBundle 序列化文件 |
卸载未使用的 AB |
6.5 托管堆内存优化
主要内存分配来源
| 来源 |
优化方案 |
| 高频 New Class/Container |
Update 中避免分配 |
| Log 输出 |
控制日志输出 |
| UIPanel.LateUpdate |
动静分离 |
| String 连接 |
使用 StringBuilder |
| GetComponent |
缓存组件引用 |
Mono 内存分配计算
1 2 3 4
| 假设某函数每帧分配 100B: 帧率 30fps → 每秒 3KB → 每分钟 180KB → 10分钟 1.8MB
如果有 10 个这样的函数 → 10分钟 18MB
|
6.6 内存分配合理额度
| 资源类型 |
占比 |
| 纹理资源 |
33% |
| Mono 内存 |
26% |
| 网格资源 |
13% |
| 动画片段 |
10% |
| 音频片段 |
10% |
| 其他 |
8% |
七、内存泄露检测
7.1 内存泄露误区
| 误区 |
真相 |
| 进出场景内存不一致 = 泄露 |
资源常驻、Mono 只升不降 |
| PSS 未回落 = 泄露 |
系统 Cache 不会及时清理 |
7.2 资源泄露检测
方法一:资源生命周期
1 2 3 4 5
| UWA 资源生命周期分析: ┌─────────────────────────────────────┐ │ 预加载资源 → 合理的常驻资源 │ │ 泄露资源 → 需要修复的资源 │ └─────────────────────────────────────┘
|
方法二:场景比较
| 比较方式 |
用途 |
| 同场景不同时刻 |
查找资源使用差异 |
| 不同类型场景 |
检查”共同资源”是否合理 |
方法三:Profiler 检测
7.3 资源冗余
冗余来源
| 来源 |
解决方案 |
| AssetBundle 打包问题 |
依赖打包,避免重复 |
| 资源实例化 |
预制多材质,避免运行时修改 |
1 2 3 4 5 6 7 8
| material.color = hitColor;
Material normalMaterial; Material hitMaterial1; Material hitMaterial2;
|
八、AssetBundle 打包优化
8.1 打包 API
1 2 3 4 5 6 7
| BuildPipeline.BuildAssetBundles( outputPath, builds, assetBundleOptions, targetPlatform );
|
8.2 打包规则
| 规则 |
说明 |
| abName |
相同 abName 打入同一 Bundle |
| 依赖关系 |
自动建立依赖,避免冗余 |
| 增量发布 |
自动跳过未变的 Bundle |
| Manifest |
记录 Bundle 信息和依赖关系 |
8.3 重要选项
| 选项 |
说明 |
| CompleteAssets |
保证资源完备性 |
| CollectDependencies |
收集依赖项 |
| DeterministicAssetBundle |
维护固定 ID |
| DisableWriteTypeTree |
减小 Bundle 大小 |
8.4 Variant 参数
1 2 3 4 5 6 7 8 9
| Variant 用途: ┌─────────────────────────────────────┐ │ 多分辨率支持 │ │ • 相同 abName + 不同 variant │ │ • 资源一一对应 │ │ • ID 相同,可相互替换 │ │ │ │ 示例: 手机/平板 UI 分辨率适配 │ └─────────────────────────────────────┘
|
8.5 打包注意事项
| 问题 |
解决方案 |
| Prefab 不建立依赖 |
共享纹理需要单独设置 abName |
| Shader Stripping |
手动模式,勾选相应 Mode |
| 代码热更新 |
分离数据和逻辑,DLL 动态加载 |
九、资源加载优化
9.1 加载耗时分析
| 资源类型 |
主要耗时因素 |
| 纹理 |
分辨率、格式、Mipmap |
| 网格 |
面片数、顶点属性 |
| Shader |
解析耗时(Keyword 数量) |
| 动画 |
压缩格式 |
9.2 纹理加载优化
加载效率对比
| 格式 |
加载效率 |
说明 |
| ETC1/ETC2 |
最高 |
Android 推荐 |
| PVRTC 4BPP |
最高 |
iOS 推荐 |
| RGBA16 |
很高 |
折中方案 |
| RGBA32 |
较低 |
谨慎使用 |
优化建议
9.3 网格加载优化
顶点属性影响
| 顶点数 |
加载耗时 |
内存占用 |
| <5000 |
低 |
低 |
| 5000-15000 |
中 |
中 |
| >15000 |
高 |
高 |
优化建议
1 2 3 4 5
| 网格优化清单: ☐ 降低顶点和面片数量 ☐ 谨慎处理顶点属性 ☐ 关闭 Read/Write(不进行读写时) ☐ 避免不同属性网格批处理
|
9.4 Shader 加载优化
Shader 解析瓶颈
| 因素 |
影响 |
| Keyword 数量 |
越多越慢 |
| Fallback |
增加解析开销 |
| 变体数量 |
影响加载时间 |
Shader 优化方案
1 2 3 4 5 6 7 8 9 10 11 12 13
|
Shader.WarmupAllShaders();
ShaderVariantCollection svc = new ShaderVariantCollection(); svc.Add(new ShaderVariantCollection.ShaderVariant( shader, passType, keywords )); svc.WarmUp();
|
Shader 打包策略
| 策略 |
说明 |
| 独立 AB 包 |
所有 Shader 打包,预加载常驻 |
| 预加载 |
游戏启动时加载,避免运行时卡顿 |
| 剔除变体 |
只打包使用的变体 |
9.5 动画加载优化
压缩格式对比
| 格式 |
加载效率 |
视觉质量 |
| Off |
慢 |
最优 |
| Keyframe Reduction |
中 |
中 |
| Optimal |
快 |
可能有损失 |
优化建议
1 2 3 4
| 动画优化: • 推荐 Optimal 压缩模式 • 检查视觉质量是否可接受 • Humanoid 比 Generic 更小
|
十、Profiler 性能参数
10.1 WaitForTargetFPS
1 2 3 4 5 6 7 8
| WaitForTargetFPS 原理: ┌─────────────────────────────────────┐ │ 设定目标帧率 (Application.targetFPS) │ │ ↓ │ │ 上一帧 < 目标帧率 │ │ ↓ │ │ 本帧等待,维持目标帧率 │ └─────────────────────────────────────┘
|
| 情况 |
说明 |
| CPU 开销过低 |
等待目标帧率 |
| CPU 开销过高 |
无法达到目标帧率 |
10.2 Gfx.WaitForPresent / Graphics.PresentAndSync
参数说明
| 参数 |
渲染模式 |
说明 |
| Gfx.WaitForPresent |
多线程渲染 |
主线程等待渲染线程 |
| Graphics.PresentAndSync |
单线程渲染 |
主线程 Present 等待 |
CPU 占用高的原因
1 2 3 4 5 6 7 8 9 10 11
| 三种主要原因: ┌─────────────────────────────────────┐ │ 1. CPU 开销低 │ │ → 等待 GPU 完成渲染或 VSync │ │ │ │ 2. CPU 开销高 │ │ → Present 错过 VSync │ │ │ │ 3. GPU 开销高 │ │ → 等待上一帧渲染完成 │ └─────────────────────────────────────┘
|
VSync 地铁比喻
1 2 3 4 5 6 7 8 9
| VSync 就像地铁到站: ┌─────────────────────────────────────┐ │ 地铁每 16.6ms (60fps) 一班 │ │ │ │ 早到 → 等待时间短 │ │ 晚到 → 等下一班 (错过 VSync) │ │ │ │ CPU Present = 乘客上车 │ └─────────────────────────────────────┘
|
优化建议
重要:忽略 Gfx.WaitForPresent 和 Graphics.PresentAndSync 参数,优化其他一切可优化的地方!
十一、优化检查清单
11.1 CPU 优化
11.2 内存优化
11.3 资源加载优化
十二、参考资料
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1487842110@qq.com