@mclawnet/agent 0.6.20 → 0.6.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/cli.js +63 -0
  2. package/dist/__tests__/checkpoint.test.d.ts +2 -0
  3. package/dist/__tests__/checkpoint.test.d.ts.map +1 -0
  4. package/dist/__tests__/fs-handler-decode.test.d.ts +2 -0
  5. package/dist/__tests__/fs-handler-decode.test.d.ts.map +1 -0
  6. package/dist/__tests__/idle-sweeper.test.d.ts +2 -0
  7. package/dist/__tests__/idle-sweeper.test.d.ts.map +1 -0
  8. package/dist/__tests__/mcp-config.test.d.ts +2 -0
  9. package/dist/__tests__/mcp-config.test.d.ts.map +1 -0
  10. package/dist/__tests__/schedule-runtime-spawn.test.d.ts +2 -0
  11. package/dist/__tests__/schedule-runtime-spawn.test.d.ts.map +1 -0
  12. package/dist/__tests__/schedule-runtime.test.d.ts +2 -0
  13. package/dist/__tests__/schedule-runtime.test.d.ts.map +1 -0
  14. package/dist/__tests__/session-limit.test.d.ts +2 -0
  15. package/dist/__tests__/session-limit.test.d.ts.map +1 -0
  16. package/dist/__tests__/swarm-cli-client.test.d.ts +2 -0
  17. package/dist/__tests__/swarm-cli-client.test.d.ts.map +1 -0
  18. package/dist/__tests__/swarm-control-dispatch.test.d.ts +2 -0
  19. package/dist/__tests__/swarm-control-dispatch.test.d.ts.map +1 -0
  20. package/dist/__tests__/swarm-session-bridge.test.d.ts +2 -0
  21. package/dist/__tests__/swarm-session-bridge.test.d.ts.map +1 -0
  22. package/dist/backend-adapter.d.ts +43 -0
  23. package/dist/backend-adapter.d.ts.map +1 -1
  24. package/dist/checkpoint.d.ts +67 -0
  25. package/dist/checkpoint.d.ts.map +1 -0
  26. package/dist/{chunk-RIK7IXSW.js → chunk-WJWCYGLQ.js} +1130 -147
  27. package/dist/chunk-WJWCYGLQ.js.map +1 -0
  28. package/dist/errors.d.ts +40 -0
  29. package/dist/errors.d.ts.map +1 -0
  30. package/dist/fs-handler.d.ts.map +1 -1
  31. package/dist/hub-connection.d.ts +13 -0
  32. package/dist/hub-connection.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/schedule-runtime.d.ts +125 -0
  35. package/dist/schedule-runtime.d.ts.map +1 -0
  36. package/dist/session-manager.d.ts +102 -0
  37. package/dist/session-manager.d.ts.map +1 -1
  38. package/dist/skill-loader.d.ts +20 -0
  39. package/dist/skill-loader.d.ts.map +1 -1
  40. package/dist/start.d.ts +2 -0
  41. package/dist/start.d.ts.map +1 -1
  42. package/dist/start.js +1 -1
  43. package/dist/swarm-cli-client.d.ts +24 -0
  44. package/dist/swarm-cli-client.d.ts.map +1 -0
  45. package/dist/swarm-cli-client.js +83 -0
  46. package/dist/swarm-cli-client.js.map +1 -0
  47. package/dist/swarm-control-dispatch.d.ts +47 -0
  48. package/dist/swarm-control-dispatch.d.ts.map +1 -0
  49. package/dist/swarm-session-bridge.d.ts +22 -0
  50. package/dist/swarm-session-bridge.d.ts.map +1 -0
  51. package/package.json +6 -4
  52. package/skills/cocos-creator-3x-cn/SKILL.md +475 -0
  53. package/skills/cocos-creator-3x-cn/references/framework/asset-management.md +322 -0
  54. package/skills/cocos-creator-3x-cn/references/framework/component-system.md +348 -0
  55. package/skills/cocos-creator-3x-cn/references/framework/event-patterns.md +410 -0
  56. package/skills/cocos-creator-3x-cn/references/framework/playable-optimization.md +257 -0
  57. package/skills/cocos-creator-3x-cn/references/language/performance.md +363 -0
  58. package/skills/cocos-creator-3x-cn/references/language/quality-hygiene.md +307 -0
  59. package/skills/cocos-creator-3x-cn/references/review/architecture-review.md +183 -0
  60. package/skills/cocos-creator-3x-cn/references/review/quality-review.md +251 -0
  61. package/skills/cocos-performance-optimizer/SKILL.md +214 -0
  62. package/skills/game-development/2d-games/SKILL.md +129 -0
  63. package/skills/game-development/3d-games/SKILL.md +145 -0
  64. package/skills/game-development/SKILL.md +175 -0
  65. package/skills/game-development/game-art/SKILL.md +195 -0
  66. package/skills/game-development/game-audio/SKILL.md +200 -0
  67. package/skills/game-development/game-design/SKILL.md +139 -0
  68. package/skills/game-development/mobile-games/SKILL.md +118 -0
  69. package/skills/game-development/multiplayer/SKILL.md +142 -0
  70. package/skills/game-development/pc-games/SKILL.md +154 -0
  71. package/skills/game-development/vr-ar/SKILL.md +133 -0
  72. package/skills/game-development/web-games/SKILL.md +160 -0
  73. package/skills/game-engine/SKILL.md +140 -0
  74. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  75. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  76. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  77. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  78. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  79. package/skills/game-engine/references/3d-web-games.md +754 -0
  80. package/skills/game-engine/references/algorithms.md +843 -0
  81. package/skills/game-engine/references/basics.md +343 -0
  82. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  83. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  84. package/skills/game-engine/references/game-publishing.md +352 -0
  85. package/skills/game-engine/references/techniques.md +894 -0
  86. package/skills/game-engine/references/terminology.md +354 -0
  87. package/skills/game-engine/references/web-apis.md +1394 -0
  88. package/skills/theone-cocos-standards/SKILL.md +557 -0
  89. package/skills/theone-cocos-standards/references/framework/component-system.md +645 -0
  90. package/skills/theone-cocos-standards/references/framework/event-patterns.md +433 -0
  91. package/skills/theone-cocos-standards/references/framework/playable-optimization.md +429 -0
  92. package/skills/theone-cocos-standards/references/framework/size-optimization.md +308 -0
  93. package/skills/theone-cocos-standards/references/language/modern-typescript.md +658 -0
  94. package/skills/theone-cocos-standards/references/language/performance.md +580 -0
  95. package/skills/theone-cocos-standards/references/language/quality-hygiene.md +582 -0
  96. package/skills/theone-cocos-standards/references/review/architecture-review.md +250 -0
  97. package/skills/theone-cocos-standards/references/review/performance-review.md +288 -0
  98. package/skills/theone-cocos-standards/references/review/quality-review.md +239 -0
  99. package/dist/chunk-RIK7IXSW.js.map +0 -1
@@ -0,0 +1,363 @@
1
+ # 性能优化指南 — Cocos Creator 3.8
2
+
3
+ > 📖 本文件为 `cocos-creator-3x-cn` 技能参考文件,提供性能优化的全面指导。
4
+
5
+ ---
6
+
7
+ ## 1. 性能优化层次
8
+
9
+ ```
10
+ ┌─────────────────────────────────────┐
11
+ │ 架构层优化 (影响最大) │
12
+ │ 对象池、资源管理、加载策略 │
13
+ ├─────────────────────────────────────┤
14
+ │ 渲染层优化 │
15
+ │ Draw Call、合批、纹理压缩 │
16
+ ├─────────────────────────────────────┤
17
+ │ 逻辑层优化 │
18
+ │ 算法、缓存、调度频率 │
19
+ ├─────────────────────────────────────┤
20
+ │ 内存层优化 (基础保障) │
21
+ │ GC 减压、引用管理、泄漏预防 │
22
+ └─────────────────────────────────────┘
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 2. 渲染性能
28
+
29
+ ### 2.1 Draw Call 优化
30
+
31
+ ```typescript
32
+ // 1. 使用图集(SpriteAtlas)合并碎图
33
+ // 同一图集 + 同一材质 + 相邻渲染顺序 = 自动合批
34
+
35
+ // 2. 合理规划渲染层级,避免合批打断
36
+ // ❌ 打断合批的排列:
37
+ // Sprite(Atlas_A) → Sprite(Atlas_B) → Sprite(Atlas_A)
38
+ // ✅ 友好排列:
39
+ // Sprite(Atlas_A) → Sprite(Atlas_A) → Sprite(Atlas_B)
40
+
41
+ // 3. 减少 Mask 使用(每个 Mask 增加 2 个 draw call)
42
+
43
+ // 4. Label 优化
44
+ // - 使用 BMFont 替代系统字体
45
+ // - 静态文本使用 BITMAP 缓存模式
46
+ // - 频繁更新的文本使用 CHAR 缓存模式
47
+ ```
48
+
49
+ ### 2.2 纹理优化
50
+
51
+ ```
52
+ 纹理规范:
53
+ - 使用 2 的幂次方尺寸(256/512/1024/2048)
54
+ - 尽量使用图集而非散图
55
+ - 大面积背景考虑使用 JPEG + 单独 Alpha 通道
56
+ - 移动端使用压缩纹理格式(ASTC/ETC2/PVRTC)
57
+ - UI 图集建议不超过 2048x2048
58
+ ```
59
+
60
+ ### 2.3 节点树优化
61
+
62
+ ```typescript
63
+ // 1. 不可见节点设为 inactive(跳过整棵子树)
64
+ node.active = false; // ✅ 比 opacity = 0 更高效
65
+
66
+ // 2. 减少节点树深度
67
+ // 扁平化结构比深层嵌套更高效
68
+
69
+ // 3. 避免频繁增删节点
70
+ // 使用对象池 + active 控制显隐
71
+ ```
72
+
73
+ ---
74
+
75
+ ## 3. 内存优化
76
+
77
+ ### 3.1 对象池模式
78
+
79
+ ```typescript
80
+ import { NodePool, instantiate, Prefab, Node } from 'cc';
81
+
82
+ class ObjectPool {
83
+ private _pool: NodePool;
84
+ private _prefab: Prefab;
85
+
86
+ constructor(prefab: Prefab, name: string, initCount = 10) {
87
+ this._prefab = prefab;
88
+ this._pool = new NodePool(name);
89
+ // 预热
90
+ for (let i = 0; i < initCount; i++) {
91
+ this._pool.put(instantiate(prefab));
92
+ }
93
+ }
94
+
95
+ public get(): Node {
96
+ return this._pool.size() > 0
97
+ ? this._pool.get()!
98
+ : instantiate(this._prefab);
99
+ }
100
+
101
+ public put(node: Node): void {
102
+ this._pool.put(node);
103
+ }
104
+
105
+ public clear(): void {
106
+ this._pool.clear();
107
+ }
108
+
109
+ public get size(): number {
110
+ return this._pool.size();
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### 3.2 避免 GC 抖动
116
+
117
+ ```typescript
118
+ // ❌ 每帧创建临时对象
119
+ protected update(dt: number): void {
120
+ const dir = new Vec3(1, 0, 0);
121
+ Vec3.multiplyScalar(dir, dir, this.speed * dt);
122
+ this.node.position = this.node.position.add(dir);
123
+ }
124
+
125
+ // ✅ 复用预分配对象
126
+ private _tempDir = new Vec3();
127
+ private _tempPos = new Vec3();
128
+
129
+ protected update(dt: number): void {
130
+ Vec3.set(this._tempDir, 1, 0, 0);
131
+ Vec3.multiplyScalar(this._tempDir, this._tempDir, this.speed * dt);
132
+ Vec3.add(this._tempPos, this.node.position, this._tempDir);
133
+ this.node.setPosition(this._tempPos);
134
+ }
135
+ ```
136
+
137
+ ### 3.3 数组操作优化
138
+
139
+ ```typescript
140
+ // ❌ 频繁 splice 删除(触发数组重排)
141
+ for (let i = arr.length - 1; i >= 0; i--) {
142
+ if (arr[i].dead) arr.splice(i, 1);
143
+ }
144
+
145
+ // ✅ 交换删除法(无需重排)
146
+ function swapRemove<T>(arr: T[], index: number): void {
147
+ arr[index] = arr[arr.length - 1];
148
+ arr.pop();
149
+ }
150
+
151
+ // ✅ 标记-清除(批量处理)
152
+ const alive: Enemy[] = [];
153
+ for (const e of enemies) {
154
+ if (!e.dead) alive.push(e);
155
+ }
156
+ enemies.length = 0;
157
+ enemies.push(...alive);
158
+ ```
159
+
160
+ ### 3.4 字符串优化
161
+
162
+ ```typescript
163
+ // ❌ 频繁字符串拼接
164
+ let result = '';
165
+ for (const item of items) {
166
+ result += item.name + ',';
167
+ }
168
+
169
+ // ✅ 使用数组 join
170
+ const parts: string[] = [];
171
+ for (const item of items) {
172
+ parts.push(item.name);
173
+ }
174
+ const result = parts.join(',');
175
+ ```
176
+
177
+ ---
178
+
179
+ ## 4. 逻辑优化
180
+
181
+ ### 4.1 更新频率控制
182
+
183
+ ```typescript
184
+ // ❌ 所有逻辑都放 update(每帧执行)
185
+ protected update(dt: number): void {
186
+ this.checkEnemies(); // 不需要每帧
187
+ this.updateUI(); // 不需要每帧
188
+ this.movePlayer(dt); // 需要每帧
189
+ }
190
+
191
+ // ✅ 低频逻辑使用 schedule
192
+ protected start(): void {
193
+ this.schedule(this.checkEnemies, 0.5); // 每 0.5 秒
194
+ this.schedule(this.updateUI, 0.1); // 每 0.1 秒
195
+ }
196
+
197
+ protected update(dt: number): void {
198
+ this.movePlayer(dt); // 仅高频逻辑
199
+ }
200
+ ```
201
+
202
+ ### 4.2 计算缓存
203
+
204
+ ```typescript
205
+ // ❌ 重复计算
206
+ update() {
207
+ const dist = Vec3.distance(this.node.position, this.target.position);
208
+ if (dist < 100) { /* ... */ }
209
+ }
210
+
211
+ // ✅ 使用距离平方比较(避免 sqrt)
212
+ private readonly RANGE_SQ = 100 * 100;
213
+ update() {
214
+ const distSq = Vec3.squaredDistance(this.node.position, this.target.position);
215
+ if (distSq < this.RANGE_SQ) { /* ... */ }
216
+ }
217
+ ```
218
+
219
+ ### 4.3 查找优化
220
+
221
+ ```typescript
222
+ // ❌ 每帧 find/getComponent
223
+ protected update(): void {
224
+ const player = find('Canvas/Player');
225
+ const hp = player?.getComponent(HealthBar);
226
+ }
227
+
228
+ // ✅ onLoad/start 中缓存
229
+ private _player: Node | null = null;
230
+ private _hp: HealthBar | null = null;
231
+
232
+ protected start(): void {
233
+ this._player = find('Canvas/Player');
234
+ this._hp = this._player?.getComponent(HealthBar) ?? null;
235
+ }
236
+ ```
237
+
238
+ ### 4.4 条件判断优化
239
+
240
+ ```typescript
241
+ // ✅ 提前返回减少嵌套
242
+ protected update(dt: number): void {
243
+ if (!this._isPlaying) return;
244
+ if (!this._target?.isValid) return;
245
+
246
+ // 核心逻辑
247
+ }
248
+
249
+ // ✅ 高概率条件前置
250
+ if (commonCase) {
251
+ // 最可能的分支
252
+ } else if (lessCommon) {
253
+ // ...
254
+ } else {
255
+ // 极少情况
256
+ }
257
+ ```
258
+
259
+ ---
260
+
261
+ ## 5. 加载性能
262
+
263
+ ### 5.1 资源预加载
264
+
265
+ ```typescript
266
+ // 场景预加载
267
+ director.preloadScene('GameScene', (err) => {
268
+ // 预加载完成,切换更快
269
+ director.loadScene('GameScene');
270
+ });
271
+
272
+ // 资源预加载
273
+ resources.preload('prefabs/boss', Prefab);
274
+ resources.preload('audio/battle', AudioClip);
275
+ ```
276
+
277
+ ### 5.2 分帧加载
278
+
279
+ ```typescript
280
+ // 大量节点分帧创建,避免单帧卡顿
281
+ private async createItems(count: number, prefab: Prefab, parent: Node): Promise<void> {
282
+ const BATCH = 5; // 每帧创建 5 个
283
+ for (let i = 0; i < count; i++) {
284
+ const node = instantiate(prefab);
285
+ parent.addChild(node);
286
+ if ((i + 1) % BATCH === 0) {
287
+ await this.nextFrame(); // 等待下一帧
288
+ }
289
+ }
290
+ }
291
+
292
+ private nextFrame(): Promise<void> {
293
+ return new Promise(resolve => {
294
+ this.scheduleOnce(resolve, 0);
295
+ });
296
+ }
297
+ ```
298
+
299
+ ### 5.3 Bundle 按需加载
300
+
301
+ ```typescript
302
+ // 根据游戏进度加载资源
303
+ private async loadLevel(level: number): Promise<void> {
304
+ return new Promise<void>((resolve, reject) => {
305
+ assetManager.loadBundle(`level_${level}`, (err, bundle) => {
306
+ if (err) { reject(err); return; }
307
+ bundle.loadScene('main', (err, scene) => {
308
+ if (err) { reject(err); return; }
309
+ director.runScene(scene);
310
+ resolve();
311
+ });
312
+ });
313
+ });
314
+ }
315
+ ```
316
+
317
+ ---
318
+
319
+ ## 6. 性能监测
320
+
321
+ ### 6.1 帧率监控
322
+
323
+ ```typescript
324
+ import { director, game } from 'cc';
325
+
326
+ // 设置目标帧率
327
+ game.frameRate = 60;
328
+
329
+ // 获取当前帧间隔
330
+ const dt = director.getDeltaTime();
331
+ const currentFPS = 1 / dt;
332
+ ```
333
+
334
+ ### 6.2 调试工具
335
+
336
+ ```
337
+ Chrome DevTools 性能分析:
338
+ 1. Performance 面板 → 录制游戏片段
339
+ 2. 查看 Scripting/Rendering/GC 时间占比
340
+ 3. 关注长任务(>16ms)
341
+
342
+ Cocos Creator 调试面板:
343
+ - 菜单栏 → 开发者 → 调试面板
344
+ - 查看 Draw Call、Node Count、Triangles 等指标
345
+ ```
346
+
347
+ ---
348
+
349
+ ## 7. 性能优化清单
350
+
351
+ | 优先级 | 检查项 | 目标 |
352
+ |--------|--------|------|
353
+ | P0 | Draw Call 数量 | 2D 游戏 < 50, 可试玩广告 < 30 |
354
+ | P0 | 帧率稳定性 | ≥ 30fps, 目标 60fps |
355
+ | P0 | 内存占用 | 移动端 < 150MB |
356
+ | P1 | 图集使用率 | > 70% 使用率 |
357
+ | P1 | 对象池覆盖 | 频繁创建/销毁的节点使用池 |
358
+ | P1 | 事件泄漏 | on/off 严格配对 |
359
+ | P2 | 临时对象分配 | update 中零分配 |
360
+ | P2 | 查找调用缓存 | find/getComponent 缓存结果 |
361
+ | P2 | 低频逻辑分离 | 从 update 移到 schedule |
362
+ | P3 | 资源按需加载 | 使用 Bundle 分模块 |
363
+ | P3 | 压缩纹理 | 启用平台对应格式 |
@@ -0,0 +1,307 @@
1
+ # TypeScript 代码质量与卫生规范 — Cocos Creator 3.8
2
+
3
+ > 📖 本文件为 `cocos-creator-3x-cn` 技能参考文件,提供 TypeScript 代码质量规范。
4
+
5
+ ---
6
+
7
+ ## 1. 导入规范
8
+
9
+ ### 1.1 模块导入
10
+
11
+ ```typescript
12
+ // ✅ 正确:从 'cc' 统一导入
13
+ import { _decorator, Component, Node, Vec3, Sprite, SpriteFrame, resources } from 'cc';
14
+ const { ccclass, property } = _decorator;
15
+
16
+ // ✅ 正确:环境宏从 'cc/env' 导入
17
+ import { DEBUG, EDITOR, PREVIEW, BUILD } from 'cc/env';
18
+
19
+ // ❌ 错误:不使用 cc. 全局前缀(3.x 中不存在)
20
+ // const node = new cc.Node();
21
+
22
+ // ✅ 按需导入第三方库
23
+ import { someUtil } from '../utils/SomeUtil';
24
+ ```
25
+
26
+ ### 1.2 导入顺序
27
+
28
+ ```typescript
29
+ // 1. 引擎核心模块
30
+ import { _decorator, Component, Node, Vec3 } from 'cc';
31
+ import { DEBUG } from 'cc/env';
32
+
33
+ // 2. 引擎 UI/渲染组件
34
+ import { Sprite, Label, Button } from 'cc';
35
+
36
+ // 3. 项目公共模块
37
+ import { EventDispatcher } from '../common/EventDispatcher';
38
+ import { GameConfig } from '../config/GameConfig';
39
+
40
+ // 4. 当前模块相关
41
+ import { PlayerData } from './PlayerData';
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 2. 命名规范
47
+
48
+ | 类别 | 规范 | 示例 |
49
+ |------|------|------|
50
+ | 类名 | PascalCase | `PlayerController`, `GameManager` |
51
+ | cc 类名 | 与类名一致 | `@ccclass('PlayerController')` |
52
+ | 方法名 | camelCase | `moveForward()`, `onTouchStart()` |
53
+ | 属性名 | camelCase | `moveSpeed`, `targetNode` |
54
+ | 私有成员 | _camelCase | `_isMoving`, `_cachedPos` |
55
+ | 常量 | UPPER_SNAKE_CASE | `MAX_HEALTH`, `MOVE_SPEED` |
56
+ | 枚举名 | PascalCase | `GameState`, `Direction` |
57
+ | 枚举值 | PascalCase | `GameState.Playing` |
58
+ | 事件名 | kebab-case | `'game-over'`, `'level-up'` |
59
+ | 文件名 | PascalCase (与类名一致) | `PlayerController.ts` |
60
+
61
+ ---
62
+
63
+ ## 3. 类型安全
64
+
65
+ ### 3.1 属性声明
66
+
67
+ ```typescript
68
+ // ✅ 使用联合类型 + null 初始值
69
+ @property(Node)
70
+ targetNode: Node | null = null;
71
+
72
+ // ✅ 使用非空断言(确保在编辑器中赋值)
73
+ @property(Sprite)
74
+ readonly sprite!: Sprite;
75
+
76
+ // ✅ 数组初始化
77
+ @property({ type: [Node] })
78
+ waypoints: Node[] = [];
79
+
80
+ // ❌ 避免 any
81
+ // @property
82
+ // data: any = null;
83
+ ```
84
+
85
+ ### 3.2 Null 安全
86
+
87
+ ```typescript
88
+ // ✅ 使用可选链
89
+ const pos = this.targetNode?.position;
90
+ const sprite = this.node.getComponent(Sprite)?.spriteFrame;
91
+
92
+ // ✅ 空值合并
93
+ const speed = this.config?.speed ?? 10;
94
+
95
+ // ✅ 提前返回
96
+ private onTouchStart(event: EventTouch): void {
97
+ if (!this.targetNode) return;
98
+ // 安全使用 this.targetNode
99
+ }
100
+
101
+ // ✅ 非空断言(仅在确信不为空时)
102
+ const label = this.getComponent(Label)!;
103
+ ```
104
+
105
+ ### 3.3 枚举使用
106
+
107
+ ```typescript
108
+ import { Enum } from 'cc';
109
+
110
+ // 需要在编辑器面板显示的枚举
111
+ enum GameState {
112
+ Idle = 0,
113
+ Playing = 1,
114
+ Paused = 2,
115
+ GameOver = 3,
116
+ }
117
+ Enum(GameState); // 注册到 cc 枚举系统
118
+
119
+ @ccclass('GameManager')
120
+ export class GameManager extends Component {
121
+ @property({ type: GameState })
122
+ state: GameState = GameState.Idle;
123
+ }
124
+
125
+ // 仅代码使用的枚举,可用 const enum(编译后内联为数值)
126
+ const enum Direction {
127
+ Up = 0,
128
+ Down = 1,
129
+ Left = 2,
130
+ Right = 3,
131
+ }
132
+ ```
133
+
134
+ ---
135
+
136
+ ## 4. 生命周期卫生
137
+
138
+ ### 4.1 事件监听配对
139
+
140
+ ```typescript
141
+ // ✅ 正确:onEnable / onDisable 严格配对
142
+ protected onEnable(): void {
143
+ input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
144
+ input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
145
+ this.node.on(Node.EventType.TOUCH_START, this.onNodeTouch, this);
146
+ }
147
+
148
+ protected onDisable(): void {
149
+ input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
150
+ input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
151
+ this.node.off(Node.EventType.TOUCH_START, this.onNodeTouch, this);
152
+ }
153
+ ```
154
+
155
+ ### 4.2 资源引用管理
156
+
157
+ ```typescript
158
+ @ccclass('ResourceHolder')
159
+ export class ResourceHolder extends Component {
160
+ private _loadedAssets: Asset[] = [];
161
+
162
+ public loadAsset(path: string, type: typeof Asset): void {
163
+ resources.load(path, type, (err, asset) => {
164
+ if (err) return;
165
+ asset.addRef();
166
+ this._loadedAssets.push(asset);
167
+ });
168
+ }
169
+
170
+ protected onDestroy(): void {
171
+ // 释放所有持有的资源
172
+ for (const asset of this._loadedAssets) {
173
+ asset.decRef();
174
+ }
175
+ this._loadedAssets.length = 0;
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### 4.3 定时器清理
181
+
182
+ ```typescript
183
+ protected onDestroy(): void {
184
+ this.unscheduleAllCallbacks();
185
+ Tween.stopAllByTarget(this.node);
186
+ }
187
+ ```
188
+
189
+ ---
190
+
191
+ ## 5. 代码组织
192
+
193
+ ### 5.1 文件结构
194
+
195
+ ```
196
+ assets/scripts/
197
+ ├── common/ # 公共工具
198
+ │ ├── EventDispatcher.ts
199
+ │ ├── ObjectPool.ts
200
+ │ └── Utils.ts
201
+ ├── config/ # 配置
202
+ │ ├── GameConfig.ts
203
+ │ └── AudioConfig.ts
204
+ ├── manager/ # 管理器(单例)
205
+ │ ├── GameManager.ts
206
+ │ ├── AudioManager.ts
207
+ │ └── UIManager.ts
208
+ ├── ui/ # UI 组件
209
+ │ ├── HUD.ts
210
+ │ ├── ResultPanel.ts
211
+ │ └── LoadingScreen.ts
212
+ ├── game/ # 游戏逻辑
213
+ │ ├── Player.ts
214
+ │ ├── Enemy.ts
215
+ │ └── Bullet.ts
216
+ └── data/ # 数据模型
217
+ ├── PlayerData.ts
218
+ └── LevelData.ts
219
+ ```
220
+
221
+ ### 5.2 单一职责
222
+
223
+ ```typescript
224
+ // ✅ 每个组件职责单一
225
+ @ccclass('PlayerMovement')
226
+ export class PlayerMovement extends Component {
227
+ // 只负责移动逻辑
228
+ }
229
+
230
+ @ccclass('PlayerAnimation')
231
+ export class PlayerAnimation extends Component {
232
+ // 只负责动画控制
233
+ }
234
+
235
+ @ccclass('PlayerHealth')
236
+ export class PlayerHealth extends Component {
237
+ // 只负责血量管理
238
+ }
239
+
240
+ // ❌ 避免上帝组件
241
+ // class PlayerController { /* 包含移动+动画+血量+UI+音效 */ }
242
+ ```
243
+
244
+ ### 5.3 访问修饰符
245
+
246
+ ```typescript
247
+ @ccclass('Example')
248
+ export class Example extends Component {
249
+ // public: 编辑器属性 + 外部 API
250
+ @property
251
+ public readonly speed: number = 10;
252
+
253
+ // protected: 子类可访问
254
+ protected _state: GameState = GameState.Idle;
255
+
256
+ // private: 仅内部使用
257
+ private _timer: number = 0;
258
+ private _cache: Map<string, any> = new Map();
259
+
260
+ // public 方法:对外接口
261
+ public startGame(): void { /* ... */ }
262
+
263
+ // private 方法:内部实现
264
+ private calculateScore(): number { /* ... */ return 0; }
265
+ }
266
+ ```
267
+
268
+ ---
269
+
270
+ ## 6. 常见代码异味
271
+
272
+ | 异味 | 问题 | 修正 |
273
+ |------|------|------|
274
+ | `as any` 类型断言 | 绕过类型检查 | 使用正确类型或类型守卫 |
275
+ | 魔法数字 | 可读性差 | 提取为命名常量 |
276
+ | 深层嵌套回调 | 可读性差 | 使用 Promise 或 async/await |
277
+ | 超长函数 (>50行) | 难以维护 | 拆分为小函数 |
278
+ | 重复代码 | 维护成本高 | 提取公共方法/基类 |
279
+ | `console.log` 残留 | 影响性能和包体 | 使用 `DEBUG` 宏包裹 |
280
+ | 未处理 `err` 参数 | 静默失败 | 添加错误处理 |
281
+ | 硬编码路径字符串 | 易出错 | 提取为常量/配置 |
282
+
283
+ ---
284
+
285
+ ## 7. 调试规范
286
+
287
+ ```typescript
288
+ import { DEBUG } from 'cc/env';
289
+
290
+ // ✅ 使用 DEBUG 宏包裹调试代码
291
+ if (DEBUG) {
292
+ console.log('Player position:', this.node.position);
293
+ }
294
+
295
+ // ✅ 封装日志工具
296
+ class Logger {
297
+ public static log(msg: string, ...args: any[]): void {
298
+ if (DEBUG) console.log(`[Game] ${msg}`, ...args);
299
+ }
300
+ public static warn(msg: string, ...args: any[]): void {
301
+ if (DEBUG) console.warn(`[Game] ${msg}`, ...args);
302
+ }
303
+ public static error(msg: string, ...args: any[]): void {
304
+ console.error(`[Game] ${msg}`, ...args); // 错误始终输出
305
+ }
306
+ }
307
+ ```