Game Quality Gates
Mandatory quality standards for all game projects. Based on 70+ real bugs and industry best practices.
Core Principle
Bugs come from cross-state interactions, not individual features.
Each feature works alone; they break in combination.
12 Universal Rules (all games)
1. Single Cleanup Entry Point 🔄
All exit paths (death/level-complete/quit/pause/scene-switch) call ONE cleanup method with options.
CODEBLOCK0
New feature = add one line here. Never scatter cleanup across exits.
2. Respect Active Buffs ⚡
Any code modifying attributes (speed/attack/size/defense) must check for active temporary effects first.
CODEBLOCK1
3. Cache Before Destroy 📦
Extract all needed data before
destroy()/
dispose()/
remove().
CODEBLOCK2
4. Timers Follow Lifecycle ⏰
Track all
setTimeout/
setInterval/
delayedCall/
rAF. Cancel in cleanup.
CODEBLOCK3
5. Frame-Rate Independent Logic 🖥️
Multiply all time-dependent logic by delta. Never assume 60fps.
CODEBLOCK4
- - Phaser
update(time, delta): delta in ms, divide by 1000 - Three.js
clock.getDelta(): returns seconds - Physics: prefer fixed timestep (accumulate delta, step every 16.67ms)
6. Scene Transition = Full Cleanup 🚪
On scene/level switch, clean: event listeners, timers, rAF, audio nodes, object pools, WebGL resources (geometry/material/texture dispose), global state, pending fetch/XHR.
Verify: Chrome DevTools → Memory → heap snapshots before/after transition.
7. Audio Lifecycle 🔊
- - iOS: AudioContext must
resume() inside a user interaction event - INLINECODE10 → pause all audio when hidden, resume when visible
- WeChat WebView:
WeixinJSBridge.invoke('getNetworkType') before autoplay - Pool short sound effects; manage background music separately
8. Input Safety 👆
- - Purchase/consume actions: mutex lock + visual disable
- Attack/fire: cooldown timer
- State toggles (pause/resume): state machine guard
- See Phaser reference for multi-touch pointer ID tracking
9. Save State Persistence 💾
- - Include
version field for migration when game updates - Only persist meaningful state (not particles/temp animations)
- Auto-save on: level end, manual save,
visibilitychange (hidden) - localStorage limit 5MB; use IndexedDB for larger saves
- WeChat: use
wx.setStorage (not localStorage)
10. Network Fault Tolerance 🌐
All network calls (leaderboard/share/ads/sync): 5s timeout + local cache fallback + no blocking game flow on failure.
11. Asset Loading Strategy 📦
Three tiers: critical (startup, <2s) → level assets (loading screen) → deferred (background lazy load).
Fatal error only for critical failures; degrade gracefully for non-critical.
Compression: GLB+Draco, WebP images, MP3+OGG dual audio, sprite atlases.
12. Anti-Cheat Baseline 🛡️
Client is untrusted. Server validates:
- - One-time raid tokens (bind user+timestamp, single use)
- Play duration sanity check (can't finish 30 levels in 3 seconds)
- Score range validation
- See
references/anti-cheat.md for implementation patterns
Engine-Specific Rules
For Phaser-specific rules (pointer ID tracking, physics group cleanup, OVERLAP_BIAS, time vs physics pause):
→ Read INLINECODE16
For Three.js-specific rules (dispose trio, GLB compression pipeline, animation state machine, prune pitfalls):
→ Read references/threejs.md
Pre-Deploy Checklist
Run this checklist before every deployment:
🔴 Universal (all games)
- - [ ] New objects cleaned in
cleanupGameState()? - [ ] New timers cancelled in cleanup?
- [ ] Attribute changes respect active buffs?
- [ ] Data cached before destroy?
- [ ] Movement/animation uses delta time?
- [ ] No memory leaks across scene transitions? (DevTools verify)
- [ ] Audio pauses on background/lock?
- [ ] Purchase/consume has duplicate-click prevention?
- [ ] Save has version number + migration?
- [ ] Network calls have timeout + fallback?
- [ ] Asset load failure has graceful degradation?
- [ ] Critical operations (spend/settle) server-validated?
🟡 Mobile Extra
- - [ ] Multi-touch: each finger tracked independently?
- [ ] iOS AudioContext resumed after first interaction?
- [ ] WeChat WebView compatible (no advanced CSS like backdrop-filter)?
- [ ] Virtual joystick/buttons don't overlap game area?
- [ ] Orientation change handled?
🔵 Engine-specific
→ See
references/phaser.md or
references/threejs.md for engine checklists.
游戏质量关卡
所有游戏项目的强制性质量标准。基于70多个真实bug和行业最佳实践。
核心原则
Bug源自跨状态交互,而非单个功能。
每个功能单独运行时正常,组合使用时就会出问题。
12条通用规则(适用于所有游戏)
1. 单一清理入口 🔄
所有退出路径(死亡/关卡完成/退出/暂停/场景切换)调用一个带选项的清理方法。
js
cleanupGameState(opts) {
// 固定顺序:子对象 → 增益+计时器 → UI → 投射物 → (可选)敌人/控制/事件
}
// 每个退出点:resetBall()、levelComplete()、gameOver()、onShutdown() → 调用此方法
新增功能 = 在此处添加一行。切勿将清理逻辑分散到各个退出点。
2. 尊重活跃增益效果 ⚡
任何修改属性(速度/攻击/尺寸/防御)的代码必须首先检查活跃的临时效果。
js
// ❌ speed = Math.max(speed, BASE_SPEED); // 忽略减速增益
// ✅ speed = Math.max(speed, this._currentBaseSpeed); // 感知增益的基准线
3. 销毁前缓存数据 📦
在调用destroy()/dispose()/remove()之前提取所有需要的数据。
js
const { x, y } = obj; const color = obj.getData(color);
obj.destroy();
spawnParticles(x, y, color);
4. 计时器遵循生命周期 ⏰
追踪所有setTimeout/setInterval/delayedCall/rAF。在清理时取消。
js
this.activeTimers.push(this.time.delayedCall(10000, cb));
// 清理时:this.activeTimers.forEach(t => t.remove(false));
5. 帧率无关逻辑 🖥️
所有依赖时间的逻辑乘以delta。切勿假设60fps。
js
// ✅ player.x += speed * (delta / 1000);
- - Phaser update(time, delta):delta单位为毫秒,除以1000
- Three.js clock.getDelta():返回秒数
- 物理引擎:优先使用固定时间步长(累积delta,每16.67ms步进一次)
6. 场景切换 = 完全清理 🚪
切换场景/关卡时,清理:事件监听器、计时器、rAF、音频节点、对象池、WebGL资源(几何体/材质/纹理释放)、全局状态、待处理的fetch/XHR。
验证:Chrome DevTools → 内存 → 切换前后的堆快照。
7. 音频生命周期 🔊
- - iOS:AudioContext必须在用户交互事件内调用resume()
- visibilitychange → 隐藏时暂停所有音频,可见时恢复
- 微信WebView:自动播放前调用WeixinJSBridge.invoke(getNetworkType)
- 池化短音效;单独管理背景音乐
8. 输入安全 👆
- - 购买/消耗操作:互斥锁 + 视觉禁用
- 攻击/射击:冷却计时器
- 状态切换(暂停/恢复):状态机守卫
- 多点触控指针ID追踪参见Phaser参考
9. 存档状态持久化 💾
- - 包含version字段,用于游戏更新时的迁移
- 仅持久化有意义的状态(不包括粒子/临时动画)
- 自动保存时机:关卡结束、手动保存、visibilitychange(隐藏时)
- localStorage限制5MB;较大存档使用IndexedDB
- 微信:使用wx.setStorage(而非localStorage)
10. 网络容错 🌐
所有网络调用(排行榜/分享/广告/同步):5秒超时 + 本地缓存回退 + 失败时不阻塞游戏流程。
11. 资源加载策略 📦
三个层级:关键资源(启动时,<2秒)→ 关卡资源(加载界面)→ 延迟资源(后台懒加载)。
仅关键资源失败为致命错误;非关键资源优雅降级。
压缩:GLB+Draco、WebP图片、MP3+OGG双音频、精灵图集。
12. 反作弊基线 🛡️
客户端不可信。服务端验证:
- - 一次性突袭令牌(绑定用户+时间戳,单次使用)
- 游戏时长合理性检查(不能在3秒内完成30关)
- 分数范围验证
- 实现模式参见references/anti-cheat.md
引擎特定规则
Phaser特定规则(指针ID追踪、物理组清理、OVERLAP_BIAS、时间vs物理暂停):
→ 阅读references/phaser.md
Three.js特定规则(释放三件套、GLB压缩管线、动画状态机、修剪陷阱):
→ 阅读references/threejs.md
部署前检查清单
每次部署前运行此检查清单:
🔴 通用规则(所有游戏)
- - [ ] 新对象已在cleanupGameState()中清理?
- [ ] 新计时器已在清理时取消?
- [ ] 属性修改尊重活跃增益效果?
- [ ] 销毁前已缓存数据?
- [ ] 移动/动画使用delta时间?
- [ ] 场景切换无内存泄漏?(DevTools验证)
- [ ] 后台/锁屏时音频暂停?
- [ ] 购买/消耗有防重复点击机制?
- [ ] 存档包含版本号+迁移逻辑?
- [ ] 网络调用有超时+回退?
- [ ] 资源加载失败有优雅降级?
- [ ] 关键操作(消费/结算)经服务端验证?
🟡 移动端额外检查
- - [ ] 多点触控:每个手指独立追踪?
- [ ] iOS AudioContext在首次交互后恢复?
- [ ] 微信WebView兼容(无高级CSS如backdrop-filter)?
- [ ] 虚拟摇杆/按钮不与游戏区域重叠?
- [ ] 屏幕方向变化已处理?
🔵 引擎特定检查
→ 引擎检查清单参见references/phaser.md或references/threejs.md