4.Unity中常见的性能优化技巧
4.1 题目
在Unity中,什么是常见的性能优化技巧?请举例说明。
4.2 深入解析
优化前先分清「问题类型」,再选手段,避免盲改:
| 大类 | 典型表现 | 主要手段方向 |
|---|---|---|
| 内存 | 占用高、OOM、Memory 曲线持续上涨 | 资源体积与生命周期、托管堆分配、原生资源卸载 |
| CPU 性能 | Profiler 中脚本/物理/动画 CPU 高、主线程长帧 | 减分配、降频、缓存、分帧、Job/Burst 等 |
| GPU 性能 | GPU 时间高、Overdraw、带宽瓶颈 | 合批、LOD、Shader/后处理、分辨率与 MSAA |
| 加载与 IO | 进场景卡、同步加载尖刺 | 异步/分帧、预加载、Addressables 分包 |
说明:GC 频繁既是 内存/分配 问题,也会表现为 CPU 卡顿(GC 跑在主线程);合批既减 CPU 提交,也减 GPU 状态切换。
下面按 内存与资源、CPU 与逻辑、GPU 与渲染、GC 与托管堆 归纳常用技巧(与上表对应)。
内存与资源管理
对象池(Object Pool)- 预先创建一批可复用的对象(如子弹、特效、敌人等),在需要时从池中取出、使用完毕后归还,而不是频繁地
Instantiate()/Destroy()。 - 显著降低内存分配和垃圾回收开销,减少卡顿。
- 预先创建一批可复用的对象(如子弹、特效、敌人等),在需要时从池中取出、使用完毕后归还,而不是频繁地
精简资源体积
- 纹理:使用合适的压缩格式(ASTC、PVRTC、DXT),并根据实际需求降低分辨率;
- 模型:剔除多余顶点和骨骼权重,使用低多边形版本;
- 音频:选择合适的编码和采样率(如 Ogg Vorbis ),避免无谓的大文件。
及时释放无用资源
- 对长期存在的资源(粒子、音频、视频、RenderTexture 等),在场景切换或不再使用时调用
Destroy(),或通过Resources.UnloadUnusedAssets()/ Addressables/AssetBundle 卸载接口释放内存。
- 对长期存在的资源(粒子、音频、视频、RenderTexture 等),在场景切换或不再使用时调用
异步加载(Async Loading)- 利用
Addressables.LoadAssetAsync、AssetBundle.LoadAssetAsync或Resources.LoadAsync,将大资源分割加载到后台线程,避免主线程帧率骤降和卡顿。
- 利用
资源打包与分组管理
- 使用 Addressables 或 AssetBundle 将资源按场景、功能模块分组,按需加载/卸载,降低启动时内存峰值。
GPU 与渲染(含部分 CPU 提交开销)
合批与 Draw Call 减少
- 静态合批(Static Batching):对不动的 Mesh 自动合并;
- 动态合批(Dynamic Batching):共享材质的小物件自动合并;
- SRP Batcher(需启用 URP/HDRP);
- GPU Instancing:批量渲染同材质的对象;
- 手动网格合并:在运行时将多个小网格合并成一个。
多级细节(LOD)系统- 使用 Unity 的 LOD Group,针对不同视距自动切换高/中/低精度模型,减少远距离渲染开销。
光照贴图(Lightmap)与烘焙- 对场景中的静态物体预先烘焙光照和阴影,生成 Lightmap,显著降低实时光照计算压力;
- 配合反射探针(Reflection Probe)提升视觉效果。
剔除与裁剪(Culling)- 开启摄像机视锥剔除(Frustum Culling);
- 配置遮挡剔除(Occlusion Culling),阻止被遮挡物体的渲染;
- 在业务逻辑层面,对远离玩家或不在视野内的对象主动停用。
控制粒子和 UI
- 粒子系统:避免过多或高密度的粒子特效,合理限制粒子发射率和最大粒子数;
- UI Canvas:减少重绘区域,避免频繁修改整个 Canvas;对于动态元素,可拆分成多个小 Canvas 或使用
CanvasRenderer.SetMesh()。
CPU 与主线程逻辑(与 GPU 重叠处:剔除、粒子模拟参数)
- Physics/动画:降低不必要的
FixedUpdate成本、简化碰撞层、控制 Animator 更新频率与骨骼数。 - 剔除与业务层:远距离对象逻辑降频、关闭不可见敌人的 AI(需与玩法一致)。
托管堆与 GC(减少分配 + 降 GC 造成的 CPU 尖刺)
减少临时分配
避免在高频调用的方法(如
Update()、OnGUI())中产生垃圾:- 用
StringBuilder替代字符串拼接; - 注意部分
foreach、LINQ、装箱等带来的分配; - 重用数组、
List<T>等容器。
- 用
重用对象与缓存
- 对频繁产生的临时对象、委托、协程迭代器等,用对象池或缓存复用。
持续优化与调优流程
Profiler 分析
- 定期使用 Unity Profiler(CPU、GPU、Memory、Rendering)定位性能瓶颈;
- 结合 Frame Debugger、RenderDoc 等工具深入排查渲染问题。
迭代验证
- 每次优化后,通过对比帧率曲线、内存占用曲线及 GC 日志,确认效果;
- 在目标平台(尤其是中低端手机和平板)上进行真机测试,确保优化策略有效。
4.3 答题示例
我会先把问题分成 内存、CPU、GPU、加载 四类,再选手段;常见答法:
- 内存与 GC:对象池、压缩与卸载资源、减
Update里分配,降低 GC 尖刺。- CPU:Profiler 看脚本/物理/动画;缓存组件、降频、分帧或 Job 化热点逻辑。
- GPU:合批/Instancing、LOD、遮挡剔除、简化 Shader 与后处理,控制 Overdraw 与带宽。
- 加载:异步与分包(Addressables 等),避免同步大资源造成尖刺。
全程用 Profiler 区分瓶颈在 CPU 还是 GPU 或内存,再针对性优化,并在真机验证。
4.4 关键词联想
对象池(Object Pool)Draw Call / 合批(Batches)- GC / 内存回收
- 异步加载 / Addressables
- LOD / Lightmap / Shader变体
- 资源压缩 / 优化贴图
- 性能分析器:Profiler / Memory Profiler
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com