game-performancelisted
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# 游戏性能优化
## 何时用
- 帧率下降、卡顿、游戏线程或渲染线程占用异常时。
- 准备实现高频生成/销毁对象(子弹、特效、敌人)的功能之前。
- Draw Call 过多、移动端发热、GPU 占用异常时。
- 大地图、远景渲染、大量 AI 同屏出现时。
- 包体超标、加载时间过长、运行时内存持续增长时。
## 核心规则
### 1. 先 Profile,不凭感觉优化
**规则:** 发现性能问题的第一步是开引擎 Profiler,定位瓶颈究竟在 CPU 游戏线程、渲染线程、GPU 还是 GC;确认瓶颈后再动手,不猜测。
**为什么——真实会犯的错:**
帧率跌到 40 fps,直觉上以为是 Draw Call 太多,花两天做合批,结果 Profiler 一开,GPU 占用 30%,真正的问题是游戏线程里每帧跑了一段 O(n²) 的敌人感知逻辑。两天白费,且合批引入了新的材质管理复杂度。还有一种常见误判:以为是 GC 卡顿,把所有对象都对象池化,结果真正问题是 Shader 编译 spike,池化没有任何帮助反而增加了大量代码复杂度。
**怎么做:**
- Unity:Profiler 窗口(CPU/GPU/Memory 标签),配合 Frame Debugger 看 Draw Call。
- Unreal:Unreal Insights 或 `stat unit`/`stat fps`/`stat game`/`stat gpu` 命令,GPU Visualizer 看渲染���时。
- Godot:Debugger → Monitors 面板,`RenderingServer.get_rendering_info()` 查 Draw Call 数量。
- 优化前记录基准帧时,优化后对比,用数据说话,不用"感觉快了"。
---
### 2. 对象池:高频生成对象一律复用
**规则:** 子弹、爆炸特效、伤害数字、拾取物等生命周期短且高频生成的对象,必须用对象池复用;禁止在游戏主循环中对这类对象频繁 new/instantiate + destroy/queue_free。
**为什么——真实会犯的错:**
射击游戏里每颗子弹都 `Instantiate` + `Destroy`,1 秒 20 发,C# 的 GC 每隔几秒做一次 Gen0 收集,帧时间 spike 到 50ms,玩家感知到明显卡顿。在移动端这个问题更严重,GC pause 动辄 100ms+。关键是这种卡顿**只在长时间游戏后出现**,开发期单次测试根本发现不了,上线后玩家投诉才暴露。
**怎么做:**
- 维护一个对象列表/队列,按需取出(激活)、用完归还(停用),不真正销毁。
- 池的初始大小根据峰值需求预估,宁可多初始化,避免运行时扩容带来的 spike。
- 归还时重置对象状态(位置、速度、生命值、粒子系统),确保下次取出是干净状态。
- Unity 4.7+:`ObjectPool<T>` 内置实现;Godot:手动维护 `Array` 池;Unreal:Actor 池或配合 Niagara 的 GPU 粒子。
---
### 3. 降 Draw Call:合批、图集、共享材质
**规则:** 减少 Draw Call 的核心是让渲染器批处理更多对象:相同材质/纹理的对象合批;UI 元素用图集;避免运行时频繁修改材质参数导致 batch 断开。
**为什么——真实会犯的错:**
UI 界面上 200 个图标,每个图标用独立的 Spri