27 · 性能预算指南
适用范围 全部系统
所属文档集 ← 返回索引 · 总览
目录
- 帧时间预算
- GC 分配预算
- 每平台性能目标
- 对象池容量公式
- 物理配置规范
- 动画导入配置规范
- UI Canvas 批处理规范
- 音频预算
- Profiler 使用规范
- 性能检查清单(PR 门禁)
1. 帧时间预算
目标帧率
| 平台 |
目标帧率 |
帧时间预算 |
| PC(高配) |
144 fps |
6.9 ms |
| PC(低配) |
60 fps |
16.6 ms |
| Steam Deck |
60 fps |
16.6 ms |
| Nintendo Switch(未来) |
30 fps |
33.3 ms |
主要基准:以 60 fps / 16.6 ms 为核心优化目标。
帧时间分配(16.6 ms)
超时警报阈值
| 系统 |
Profiler Marker |
警报阈值 |
PlayerController |
[BaseGames] Player.Update |
> 1 ms |
EnemyAI(全部) |
[BaseGames] Enemies.AI |
> 2 ms |
GlobalObjectPool.Prewarm |
[BaseGames] Pool.Prewarm |
> 50 ms(仅启动一次) |
SaveManager.Save |
[BaseGames] Save.Write |
> 10 ms(异步写入,主线程触发) |
2. GC 分配预算
限制
| 范围 |
限制 |
说明 |
| 每帧 GC 分配(游戏进行中) |
≤ 256 KB |
超出可能导致 GC Pause |
| 单次 GC Pause(如需触发) |
≤ 1 ms |
使用 Incremental GC |
| 游戏启动时(预热阶段) |
不限制 |
仅启动一次,不影响游玩 |
| 场景加载时(加载画面覆盖) |
不限制 |
加载画面覆盖,不可见 |
Unity 设置
常见 GC 热点及替代方案
| 反模式 |
替代方案 |
GetComponent<T>() 在 Update 中 |
Awake 缓存引用 |
string 拼接/Format 在热路径 |
预分配 StringBuilder 或 string.Format 仅在非热路径 |
LINQ(.Where().ToList())在 Update |
手写 for 循环 + 预分配 List<T> |
事件 += lambda 每帧注册 |
OnEnable/OnDisable 订阅/取消 |
new Vector2/3() 频繁在 Update |
复用局部变量,不 new |
Physics2D.RaycastAll() |
Physics2D.RaycastNonAlloc() + 预分配数组 |
Coroutine yield return new WaitForSeconds() 每帧 |
缓存 WaitForSeconds 实例(static readonly) |
推荐 Profiler 内存标记
3. 每平台性能目标
渲染
| 指标 |
PC 低配 目标 |
Steam Deck 目标 |
| Draw Calls / 帧 |
≤ 150 |
≤ 100 |
| Batches / 帧 |
≤ 80 |
≤ 60 |
| SetPass Calls / 帧 |
≤ 20 |
≤ 15 |
| Sprite Atlas 最大尺寸 |
2048×2048 |
1024×1024 |
| 像素填充率(全屏四边形) |
— |
避免超过 3 层透明叠加 |
活跃对象上限
| 对象类型 |
同屏上限 |
超出时行为 |
| 活跃敌人 |
20 |
超出范围的敌人进入"休眠"(禁用 AI,保留碰撞) |
| 活跃弹射物 |
64 |
对象池:超出上限时最老的 Projectile 自动回收 |
| 活跃粒子系统 |
32 |
Feel MMF_Player 内置最大粒子预算 |
| 活跃 MMF_Player |
16 |
低优先级 Feedback 在帧预算紧张时跳过 |
4. 对象池容量公式
弹射物对象池
| 参数 |
值 |
说明 |
| 最大活跃敌人 |
20 |
见活跃对象上限 |
| 每敌人最大弹射物 |
4 |
Boss 弹幕模式最大同时弹射物 |
| 齐射数 |
2 |
一轮连发的发射次数 |
| 安全余量 |
1.5 |
防止池枯竭 |
| 推荐池容量 |
256 |
向上取 2 的幂次 |
粒子/特效对象池
敌人对象池
- Boss 敌人:不使用对象池(唯一实例,场景卸载时销毁)
- 普通敌人:
预热数量 = 房间最大敌人数 × 2(支持密集战斗)
池枯竭策略
5. 物理配置规范
Fixed Timestep
不要使用默认 0.02 以外的值,除非特别测试验证。60fps 游戏中 FixedUpdate 每帧约调用 0.83 次(略低于每帧 1 次),游戏逻辑不依赖精确的 FixedUpdate 频率。
Physics2D 配置
推荐碰撞层矩阵
| 层 |
Player |
Enemy |
Projectile |
Wall |
OneWay |
Trigger |
| Player |
✗ |
✗ |
✗ |
✓ |
✓ |
✓ |
| Enemy |
✗ |
✗ |
✓ |
✓ |
✓ |
✗ |
| Projectile |
✓ |
✓ |
✗ |
✓ |
✗ |
✗ |
| HitBox |
✗ |
✓ |
✗ |
✗ |
✗ |
✗ |
| HurtBox |
✗ |
✗ |
✗ |
✗ |
✗ |
✗ |
HitBox/HurtBox 仅与对应目标层碰撞,减少不必要的碰撞查询。
Rigidbody2D 最佳实践
- 玩家/敌人:
CollisionDetectionMode = Continuous(防止穿墙)
- 弹射物:
CollisionDetectionMode = Continuous(高速物体必须)
- 静态平台:使用
StaticRigidbody2D 或仅 Collider2D(无 Rigidbody2D)
6. 动画导入配置规范
帧率策略
| 动画类型 |
推荐帧率 |
说明 |
| Idle(待机循环) |
12 fps |
动作缓慢,低帧率不明显 |
| Run(奔跑循环) |
20 fps |
需要流畅感 |
| Jump / Fall |
12 fps |
空中动作简单 |
| Attack(精确帧数) |
60 fps |
HitBox 需要精确到帧 |
| Boss 攻击预警 |
60 fps |
电报动作需要精确控制 |
| UI 动画 |
30 fps |
界面元素不需要极高帧率 |
| Cutscene |
24 fps |
电影帧率 |
Animancer 支持动画混合,帧率差异在混合时自动处理,无需担心不同帧率动画之间的转换问题。
导入设置
7. UI Canvas 批处理规范
Canvas 分层策略
| Canvas |
更新频率 |
推荐类型 |
| 主 HUD(HP/Soul/Geo) |
按需(事件驱动) |
Screen Space - Camera |
| Boss HP 条 |
按需 |
与主 HUD 同 Canvas |
| 小地图 |
按需 |
独立 Canvas(复杂更新) |
| 暂停菜单 |
静态(打开时) |
Screen Space - Overlay |
| 对话 UI |
按需 |
独立 Canvas |
| 加载画面 |
静态 |
独立 Canvas(最高层级) |
Draw Call 限制
| 规则 |
值 |
| 单个 Canvas 最大 Draw Calls |
8 |
| 共享 Sprite Atlas 尺寸 |
512×512(HUD)/ 1024×1024(全屏 UI) |
| 透明 UI 元素叠加层数 |
≤ 4 层(超出会导致 Overdraw) |
避免 Canvas 脏标记
- 动态数值(HP、Geo)使用
TextMeshPro,仅在数值变化时更新 text 属性
- 动画元素(Blood flash、Soul 充能)使用独立子 Canvas 隔离脏标记
- 不在 Update 中每帧刷新 UI 文本
8. 音频预算
| 指标 |
限制 |
| 同时播放的 AudioSource 数量 |
≤ 32(平台限制通常为 32~256,保守取低值) |
| BGM 同时层数(自适应音乐) |
≤ 4 层(探索基础层 + 3 个叠加层) |
| 单个 SFX 最大并发实例 |
≤ 4(同一 SFX 类型,超出时最老实例停止) |
| 音频剪辑内存预算 |
≤ 50 MB(所有已加载音频资产总大小) |
音频导入规范
| 类型 |
格式 |
Load Type |
Compression |
| BGM(长曲) |
.ogg |
Streaming |
Vorbis Q50 |
| SFX(短促) |
.wav |
Decompress on Load |
PCM |
| Ambient(环境) |
.ogg |
Streaming |
Vorbis Q40 |
| UI 点击音效 |
.wav |
Decompress on Load |
PCM |
9. Profiler 使用规范
必须加 ProfilerMarker 的位置
性能分析 SOP(每里程碑)
- 深度模式录制 300 帧:在最复杂场景(Boss 战 + 大量弹射物 + Feedback)
- 关注热点:
CPU Usage 视图,过滤 [BaseGames] 标签,检查超时项
- GC 检查:
Memory 视图,确认每帧 GC 分配 ≤ 256 KB
- 物理热点:
Physics 2D 检查 ContactCount,确认碰撞层矩阵设置正确
- 渲染:
Frame Debugger 检查 Draw Call,确认 Atlas 打包正确
内存快照 SOP
- 每个主要场景加载后各取一次内存快照
- 对比两次快照的内存增量,确认无场景加载内存泄漏(Addressable Handle 是否全部释放)
10. 性能检查清单(PR 门禁)
提交 PR 前必须自查以下所有项,全部通过方可合并:
代码层
对象池
物理
UI
音频
Addressables