Unity 性能优化 · 图解全景手册

01 优化方法论:先测量,再优化

**核心原则:**不要凭感觉优化。所有优化必须来自真机 Profiler 数据,且改一处、复测一次。

性能优化是一个闭环过程,核心思路是:先建立基线,再定位瓶颈,然后针对性优化,最后回归验证。任何跳过测量直接动手改代码的做法,都可能导致无效优化甚至引入新的性能问题。

02 帧预算:明确性能目标

在开始优化之前,必须先明确目标帧率对应的帧预算。以 60 FPS 为例,单帧总预算约为 16.6 毫秒;以 30 FPS 为例,单帧总预算约为 33.3 毫秒。

帧预算需要进一步拆分为 CPU 和 GPU 两部分。CPU 侧主要关注逻辑更新、物理模拟、动画系统和渲染提交(Draw Call);GPU 侧主要关注顶点处理、片元着色、Overdraw 和带宽占用。建议为 CPU 和 GPU 分别设定预算上限,例如 CPU 8 毫秒、GPU 8 毫秒,剩余时间作为缓冲。

03 特效优化:从源头控制开销

粒子特效是移动端性能消耗的大户,优化时应从以下几个方面入手:

  • 控制粒子数量:单个特效的粒子上限应结合屏幕占比设定,远处或小面积特效可适当降低发射率。
  • 限制 Overdraw:半透明粒子叠加会造成严重的像素重复写入,应避免大面积、多层级的半透明特效叠加。
  • 合理使用贴图:优先使用图集(Atlas)合并特效贴图,减少材质切换和 Draw Call。
  • 关闭不必要的组件:不需要碰撞检测的粒子系统应关闭 Collision 模块,不需要灯光交互的应关闭灯光模块。

04 粒子模块:按需启用

Unity 粒子系统包含多个可选模块,每个模块都会带来额外的 CPU 开销。默认情况下,只应启用当前特效真正需要的模块。

常见的开销来源包括:Collision 模块(碰撞检测)、Sub Emitters 模块(子发射器)、Noise 模块(噪声扰动)、Trails 模块(拖尾渲染)。如果特效不需要这些能力,应保持模块关闭状态。此外,粒子系统的 Scaling Mode 建议设置为 Hierarchy 或 Shape,避免每帧进行不必要的变换计算。

05 模型管线:减面与 LOD

模型侧的性能优化主要围绕顶点数量和渲染负担展开:

  • 减面:在建模阶段或导入设置中合理减面,去掉不可见或低贡献的顶点。
  • LOD 分级:为模型配置多级 LOD(Level of Detail),根据相机距离切换不同精度的网格。
  • 网格压缩:在导入设置中开启网格压缩(Mesh Compression),减少内存占用。
  • 蒙皮优化:对于骨骼动画模型,合理设置骨骼数量,避免冗余骨骼参与计算。

06 合批:减少 Draw Call

Draw Call 是 CPU 侧渲染提交的主要开销。减少 Draw Call 的核心手段是合批(Batching),Unity 提供两种内置合批方式:

  • 静态合批(Static Batching):适用于场景中不移动的物体,在构建时合并网格,运行时只需一次提交。
  • 动态合批(Dynamic Batching):适用于小规模、移动的物体,Unity 在运行时自动合并满足条件的网格。

此外,使用图集(Atlas)合并贴图、减少材质种类,也能有效提升合批成功率。需要特别注意的是,动态合批对顶点数有限制,且合批本身也有 CPU 开销,应结合 Profiler 数据判断是否值得开启。

07 贴图内存:格式与压缩

贴图是内存占用的主要来源之一,优化方向包括:

  • 压缩格式:移动端优先使用 ASTC(Android)和 PVRTC(iOS)等硬件压缩格式,避免使用未压缩的 RGBA32。
  • 尺寸控制:贴图尺寸应匹配实际显示需求,避免使用过大的贴图。
  • Mipmap 策略:对于 3D 场景中的贴图,开启 Mipmap 可以减少远处采样时的显存带宽压力;对于 UI 贴图,通常不需要 Mipmap。
  • 图集合并:将多张小贴图合并为图集,减少内存碎片和加载次数。

08 UI 分组:动静分离

UI 性能优化的核心思路是动静分离:将静态 UI 和动态 UI 分开管理,避免动态元素破坏静态元素的合批。

Canvas 的重建(Rebuild)开销与 UI 元素的变更频率直接相关。建议将频繁变化的文本、图标等元素放在独立的 Canvas 中,静态背景和固定布局放在另一个 Canvas 中,从而减少不必要的网格重建。

09 UI 合批:层级与图集

UI 合批的成败取决于层级顺序和贴图使用方式:

  • 层级顺序:相邻且使用同一图集的 UI 元素可以合批,中间插入其他图集的元素会打断合批。
  • 图集管理:将 UI 图片统一放入图集,避免使用独立贴图。
  • 避免 Raycast 滥用:不需要交互的 UI 元素应关闭 Raycast Target,减少命中检测开销。
  • 减少 Outline / Shadow:描边和阴影组件会额外生成顶点,应谨慎使用。

10 GC 优化:减少堆分配

C# 脚本中的堆分配是 GC(垃圾回收)压力的主要来源。GC 优化应关注以下几点:

  • 避免频繁字符串拼接:使用 StringBuilder 替代多次字符串相加。
  • 缓存组件引用:避免在 Update 中反复调用 GetComponent。
  • 使用对象池:对于频繁创建和销毁的对象(如子弹、飘字),使用对象池复用实例。
  • 避免闭包和 LINQ:在热路径中避免使用匿名函数和 LINQ 查询,它们会产生额外的堆分配。
  • 注意协程和事件:协程的 yield 和事件的 += / -= 也可能产生分配,应合理管理生命周期。

11 内存泄漏:定位与预防

内存泄漏会导致游戏运行时间越长越卡顿,最终可能被系统强制杀掉。常见的内存泄漏来源包括:

  • 事件未解绑:对象销毁前未移除事件监听,导致对象无法被回收。
  • 静态引用:静态字段持有对象引用,导致对象长期驻留内存。
  • 协程未停止:场景切换时未停止协程,协程持有的引用无法释放。
  • 资源未卸载:加载的 Asset 未通过 Resources.UnloadUnusedAssets 或 Addressables 释放。

定位内存泄漏的常用手段是使用 Unity Profiler 的 Memory 模块,观察堆内存的持续增长趋势,并结合对象快照对比分析。

12 渲染排序:减少状态切换

渲染排序直接影响 GPU 的状态切换开销。优化方向包括:

  • 材质排序:将使用相同材质的物体尽量连续渲染,减少材质切换。
  • 层级控制:通过 Render Queue 和 Sorting Layer 合理控制渲染顺序,避免不必要的深度测试失败。
  • 减少 Shader 变体:Shader 变体过多会导致编译时间和运行时切换开销,应通过 Shader Variant Collection 控制。

13 包体优化:裁剪与压缩

包体大小影响下载转化率和用户留存,优化方向包括:

  • 资源裁剪:移除未使用的资源,使用 Asset Bundle 按需加载。
  • 贴图压缩:使用硬件压缩格式,避免重复导入同一贴图。
  • 音频压缩:音频文件使用合适的压缩格式(如 Vorbis / AAC),控制采样率和时长。
  • 代码裁剪:启用 IL2CPP 的代码裁剪(Strip Engine Code),移除未使用的引擎代码。

总清单:性能优化速查

以下是一份面向面试和日常开发的性能优化速查清单:

维度 核心手段 关键指标
帧预算 CPU / GPU 分项预算 16.6 ms(60 FPS)
特效 粒子数量、Overdraw、图集 Draw Call、填充率
模型 减面、LOD、网格压缩 顶点数、三角面数
合批 静态合批、动态合批、图集 Draw Call 数量
贴图 ASTC / PVRTC、尺寸、Mipmap 显存占用
UI 动静分离、图集、层级 Canvas Rebuild 次数
GC 对象池、StringBuilder、缓存引用 堆分配量
内存 事件解绑、资源卸载 堆内存曲线
包体 Asset Bundle、压缩、裁剪 安装包大小
相关推荐
千里马学框架6 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
魔士于安6 天前
unity 丑陋哥布林 哥布林有humannoid 动画没 带动画
unity·游戏引擎·材质·贴图·模型
liangshanbo12156 天前
React 性能优化实战
性能优化·react
mmsx6 天前
Android GIS系列 内存加锁、SQLite 开事务:矢量数据集双层并发设计
android·性能优化·app
小贺儿开发6 天前
Unity 家居视频遥控(细节优化)
科技·unity·程序员·udp·视频·工具·通信
淡海水6 天前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
Pioneer000017 天前
我用 Redis + 网关做多模型 API 路由:缓存命中率 95%+ 的工程实践
人工智能·redis·后端·缓存·性能优化·架构
ZFJ_张福杰7 天前
【Flutter】Flutter 中有哪些耗时操作?从 UI 卡顿到 Isolate 性能优化
flutter·性能优化·卡顿·isolate
政企项目老覃7 天前
金融转账“幽灵失败“排查实录:从本地消息表到 Seata TCC 的选型与权衡
数据库·程序人生·性能优化·数据分析·系统架构
爱喝水的鱼丶7 天前
SAP-ABAP:MM 模块供应商主数据开发:字段扩展、分级管控与同步接口开发
开发语言·性能优化·接口·sap·abap·增强·经验交流