03 · 视觉特效与模拟
03 · 视觉特效与模拟
VFX 是独立游戏里最容易超预算、最容易翻车、也最容易出彩的领域。 一句话原则:特效的价值不在数量,在时机与分层。
1. VFX 预算(先定,再画)
粒子预算表
| 场景类型 | 同屏最大粒子数(Low/Mid) | 系统数 | 说明 |
|---|---|---|---|
| 环境氛围(尘埃/落叶/雨) | 500 / 1500 | 3–5 | 常驻,预算大头 |
| 战斗特效(单次命中) | 30 / 60 | 1–2 | 短生命周期 |
| 技能特效(大招) | 200 / 500 | 3–5 | 短暂,允许借预算 |
| Boss 战 | 800 / 2000 | 8–12 | 允许超常驻预算 2× |
| 场景事件(瀑布/火堆) | 200 / 600 | 2–4 |
Overdraw 预算(见 principles/02)
- 透明层 ≤ 2.5(Low)/ ≤ 4(Mid)
- 每个特效系统要标注它贡献的 overdraw 层数
- 加性混合(Additive)的特效不写深度,但会叠加填充 → 更贵
帧预算
- VFX 总 GPU ≤ 2.0ms(Low)/ ≤ 3.0ms(Mid)
- VFX 总 CPU(更新/生成)≤ 0.5ms
- CPU 粒子的瓶颈通常是"每帧生成/回收",用对象池
2. 特效的五层结构(万能拆解模板)
任何特效都能拆成五层。独立游戏用 3 层就够,大招用 5 层。
| 层 | 作用 | 时长 | 典型元素 | 成本 |
|---|---|---|---|---|
| L1 Anticipation 预备 | 预告"要发生了" | 100–300ms | 收缩、聚光、粒子吸入、音效起 | 低 |
| L2 Impact 冲击 | 瞬间爆发 | 50–150ms | 闪白、冲击波环、碎片、屏震 | 中 |
| L3 Core 主体 | 特效本体 | 300–1000ms | 主粒子、火焰、能量 | 高 |
| L4 Debris 残留 | 余韵 | 500–1500ms | 烟、余烬、碎片、地面痕迹 | 中 |
| L5 Decal 痕迹 | 留存证据 | 2–10s | 地面焦痕、血迹、裂痕 | 低(但要管理数量) |
关键:L1 和 L5 最省钱但收益最高。新手特效师只做 L3,老手会加 L1 和 L5。
3. 打击感时间轴(TA 必须能画出来)
以一次近战命中为例:
t=0ms 命中判定
t=0 Hitstop 开始(游戏时间缩放 0.05)
t=0 受击者闪白(1–2 帧全白)
t=0 命中粒子生成(6–10 个,锥形喷射)
t=0 音效播放(与闪白同帧!)
t=0 屏幕震动开始(振幅 ease-out)
t=0–80ms 受击者击退位移
t=60ms 冲击波环 mesh 缩放动画(0.5→1.5,淡出)
t=80ms Hitstop 结束,时间恢复
t=100ms 闪白结束,恢复正常色
t=150ms 屏震结束
t=300ms 余烬粒子淡出
t=800ms 地面 decal 出现(可选)
要点
- Hitstop 期间特效仍要播放(用 unscaled time),否则会"卡住不动"很难看
- 闪白 1–2 帧足矣,太长会像 bug
- 屏震频率 < 20Hz,振幅 < 8px,否则晕
- 音效与视觉必须同帧,不同步会让手感崩塌
4. 特效技法库
核心技法(必会)
| 技法 | 用途 | 成本 |
|---|---|---|
| Flipbook / 序列帧 | 爆炸、烟、火焰 | 低(一张图解决复杂模拟) |
| UV 流动/滚动 | 能量、水流、光带 | 极低 |
| 软粒子(深度淡出) | 粒子与地面相交不硬切 | 低 |
| 加性混合 + 遮罩 | 能量、光效 | 低 |
| GPU 粒子 | 大量粒子(雨、雪、尘埃) | 中(但省 CPU) |
| 广告牌 Billboard | 所有粒子的默认朝向 | 极低 |
| 拉伸广告牌 Stretched Billboard | 速度线、火花拖尾 | 低 |
| 网格发射 Mesh Emitter | 沿物体表面生成 | 中 |
| 噪声驱动位移 | 火焰扰动、烟雾 | 中 |
| 曲线/参数驱动 | 全部 —— 一定要参数化 | — |
进阶(招牌候选)
| 技法 | 用途 | 成本 |
|---|---|---|
| 屏幕空间扭曲 | 热浪、冲击波、黑洞 | 中 |
| 深度/法线交互 | 雪地脚印、水面涟漪 | 中 |
| Volume/RT 模拟 | 流体、烟雾 | 高 |
| 粒子碰撞 | 火花弹跳 | 中 |
| Decal 投影 | 血迹、弹孔、涂鸦 | 低 |
| Trail / Ribbon | 刀光、轨迹 | 低 |
| 顶点动画 mesh | 冲击波环、能量盾 | 低 |
5. 常用特效的"够用"实现(独立游戏版)
| 需求 | 不要做 | 做这个 |
|---|---|---|
| 火焰 | 流体模拟 | Flipbook(8×8)+ UV 扰动 + 加性 + 少量烟 |
| 水 | 全屏折射 | 滚动法线 + 深度淡出 + 岸边泡沫 decal |
| 雨 | 每滴一个粒子 | GPU 粒子 + 拉伸广告牌 + 屏幕空间水痕 + 地面 ripple decal |
| 雪 | 物理雪 | GPU 粒子 + 风场噪声 + 累积材质参数 |
| 爆炸 | 复杂模拟 | 1 个 Flipbook + 冲击波环 + 碎片 + 屏震 + 烟 |
| 刀光 | 真实轨迹 | Trail renderer + 沿轨迹的渐变 alpha |
| 魔法 | 复杂能量场 | 加性 mesh + 噪声流动 + 边缘 rim |
| 血 | 真实流体 | 8 个粒子 + decal |
| 烟 | 体积烟 | Flipbook + 缓慢上升 + 软粒子 |
6. 模拟(Simulation)—— 独立游戏的双刃剑
该模拟的
| 场景 | 理由 |
|---|---|
| 玩家可交互的物理(推箱子、破坏) | 玩法核心 |
| 布料/头发(少量) | 视觉提升明显 |
| 绳索/链条 | 少量即可 |
| Noita 式像素模拟 | 它就是玩法(L3) |
不该模拟的
- 大规模流体(用 Flipbook)
- 全场景天气物理
- 每一根草
- 精确的流体浮力
模拟的稳定性规则
- 固定时间步长(Fixed Timestep),不要跟帧率走
- 限制最大迭代次数和最大物体数
- 必须有"卡死检测":超出边界/速度异常 → 重置
- 可一键关掉:模拟出问题时能降级成 Flipbook
- 确定性:如果需要回放/联机,必须固定种子 + 固定步长
7. VFX 性能优化清单
| 问题 | 症状 | 解法 |
|---|---|---|
| Overdraw 爆炸 | 透明处掉帧 | 减少粒子数、增大尺寸;挖空贴图透明区;降采样 |
| CPU 生成开销 | 每帧 new 粒子卡顿 | 对象池;预分配 |
| 太多不同材质 | DrawCall 高 | 所有特效共用 1–2 个特效母材质 |
| 软粒子深度采样 | 移动端贵 | 降采样深度图或关掉 |
| Decal 堆积 | 内存涨 | Decal 池(最多 N 个,循环复用) |
| 粒子永远不销毁 | 泄漏 | 生命周期上限 + 强制回收 |
| 特效在低端机照跑 | 低端机卡 | 画质档位控制粒子上限倍率 |
| 阴影投射的粒子 | 极贵 | 粒子禁止投影 |
| 透明排序错误 | 闪烁/穿插 | 显式设置渲染队列;减少层数 |
8. 画质档位对 VFX 的控制
| 档 | 粒子倍率 | Flipbook 分辨率 | 软粒子 | Decal 上限 |
|---|---|---|---|---|
| 低 | 0.3 | 512 | 关 | 20 |
| 中 | 0.6 | 512 | 开 | 50 |
| 高 | 1.0 | 1024 | 开 | 100 |
| 极致 | 1.5 | 1024 | 开 | 200 |
实现方式:一个全局 VFXQualityScale 参数,所有系统在生成时乘这个系数。必须在系统设计的第一天就留好这个接口。
9. VFX 规格单模板
见 templates/06-vfx-spec.md
10. VFX 库建设(量产关键)
建立 10–20 个可复用特效预设,覆盖 80% 需求:
| 类别 | 必备预设 |
|---|---|
| 打击 | 轻击 / 重击 / 暴击 / 格挡 / 命中护盾 |
| 状态 | 中毒 / 燃烧 / 冰冻 / 眩晕 / 治疗 / 增益 |
| 环境 | 火堆 / 瀑布 / 风 / 雨 / 尘埃 / 落叶 |
| UI 反馈 | 拾取 / 升级 / 解锁 / 失败 |
| 转场 | 传送 / 死亡 / 重生 / 加载 |
每个预设必须参数化:颜色、尺寸、时长、强度可由策划调节。
11. 自检清单
- 粒子预算表写了吗?同屏最大数是多少?
- 每个特效标注了 overdraw 贡献吗?
- 五层结构里,L1(预备)和 L5(痕迹)有了吗?
- 打击感时间轴画了吗?音效与视觉同帧吗?
- Hitstop 期间特效还在播放吗?
- 特效共用母材质了吗?(≤2 个)
- 有画质档位倍率吗?
- 用对象池了吗?
- Decal 有上限吗?
- 粒子禁止投影了吗?
- 最乱的战斗场面,玩家还能看清自己吗?(回
principles/06) - 关掉全部特效,游戏还能玩吗?不能 → 玩法过度依赖特效(危险)。
12. 一句话总结
特效的 80% 效果来自 20% 的粒子 + 正确的时机。 一个在正确时刻出现的 8 粒子火花,比一个永远在跑的 800 粒子火焰更有效,也更便宜。 先做时机,再做数量。