@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,645 @@
1
+ # Cocos Creator Component System
2
+
3
+ ## Entity-Component (EC) System Overview
4
+
5
+ Cocos Creator uses an Entity-Component (EC) architecture where:
6
+ - **Node** = Entity (game object container)
7
+ - **Component** = Behavior/functionality attached to Node
8
+ - **Scene** = Collection of Node hierarchies
9
+
10
+ ```typescript
11
+ import { _decorator, Component, Node } from 'cc';
12
+ const { ccclass, property } = _decorator;
13
+
14
+ // ✅ EXCELLENT: Complete component structure
15
+ @ccclass('PlayerController')
16
+ export class PlayerController extends Component {
17
+ // @property decorator exposes fields to Inspector
18
+ @property(Node)
19
+ private readonly targetNode: Node | null = null;
20
+
21
+ @property(Number)
22
+ private readonly moveSpeed: number = 100;
23
+
24
+ // Private fields not exposed
25
+ private currentHealth: number = 100;
26
+ private static readonly MAX_HEALTH: number = 100;
27
+
28
+ // Lifecycle methods in execution order:
29
+ // 1. onLoad() - Component initialization
30
+ // 2. start() - After all components loaded
31
+ // 3. onEnable() - When enabled (can be called multiple times)
32
+ // 4. update(dt) - Every frame
33
+ // 5. lateUpdate(dt) - After all update() calls
34
+ // 6. onDisable() - When disabled
35
+ // 7. onDestroy() - Cleanup
36
+ }
37
+ ```
38
+
39
+ ## @ccclass Decorator
40
+
41
+ ```typescript
42
+ import { _decorator, Component } from 'cc';
43
+ const { ccclass } = _decorator;
44
+
45
+ // ✅ EXCELLENT: @ccclass with explicit name
46
+ @ccclass('GameManager')
47
+ export class GameManager extends Component {
48
+ // Component implementation
49
+ }
50
+
51
+ // ✅ GOOD: @ccclass without name (uses class name)
52
+ @ccclass
53
+ export class PlayerController extends Component {
54
+ // Component implementation
55
+ }
56
+
57
+ // ❌ WRONG: Missing @ccclass decorator
58
+ export class GameManager extends Component {
59
+ // Won't work - Cocos can't serialize this component
60
+ }
61
+
62
+ // ❌ WRONG: Not extending Component
63
+ @ccclass('GameManager')
64
+ export class GameManager {
65
+ // Won't work - must extend Component
66
+ }
67
+ ```
68
+
69
+ ## @property Decorator
70
+
71
+ ```typescript
72
+ import { _decorator, Component, Node, Sprite, Label } from 'cc';
73
+ const { ccclass, property } = _decorator;
74
+
75
+ @ccclass('PropertyExamples')
76
+ export class PropertyExamples extends Component {
77
+ // ✅ EXCELLENT: Node reference
78
+ @property(Node)
79
+ private readonly playerNode: Node | null = null;
80
+
81
+ // ✅ EXCELLENT: Component reference
82
+ @property(Sprite)
83
+ private readonly spriteComponent: Sprite | null = null;
84
+
85
+ // ✅ EXCELLENT: Primitive types
86
+ @property(Number)
87
+ private readonly moveSpeed: number = 100;
88
+
89
+ @property(String)
90
+ private readonly playerName: string = 'Player';
91
+
92
+ @property(Boolean)
93
+ private readonly enableDebug: boolean = false;
94
+
95
+ // ✅ EXCELLENT: Array of nodes
96
+ @property([Node])
97
+ private readonly enemyNodes: Node[] = [];
98
+
99
+ // ✅ EXCELLENT: Array of numbers
100
+ @property([Number])
101
+ private readonly levelScores: number[] = [];
102
+
103
+ // ✅ EXCELLENT: Enum property
104
+ @property({ type: Enum(GameState) })
105
+ private currentState: GameState = GameState.LOADING;
106
+
107
+ // ✅ EXCELLENT: Property with custom display name and tooltip
108
+ @property({
109
+ type: Number,
110
+ displayName: 'Movement Speed',
111
+ tooltip: 'Player movement speed in units per second',
112
+ min: 0,
113
+ max: 500,
114
+ step: 10,
115
+ })
116
+ private readonly speed: number = 100;
117
+
118
+ // ✅ EXCELLENT: readonly for properties that shouldn't be reassigned
119
+ @property(Node)
120
+ private readonly targetNode: Node | null = null; // Can't reassign after initialization
121
+
122
+ // Private field (not exposed to Inspector)
123
+ private currentHealth: number = 100;
124
+ }
125
+
126
+ // ❌ WRONG: Property without type
127
+ @property
128
+ private playerNode: Node | null = null; // Won't serialize correctly
129
+
130
+ // ❌ WRONG: Mutable property that should be readonly
131
+ @property(Node)
132
+ private targetNode: Node | null = null; // Should be readonly if not reassigned
133
+ ```
134
+
135
+ ## Component Lifecycle Methods
136
+
137
+ ### 1. onLoad() - Initialization
138
+
139
+ ```typescript
140
+ import { _decorator, Component, Node } from 'cc';
141
+ const { ccclass, property } = _decorator;
142
+
143
+ @ccclass('GameManager')
144
+ export class GameManager extends Component {
145
+ @property(Node)
146
+ private readonly playerNode: Node | null = null;
147
+
148
+ @property(Node)
149
+ private readonly uiRoot: Node | null = null;
150
+
151
+ // ✅ EXCELLENT: onLoad for initialization and validation
152
+ protected onLoad(): void {
153
+ // Validate required references
154
+ if (!this.playerNode) {
155
+ throw new Error('GameManager: playerNode is required');
156
+ }
157
+ if (!this.uiRoot) {
158
+ throw new Error('GameManager: uiRoot is required');
159
+ }
160
+
161
+ // Initialize component state
162
+ this.initializeGameState();
163
+
164
+ // Cache references (DO NOT reference other components yet)
165
+ this.cacheNodeReferences();
166
+ }
167
+
168
+ private initializeGameState(): void {
169
+ // Setup initial state
170
+ }
171
+
172
+ private cacheNodeReferences(): void {
173
+ // Cache child nodes for faster access
174
+ }
175
+ }
176
+
177
+ // ❌ WRONG: Accessing other components in onLoad
178
+ protected onLoad(): void {
179
+ // Don't do this - other components may not be loaded yet
180
+ const playerController = this.playerNode!.getComponent(PlayerController);
181
+ playerController.initialize(); // May be undefined!
182
+ }
183
+
184
+ // ❌ WRONG: Heavy operations in onLoad
185
+ protected onLoad(): void {
186
+ // Avoid expensive operations - onLoad should be fast
187
+ this.loadAllLevelData(); // Should be async in start()
188
+ this.generateProceduralContent(); // Too expensive for onLoad
189
+ }
190
+ ```
191
+
192
+ ### 2. start() - Post-Initialization
193
+
194
+ ```typescript
195
+ import { _decorator, Component, Node } from 'cc';
196
+ const { ccclass, property } = _decorator;
197
+
198
+ @ccclass('PlayerController')
199
+ export class PlayerController extends Component {
200
+ @property(Node)
201
+ private readonly enemyManagerNode: Node | null = null;
202
+
203
+ private enemyManager!: EnemyManager;
204
+
205
+ protected onLoad(): void {
206
+ // Validate references
207
+ if (!this.enemyManagerNode) {
208
+ throw new Error('PlayerController: enemyManagerNode is required');
209
+ }
210
+ }
211
+
212
+ // ✅ EXCELLENT: start() for referencing other components
213
+ protected start(): void {
214
+ // Safe to get components from other nodes now
215
+ const enemyManager = this.enemyManagerNode!.getComponent(EnemyManager);
216
+ if (!enemyManager) {
217
+ throw new Error('EnemyManager component not found');
218
+ }
219
+ this.enemyManager = enemyManager;
220
+
221
+ // Initialize based on other components
222
+ this.setupPlayerBasedOnEnemies();
223
+
224
+ // Start async operations
225
+ this.loadPlayerDataAsync();
226
+ }
227
+
228
+ private setupPlayerBasedOnEnemies(): void {
229
+ const enemyCount = this.enemyManager.getEnemyCount();
230
+ this.adjustDifficultyBasedOnEnemies(enemyCount);
231
+ }
232
+
233
+ private async loadPlayerDataAsync(): Promise<void> {
234
+ // Async loading is safe in start()
235
+ }
236
+ }
237
+
238
+ // ❌ WRONG: Using start() instead of onLoad for validation
239
+ protected start(): void {
240
+ // Too late - might be used before start() is called
241
+ if (!this.playerNode) {
242
+ throw new Error('playerNode is required');
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### 3. onEnable() - Activation
248
+
249
+ ```typescript
250
+ import { _decorator, Component, Node, EventTouch } from 'cc';
251
+ const { ccclass, property } = _decorator;
252
+
253
+ @ccclass('InputHandler')
254
+ export class InputHandler extends Component {
255
+ @property(Node)
256
+ private readonly buttonNode: Node | null = null;
257
+
258
+ // ✅ EXCELLENT: onEnable() for registering listeners
259
+ protected onEnable(): void {
260
+ // Register event listeners
261
+ if (this.buttonNode) {
262
+ this.buttonNode.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
263
+ this.buttonNode.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
264
+ }
265
+
266
+ // Subscribe to global events
267
+ EventManager.on(GameEvent.LEVEL_COMPLETE, this.onLevelComplete, this);
268
+
269
+ // Resume component operations
270
+ this.resumeGameLogic();
271
+ }
272
+
273
+ protected onDisable(): void {
274
+ // ✅ CRITICAL: Always unregister in onDisable
275
+ if (this.buttonNode) {
276
+ this.buttonNode.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
277
+ this.buttonNode.off(Node.EventType.TOUCH_END, this.onTouchEnd, this);
278
+ }
279
+
280
+ EventManager.off(GameEvent.LEVEL_COMPLETE, this.onLevelComplete, this);
281
+
282
+ // Pause component operations
283
+ this.pauseGameLogic();
284
+ }
285
+
286
+ private onTouchStart(event: EventTouch): void {
287
+ // Handle touch
288
+ }
289
+
290
+ private onTouchEnd(event: EventTouch): void {
291
+ // Handle touch end
292
+ }
293
+
294
+ private onLevelComplete(): void {
295
+ // Handle level complete
296
+ }
297
+ }
298
+
299
+ // ❌ WRONG: Registering listeners in onLoad
300
+ protected onLoad(): void {
301
+ // Don't register here - won't be unregistered properly when disabled
302
+ this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
303
+ }
304
+
305
+ // ❌ WRONG: Not unregistering in onDisable
306
+ protected onEnable(): void {
307
+ this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
308
+ }
309
+
310
+ protected onDisable(): void {
311
+ // Missing unregistration - memory leak!
312
+ }
313
+ ```
314
+
315
+ ### 4. update(dt) - Per-Frame Logic
316
+
317
+ ```typescript
318
+ import { _decorator, Component, Node, Vec3 } from 'cc';
319
+ const { ccclass, property } = _decorator;
320
+
321
+ @ccclass('PlayerMovement')
322
+ export class PlayerMovement extends Component {
323
+ @property(Number)
324
+ private readonly moveSpeed: number = 100;
325
+
326
+ private readonly tempVec3: Vec3 = new Vec3();
327
+ private inputDirection: Vec3 = new Vec3(1, 0, 0);
328
+
329
+ // ✅ EXCELLENT: Efficient update implementation
330
+ protected update(dt: number): void {
331
+ // Reuse preallocated vector
332
+ this.node.getPosition(this.tempVec3);
333
+
334
+ // Calculate movement
335
+ this.tempVec3.x += this.inputDirection.x * this.moveSpeed * dt;
336
+ this.tempVec3.y += this.inputDirection.y * this.moveSpeed * dt;
337
+
338
+ // Apply new position
339
+ this.node.setPosition(this.tempVec3);
340
+ }
341
+ }
342
+
343
+ // Throttled expensive operations
344
+ @ccclass('AIController')
345
+ export class AIController extends Component {
346
+ private frameCount: number = 0;
347
+ private static readonly AI_UPDATE_INTERVAL: number = 10;
348
+
349
+ // ✅ EXCELLENT: Throttle expensive operations
350
+ protected update(dt: number): void {
351
+ this.frameCount++;
352
+
353
+ // Cheap operations every frame
354
+ this.moveTowardsTarget(dt);
355
+
356
+ // Expensive AI decisions every 10 frames
357
+ if (this.frameCount % AIController.AI_UPDATE_INTERVAL === 0) {
358
+ this.updateAIDecision();
359
+ }
360
+ }
361
+
362
+ private moveTowardsTarget(dt: number): void {
363
+ // Simple movement calculation
364
+ }
365
+
366
+ private updateAIDecision(): void {
367
+ // Complex AI logic
368
+ }
369
+ }
370
+
371
+ // ❌ WRONG: Allocations in update
372
+ protected update(dt: number): void {
373
+ const currentPos = this.node.position.clone(); // Allocates every frame!
374
+ currentPos.x += this.moveSpeed * dt;
375
+ this.node.setPosition(currentPos);
376
+ }
377
+
378
+ // ❌ WRONG: Expensive operations every frame
379
+ protected update(dt: number): void {
380
+ this.recalculatePathfinding(); // A* algorithm 60 times per second!
381
+ this.updateComplexAI(); // Too expensive for every frame
382
+ }
383
+
384
+ // ❌ WRONG: Component lookups in update
385
+ protected update(dt: number): void {
386
+ const sprite = this.node.getComponent(Sprite); // Cache this in onLoad!
387
+ sprite?.doSomething();
388
+ }
389
+ ```
390
+
391
+ ### 5. lateUpdate(dt) - Post-Update Logic
392
+
393
+ ```typescript
394
+ import { _decorator, Component, Node, Camera } from 'cc';
395
+ const { ccclass, property } = _decorator;
396
+
397
+ @ccclass('CameraFollow')
398
+ export class CameraFollow extends Component {
399
+ @property(Node)
400
+ private readonly target: Node | null = null;
401
+
402
+ @property(Camera)
403
+ private readonly camera: Camera | null = null;
404
+
405
+ // ✅ EXCELLENT: lateUpdate for camera following
406
+ // Runs after all update() calls, ensuring target has moved
407
+ protected lateUpdate(dt: number): void {
408
+ if (!this.target || !this.camera) return;
409
+
410
+ // Follow target position after target has been updated
411
+ const targetPos = this.target.position;
412
+ this.camera.node.setPosition(targetPos.x, targetPos.y, this.camera.node.position.z);
413
+ }
414
+ }
415
+
416
+ // ✅ GOOD: lateUpdate for UI that depends on game state
417
+ @ccclass('HealthBarUpdater')
418
+ export class HealthBarUpdater extends Component {
419
+ @property(Node)
420
+ private readonly healthBar: Node | null = null;
421
+
422
+ private playerHealth: number = 100;
423
+
424
+ // Health is updated in PlayerController.update()
425
+ // UI is updated in lateUpdate() to reflect final health value
426
+ protected lateUpdate(dt: number): void {
427
+ if (!this.healthBar) return;
428
+
429
+ const healthPercentage = this.playerHealth / 100;
430
+ this.healthBar.scale = new Vec3(healthPercentage, 1, 1);
431
+ }
432
+ }
433
+
434
+ // ❌ WRONG: Using lateUpdate for regular logic
435
+ protected lateUpdate(dt: number): void {
436
+ // This should be in update(), not lateUpdate()
437
+ this.movePlayer(dt);
438
+ }
439
+ ```
440
+
441
+ ### 6. onDestroy() - Cleanup
442
+
443
+ ```typescript
444
+ import { _decorator, Component, Node } from 'cc';
445
+ const { ccclass, property } = _decorator;
446
+
447
+ @ccclass('ResourceManager')
448
+ export class ResourceManager extends Component {
449
+ private readonly loadedAssets: Map<string, Asset> = new Map();
450
+ private readonly eventListeners: Set<Function> = new Set();
451
+ private readonly scheduledCallbacks: Set<Function> = new Set();
452
+
453
+ // ✅ EXCELLENT: Complete cleanup in onDestroy
454
+ protected onDestroy(): void {
455
+ // Unregister all event listeners
456
+ this.node.off(Node.EventType.TOUCH_START);
457
+ EventManager.off(GameEvent.LEVEL_COMPLETE, this.onLevelComplete, this);
458
+
459
+ // Clear collections
460
+ this.eventListeners.clear();
461
+ this.scheduledCallbacks.clear();
462
+
463
+ // Release loaded assets
464
+ for (const [id, asset] of this.loadedAssets) {
465
+ asset.decRef();
466
+ }
467
+ this.loadedAssets.clear();
468
+
469
+ // Unschedule all callbacks
470
+ this.unscheduleAllCallbacks();
471
+
472
+ // Clear any references to prevent memory leaks
473
+ this.clearReferences();
474
+ }
475
+
476
+ private clearReferences(): void {
477
+ // Clear any cached references
478
+ }
479
+ }
480
+
481
+ // ❌ WRONG: Missing cleanup
482
+ protected onDestroy(): void {
483
+ // Forgot to unregister events - memory leak!
484
+ // Forgot to release assets - memory leak!
485
+ // Forgot to unschedule callbacks - may cause errors!
486
+ }
487
+
488
+ // ❌ WRONG: Incomplete cleanup
489
+ protected onDestroy(): void {
490
+ this.loadedAssets.clear(); // Cleared map but didn't decRef assets!
491
+ }
492
+ ```
493
+
494
+ ## Component Execution Order
495
+
496
+ ```typescript
497
+ // Execution order when scene loads:
498
+ // 1. All components: onLoad() (in hierarchy order)
499
+ // 2. All components: start() (in hierarchy order)
500
+ // 3. All components: onEnable() (if not already enabled)
501
+ // 4. Begin frame loop:
502
+ // - All components: update(dt)
503
+ // - All components: lateUpdate(dt)
504
+ // 5. When component disabled:
505
+ // - Component: onDisable()
506
+ // 6. When component destroyed:
507
+ // - Component: onDestroy()
508
+
509
+ // ✅ EXCELLENT: Lifecycle method organization
510
+ @ccclass('CompleteLifecycle')
511
+ export class CompleteLifecycle extends Component {
512
+ // 1. INITIALIZATION PHASE
513
+ protected onLoad(): void {
514
+ // Initialize component
515
+ // Validate required references
516
+ // Cache node references
517
+ // DO NOT access other components yet
518
+ }
519
+
520
+ protected start(): void {
521
+ // Access other components (safe now)
522
+ // Start async operations
523
+ // Initialize based on other components
524
+ }
525
+
526
+ // 2. ACTIVATION PHASE
527
+ protected onEnable(): void {
528
+ // Register event listeners
529
+ // Subscribe to global events
530
+ // Resume operations
531
+ }
532
+
533
+ // 3. UPDATE PHASE
534
+ protected update(dt: number): void {
535
+ // Per-frame game logic
536
+ // Movement, input, AI
537
+ // Keep allocations zero
538
+ }
539
+
540
+ protected lateUpdate(dt: number): void {
541
+ // Logic that depends on update()
542
+ // Camera follow, UI updates
543
+ }
544
+
545
+ // 4. DEACTIVATION PHASE
546
+ protected onDisable(): void {
547
+ // Unregister event listeners
548
+ // Unsubscribe from events
549
+ // Pause operations
550
+ }
551
+
552
+ // 5. CLEANUP PHASE
553
+ protected onDestroy(): void {
554
+ // Release resources
555
+ // Clear collections
556
+ // Unschedule callbacks
557
+ // Final cleanup
558
+ }
559
+ }
560
+ ```
561
+
562
+ ## Required Reference Validation
563
+
564
+ ```typescript
565
+ import { _decorator, Component, Node, Sprite } from 'cc';
566
+ const { ccclass, property } = _decorator;
567
+
568
+ @ccclass('RequiredReferences')
569
+ export class RequiredReferences extends Component {
570
+ @property(Node)
571
+ private readonly targetNode: Node | null = null;
572
+
573
+ @property(Sprite)
574
+ private readonly spriteComponent: Sprite | null = null;
575
+
576
+ @property([Node])
577
+ private readonly enemyNodes: Node[] = [];
578
+
579
+ // ✅ EXCELLENT: Validate all required references in onLoad
580
+ protected onLoad(): void {
581
+ if (!this.targetNode) {
582
+ throw new Error('RequiredReferences: targetNode is required');
583
+ }
584
+
585
+ if (!this.spriteComponent) {
586
+ throw new Error('RequiredReferences: spriteComponent is required');
587
+ }
588
+
589
+ if (this.enemyNodes.length === 0) {
590
+ throw new Error('RequiredReferences: at least one enemy node is required');
591
+ }
592
+
593
+ // All references validated - safe to use
594
+ this.initialize();
595
+ }
596
+
597
+ private initialize(): void {
598
+ // Can safely use all references here
599
+ this.targetNode!.setPosition(0, 0, 0);
600
+ this.spriteComponent!.sizeMode = Sprite.SizeMode.CUSTOM;
601
+ }
602
+ }
603
+
604
+ // ❌ WRONG: No validation
605
+ protected onLoad(): void {
606
+ // Assuming references exist - may crash at runtime
607
+ this.targetNode!.setPosition(0, 0, 0);
608
+ }
609
+
610
+ // ❌ WRONG: Silent validation
611
+ protected onLoad(): void {
612
+ if (!this.targetNode) {
613
+ console.error('targetNode is missing'); // Don't just log
614
+ return; // Silent failure
615
+ }
616
+ }
617
+ ```
618
+
619
+ ## Summary: Component System Checklist
620
+
621
+ **Component Structure:**
622
+ - [ ] @ccclass decorator on class
623
+ - [ ] Extends Component base class
624
+ - [ ] @property decorator for Inspector-exposed fields
625
+ - [ ] readonly for properties that aren't reassigned
626
+ - [ ] Access modifiers (public/private/protected)
627
+
628
+ **Lifecycle Implementation:**
629
+ - [ ] onLoad() - Validate required references, initialize state
630
+ - [ ] start() - Access other components, start async operations
631
+ - [ ] onEnable() - Register event listeners
632
+ - [ ] update(dt) - Per-frame logic (zero allocations)
633
+ - [ ] lateUpdate(dt) - Post-update logic (camera, UI)
634
+ - [ ] onDisable() - Unregister event listeners
635
+ - [ ] onDestroy() - Release resources, clear references
636
+
637
+ **Best Practices:**
638
+ - [ ] Validate required @property references in onLoad()
639
+ - [ ] Throw exceptions for missing required references
640
+ - [ ] Cache component references (don't lookup in update)
641
+ - [ ] Zero allocations in update/lateUpdate
642
+ - [ ] Always unregister listeners in onDisable/onDestroy
643
+ - [ ] Use readonly for @property fields when appropriate
644
+
645
+ **The component lifecycle is the foundation of Cocos Creator architecture.**