☰
粒子特效卡顿?一文破解GPU/CPU/DrawCall三大元凶
2026/10/15 5:52:14 网站建设 项目流程

先记住一句话:

粒子特效卡,通常是三个原因:画得太多层(GPU)、算得太多(CPU)、命令发得太多(Draw Call)。优化就是找出是哪一个,再对症下药。


一、先搞懂:粒子到底贵在哪?

把手机想成一个画家:

CPU:助手,负责算每个粒子在哪、多大、什么颜色 GPU:画家,负责把粒子一笔一笔画到屏幕上 Draw Call:助手每次跑去跟画家说“现在画这个”
问题比喻表现
Overdraw(重复绘制)画家在同一个地方反复涂了 10 层GPU 卡,特效贴近镜头时掉帧最明显
粒子数量 / 模块太多助手要算的东西太多CPU 卡,Profiler 里ParticleSystem.Update很高
Draw Call 太多助手跑腿次数太多CPU 卡,Frame Debugger 里命令很多
贴图太大太多颜料太占地方内存高、加载慢、带宽高(发热)

最常见的元凶,尤其在手机上,是第一个:Overdraw。


二、头号杀手:Overdraw(重复绘制)

1. 什么是 Overdraw

粒子大多是半透明的,后面的东西不能省略不画。

一团烟雾由 20 张半透明图片叠成 → 中间的像素被画了 20 遍 → 画一个像素的工作量变成 20 倍

而且粒子越大、越贴近镜头,覆盖的像素越多,越卡。一个铺满全屏的爆炸,比远处的小火花贵得多。

2. 怎么看

Scene 视图左上角的显示模式里选Overdraw(内置管线可用;URP 可用 Rendering Debugger 查看):

颜色越亮(越白)= 被画的遍数越多 = 越费

3. 怎么减

方法说明
减少粒子大小大面积半透明是最贵的,能小就小
减少叠加层数用 1 张画得好的图,代替 10 张叠出来的效果
裁掉透明边贴图四周大片透明也要画。用贴合形状的网格(Mesh)代替方形面片,少画透明像素
限制贴脸在 Renderer 里设置Max Particle Size,防止粒子靠近镜头时撑满屏幕
少用全屏特效全屏光晕、雾,能用后处理或一张简单面片代替就代替

💡 经验:宁可让粒子不透明、或用 Alpha Test(镂空),也比大面积半透明叠加便宜。


三、控制数量:少即是多

1. 限制粒子数

设置作用
Max Particles上限,防止意外暴增。默认 1000,手机上通常设得远低于它
Emission Rate / Burst每秒发射多少,能少就少
Start Lifetime寿命越长,同时存在的粒子越多
同时存在的粒子数 ≈ 每秒发射数 × 寿命 每秒 50 个 × 寿命 4 秒 = 同时约 200 个 改成寿命 2 秒 → 只剩约 100 个

很多粒子其实早就变透明、看不见了,但还活着。把寿命缩短到刚好看不见的时候。

2. 用“质感”代替“数量”

❌ 发射 200 个小火星凑出一团火 ✅ 用序列帧动画(Texture Sheet Animation)播一张会动的火焰图

一张画得好的序列帧,往往比一大堆粒子效果更好、更省。

3. 分档:好手机和差手机用不同版本

高配:完整效果 中配:粒子数减半,去掉部分子发射器 低配:只保留核心部分

可以做多个预制体,或在代码里根据画质等级调整emission.rateOverTime、maxParticles。


四、减少 CPU 计算:小心“贵”的模块

粒子系统每个模块都要 CPU 算,有些模块特别贵:

模块贵不贵建议
Collision(碰撞)🔴 很贵尽量不用;必须用时选 Planes 模式代替 World,并降低 Quality
Lights(灯光)🔴 很贵每个粒子都可能是一盏实时灯,手机上基本别用
Trails(拖尾)🟠 较贵要生成网格;控制数量和 Lifetime
Noise(噪波)🟠 较贵降低 Quality,或用曲线代替
Sub Emitters(子发射器)🟠 看数量每个粒子再生粒子,数量会成倍增长
Trigger / External Forces🟠 较贵不需要就关掉
颜色、大小、旋转曲线🟢 便宜放心用

原则:不用的模块一定要关掉,不要“勾上但参数是 0”。

关键:保持“程序化模式”(Procedural Mode)

Unity 的粒子系统,如果只用了简单的模块,可以提前算出整个播放过程:

程序化模式:Unity 知道粒子会飞到哪 → 不在屏幕里时可以直接不算 非程序化: Unity 必须一步一步算 → 不在屏幕里也得一直算

用了碰撞、噪波、子发射器、某些世界空间设置等,就会失去这个能力。Inspector 右上角会出现一个警告图标,鼠标放上去能看到原因。

设置剔除模式(Culling Mode)

在主模块里:

选项意思适合
AutomaticUnity 自动决定一般情况
Pause看不见就暂停环境特效(篝火、瀑布)
Pause And Catch-up看不见暂停,回来时补上需要状态连续的特效
Always Simulate一直算尽量少用

五、减少 Draw Call:让粒子“一起画”

1. 共用材质

10 个粒子系统,用 10 种材质 → 至少 10 次 Draw Call 10 个粒子系统,共用 1 种材质 + 1 张贴图集 → 有机会合并

做法:把火花、烟、光点等画到同一张贴图集(Atlas)里,用 Texture Sheet Animation 选取不同格子。

2. 注意排序

半透明物体必须按顺序画,如果排序把同材质的粒子隔开了,就合并不了:

材质 A → 材质 B → 材质 A ❌ 被打断,3 次 材质 A → 材质 A → 材质 B ✅ 2 次

可以通过 Renderer 里的Sorting Layer / Order in Layer / Sorting Fudge调整顺序。

3. 网格粒子开 GPU Instancing

如果粒子是 3D 模型(Render Mode = Mesh),在 Renderer 里开启Enable GPU Instancing(需要 Shader 支持),大量相同网格可以一次画完。网格本身面数也要低。

4. 用 Frame Debugger 检查

Window → Analysis → Frame Debugger,可以一步步看每次 Draw Call 画了什么、为什么没合并。


六、贴图与 Shader

贴图

建议原因
尺寸够用就行,一般 128 / 256 / 512粒子很小、动得快,大图看不出区别
用压缩格式(手机用 ASTC / ETC2)省内存和带宽
尽量用贴图集减少材质,方便合并
黑白图用单通道只需要形状的话,不必用彩色 RGBA

Shader

✅ 用简单的粒子 Shader(Unlit、Mobile/Particles、URP Particles Unlit) ❌ 少用:扭曲(抓屏 GrabPass / Opaque Texture)、多张贴图叠加、复杂计算 ⚠️ 软粒子(Soft Particles)需要深度图,手机上要慎重

粒子覆盖的每个像素都要跑一遍 Shader,所以 Shader 越复杂,Overdraw 的代价越成倍放大。


七、使用方式:别反复“生”和“杀”

1. 对象池

❌ 每次开枪 Instantiate 一个特效,播完 Destroy → 频繁分配内存,产生 GC 卡顿 ✅ 提前生成一批,用完 Stop、隐藏,下次再拿出来 Play

2. 播完要停

  • 主模块设置Stop Action(如 Disable / Callback),播完自动处理
  • 避免 Looping 的特效被遗忘在场景里一直播

3. 慎用 Prewarm

勾选 Prewarm 会在开始时一次性模拟一整轮,大量特效同时启动可能造成卡顿。

4. 距离优化

远处的特效:减少粒子、换简化版,或者干脆不播 看不见的特效:关掉

八、特别多的粒子:考虑 VFX Graph

Particle System(传统)VFX Graph
谁来算CPUGPU
适合数量几十到几千几万到上百万
平台全平台,手机首选需要 Compute Shader,偏中高端设备
物理交互和物理系统交互方便较弱
手机游戏、普通技能特效 → Particle System PC/主机、海量粒子(星空、沙尘、魔法阵)→ VFX Graph

⚠️ VFX Graph 解决的是“CPU 算不过来”,解决不了 Overdraw。粒子多了照样会画很多层。


九、怎么找问题:排查流程

第 1 步:Profiler(Window → Analysis → Profiler) → 是 CPU 高,还是 GPU 高? 第 2 步:如果 GPU 高 → 打开 Overdraw 视图,看哪里最亮 → 减小、减少、裁剪那些粒子 第 3 步:如果 CPU 高 → 看 ParticleSystem.Update 等开销 → 检查粒子数量、昂贵模块、是否失去程序化模式 第 4 步:如果 Draw Call 多 → Frame Debugger 看为什么没合并 → 合并材质、调整排序 第 5 步:一定要在真机上测! → 编辑器里流畅,不代表手机上流畅

真机分析工具:Unity Profiler 连接真机、Xcode Instruments(iOS)、Snapdragon Profiler / Mali Graphics Debugger(安卓)、RenderDoc。


十、上线前检查清单

□ Overdraw 视图里没有大片高亮 □ 设置了 Max Particles,且数量合理 □ 粒子寿命没有比“看得见的时间”长很多 □ 设置了 Max Particle Size,贴脸不会撑满屏幕 □ 没有用实时灯光模块、World 碰撞(或已确认必要) □ 不用的模块都关掉了 □ 环境特效设置了合适的 Culling Mode □ 尽量共用材质和贴图集 □ 贴图尺寸合适、已压缩 □ 使用简单的粒子 Shader □ 频繁出现的特效用了对象池 □ 有高 / 低画质版本 □ 已在目标低端机上实测

💡 关于“多少个粒子才算多”:没有统一标准,取决于项目和设备。建议团队在目标低端机上实测,定下自己的预算,比如“单个技能特效最多几个 Draw Call、同屏最多多少粒子”,然后让所有特效都遵守。


一句话总结

粒子优化的核心顺序是:先用 Profiler 判断瓶颈;GPU 卡就减少大面积半透明叠加(Overdraw),CPU 卡就减少粒子数量和昂贵模块,Draw Call 多就合并材质和贴图;再配合对象池、剔除和分档画质,并且永远以真机测试为准。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询