@mclawnet/agent 0.6.19 → 0.6.21

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 (66) hide show
  1. package/dist/{chunk-RO47ET27.js → chunk-M2CDVPQF.js} +2 -2
  2. package/dist/{chunk-CBZIH6FY.js → chunk-PJ5M6Q36.js} +2 -2
  3. package/dist/chunk-PJ5M6Q36.js.map +1 -0
  4. package/dist/{chunk-MSDIRBXF.js → chunk-RIK7IXSW.js} +2 -2
  5. package/dist/index.js +2 -2
  6. package/dist/{linux-6AR7SXHW.js → linux-IHA4O633.js} +3 -3
  7. package/dist/{macos-BTP5JW3U.js → macos-G4VK2253.js} +8 -3
  8. package/dist/macos-G4VK2253.js.map +1 -0
  9. package/dist/service/index.js +5 -5
  10. package/dist/service/macos.d.ts.map +1 -1
  11. package/dist/start.js +2 -2
  12. package/dist/{windows-IQNSUMN6.js → windows-P6U3JLUZ.js} +3 -3
  13. package/package.json +4 -4
  14. package/skills/cocos-creator-3x-cn/SKILL.md +475 -0
  15. package/skills/cocos-creator-3x-cn/references/framework/asset-management.md +322 -0
  16. package/skills/cocos-creator-3x-cn/references/framework/component-system.md +348 -0
  17. package/skills/cocos-creator-3x-cn/references/framework/event-patterns.md +410 -0
  18. package/skills/cocos-creator-3x-cn/references/framework/playable-optimization.md +257 -0
  19. package/skills/cocos-creator-3x-cn/references/language/performance.md +363 -0
  20. package/skills/cocos-creator-3x-cn/references/language/quality-hygiene.md +307 -0
  21. package/skills/cocos-creator-3x-cn/references/review/architecture-review.md +183 -0
  22. package/skills/cocos-creator-3x-cn/references/review/quality-review.md +251 -0
  23. package/skills/cocos-performance-optimizer/SKILL.md +214 -0
  24. package/skills/game-development/2d-games/SKILL.md +129 -0
  25. package/skills/game-development/3d-games/SKILL.md +145 -0
  26. package/skills/game-development/SKILL.md +175 -0
  27. package/skills/game-development/game-art/SKILL.md +195 -0
  28. package/skills/game-development/game-audio/SKILL.md +200 -0
  29. package/skills/game-development/game-design/SKILL.md +139 -0
  30. package/skills/game-development/mobile-games/SKILL.md +118 -0
  31. package/skills/game-development/multiplayer/SKILL.md +142 -0
  32. package/skills/game-development/pc-games/SKILL.md +154 -0
  33. package/skills/game-development/vr-ar/SKILL.md +133 -0
  34. package/skills/game-development/web-games/SKILL.md +160 -0
  35. package/skills/game-engine/SKILL.md +140 -0
  36. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  37. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  38. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  39. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  40. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  41. package/skills/game-engine/references/3d-web-games.md +754 -0
  42. package/skills/game-engine/references/algorithms.md +843 -0
  43. package/skills/game-engine/references/basics.md +343 -0
  44. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  45. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  46. package/skills/game-engine/references/game-publishing.md +352 -0
  47. package/skills/game-engine/references/techniques.md +894 -0
  48. package/skills/game-engine/references/terminology.md +354 -0
  49. package/skills/game-engine/references/web-apis.md +1394 -0
  50. package/skills/theone-cocos-standards/SKILL.md +557 -0
  51. package/skills/theone-cocos-standards/references/framework/component-system.md +645 -0
  52. package/skills/theone-cocos-standards/references/framework/event-patterns.md +433 -0
  53. package/skills/theone-cocos-standards/references/framework/playable-optimization.md +429 -0
  54. package/skills/theone-cocos-standards/references/framework/size-optimization.md +308 -0
  55. package/skills/theone-cocos-standards/references/language/modern-typescript.md +658 -0
  56. package/skills/theone-cocos-standards/references/language/performance.md +580 -0
  57. package/skills/theone-cocos-standards/references/language/quality-hygiene.md +582 -0
  58. package/skills/theone-cocos-standards/references/review/architecture-review.md +250 -0
  59. package/skills/theone-cocos-standards/references/review/performance-review.md +288 -0
  60. package/skills/theone-cocos-standards/references/review/quality-review.md +239 -0
  61. package/dist/chunk-CBZIH6FY.js.map +0 -1
  62. package/dist/macos-BTP5JW3U.js.map +0 -1
  63. /package/dist/{chunk-RO47ET27.js.map → chunk-M2CDVPQF.js.map} +0 -0
  64. /package/dist/{chunk-MSDIRBXF.js.map → chunk-RIK7IXSW.js.map} +0 -0
  65. /package/dist/{linux-6AR7SXHW.js.map → linux-IHA4O633.js.map} +0 -0
  66. /package/dist/{windows-IQNSUMN6.js.map → windows-P6U3JLUZ.js.map} +0 -0
@@ -0,0 +1,250 @@
1
+ # Cocos Creator Architecture Review
2
+
3
+ This review focuses on Cocos Creator-specific architectural issues including component lifecycle violations, event management problems, and performance issues specific to playable ads.
4
+
5
+ ## Component Lifecycle Violations
6
+
7
+ ### Accessing Components in onLoad
8
+
9
+ ```typescript
10
+ // ❌ CRITICAL: Accessing other components in onLoad
11
+ @ccclass('BadLifecycle')
12
+ export class BadLifecycle extends Component {
13
+ @property(Node)
14
+ private playerNode: Node | null = null;
15
+
16
+ protected onLoad(): void {
17
+ // WRONG: Other components may not be loaded yet
18
+ const controller = this.playerNode!.getComponent(PlayerController);
19
+ controller.initialize(); // May be undefined!
20
+ }
21
+ }
22
+
23
+ // ✅ CORRECT: Access components in start()
24
+ @ccclass('GoodLifecycle')
25
+ export class GoodLifecycle extends Component {
26
+ @property(Node)
27
+ private readonly playerNode: Node | null = null;
28
+
29
+ private playerController!: PlayerController;
30
+
31
+ protected onLoad(): void {
32
+ if (!this.playerNode) {
33
+ throw new Error('GoodLifecycle: playerNode is required');
34
+ }
35
+ }
36
+
37
+ protected start(): void {
38
+ const controller = this.playerNode!.getComponent(PlayerController);
39
+ if (!controller) {
40
+ throw new Error('PlayerController not found');
41
+ }
42
+ this.playerController = controller;
43
+ this.playerController.initialize();
44
+ }
45
+ }
46
+
47
+ // Severity: 🔴 Critical
48
+ // Impact: Undefined behavior, crashes
49
+ // Fix: Move component access from onLoad() to start()
50
+ ```
51
+
52
+ ### Event Listener Memory Leaks
53
+
54
+ ```typescript
55
+ // ❌ CRITICAL: Not unregistering event listeners
56
+ @ccclass('EventLeakBad')
57
+ export class EventLeakBad extends Component {
58
+ protected onEnable(): void {
59
+ this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
60
+ EventManager.on(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
61
+ }
62
+
63
+ // MISSING: onDisable() - memory leak!
64
+ }
65
+
66
+ // ✅ CORRECT: Always unregister in onDisable
67
+ @ccclass('EventLeakGood')
68
+ export class EventLeakGood extends Component {
69
+ protected onEnable(): void {
70
+ this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
71
+ EventManager.on(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
72
+ }
73
+
74
+ protected onDisable(): void {
75
+ this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
76
+ EventManager.off(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
77
+ }
78
+
79
+ private onTouchStart(event: EventTouch): void {}
80
+ private onScoreChanged(data: ScoreChangedEvent): void {}
81
+ }
82
+
83
+ // Severity: 🔴 Critical
84
+ // Impact: Memory leaks, performance degradation
85
+ // Fix: Always implement onDisable() to unregister listeners
86
+ ```
87
+
88
+ ### Missing Required Reference Validation
89
+
90
+ ```typescript
91
+ // ❌ CRITICAL: No validation of required references
92
+ @ccclass('NoValidation')
93
+ export class NoValidation extends Component {
94
+ @property(Node)
95
+ private targetNode: Node | null = null;
96
+
97
+ protected onLoad(): void {
98
+ this.targetNode!.setPosition(0, 0, 0); // Will crash if null
99
+ }
100
+ }
101
+
102
+ // ✅ CORRECT: Validate in onLoad
103
+ @ccclass('WithValidation')
104
+ export class WithValidation extends Component {
105
+ @property(Node)
106
+ private readonly targetNode: Node | null = null;
107
+
108
+ protected onLoad(): void {
109
+ if (!this.targetNode) {
110
+ throw new Error('WithValidation: targetNode is required');
111
+ }
112
+ this.targetNode.setPosition(0, 0, 0);
113
+ }
114
+ }
115
+
116
+ // Severity: 🔴 Critical
117
+ // Impact: Runtime crashes with unhelpful errors
118
+ // Fix: Validate all required @property references in onLoad()
119
+ ```
120
+
121
+ ### Resource Cleanup Violations
122
+
123
+ ```typescript
124
+ // ❌ CRITICAL: Not releasing resources
125
+ @ccclass('ResourceLeakBad')
126
+ export class ResourceLeakBad extends Component {
127
+ private readonly loadedAssets: Map<string, Asset> = new Map();
128
+
129
+ protected onDestroy(): void {
130
+ // MISSING: decRef() and clear()
131
+ }
132
+ }
133
+
134
+ // ✅ CORRECT: Complete cleanup
135
+ @ccclass('ResourceLeakGood')
136
+ export class ResourceLeakGood extends Component {
137
+ private readonly loadedAssets: Map<string, Asset> = new Map();
138
+
139
+ protected onDestroy(): void {
140
+ for (const [id, asset] of this.loadedAssets) {
141
+ asset.decRef();
142
+ }
143
+ this.loadedAssets.clear();
144
+ this.unscheduleAllCallbacks();
145
+ }
146
+ }
147
+
148
+ // Severity: 🔴 Critical
149
+ // Impact: Memory leaks
150
+ // Fix: Release resources and clear collections in onDestroy()
151
+ ```
152
+
153
+ ## Performance Violations (Playable-Specific)
154
+
155
+ ### Allocations in Update Loop
156
+
157
+ ```typescript
158
+ // ❌ CRITICAL: Allocating every frame
159
+ @ccclass('UpdateAllocationsBad')
160
+ export class UpdateAllocationsBad extends Component {
161
+ protected update(dt: number): void {
162
+ const pos = this.node.position.clone(); // 60 allocations/second
163
+ pos.y += 10 * dt;
164
+ this.node.setPosition(pos);
165
+ }
166
+ }
167
+
168
+ // ✅ CORRECT: Preallocate and reuse
169
+ @ccclass('UpdateAllocationsGood')
170
+ export class UpdateAllocationsGood extends Component {
171
+ private readonly tempVec3: Vec3 = new Vec3();
172
+
173
+ protected update(dt: number): void {
174
+ this.node.getPosition(this.tempVec3);
175
+ this.tempVec3.y += 10 * dt;
176
+ this.node.setPosition(this.tempVec3);
177
+ }
178
+ }
179
+
180
+ // Severity: 🔴 Critical
181
+ // Impact: Frame drops, GC pauses
182
+ // Fix: Preallocate objects, reuse in update
183
+ ```
184
+
185
+ ### Component Lookup in Update
186
+
187
+ ```typescript
188
+ // ❌ IMPORTANT: getComponent in update
189
+ @ccclass('ComponentLookupBad')
190
+ export class ComponentLookupBad extends Component {
191
+ @property(Node)
192
+ private playerNode: Node | null = null;
193
+
194
+ protected update(dt: number): void {
195
+ const controller = this.playerNode!.getComponent(PlayerController); // Expensive!
196
+ controller?.update(dt);
197
+ }
198
+ }
199
+
200
+ // ✅ CORRECT: Cache component reference
201
+ @ccclass('ComponentLookupGood')
202
+ export class ComponentLookupGood extends Component {
203
+ @property(Node)
204
+ private readonly playerNode: Node | null = null;
205
+
206
+ private playerController!: PlayerController;
207
+
208
+ protected start(): void {
209
+ if (!this.playerNode) {
210
+ throw new Error('playerNode is required');
211
+ }
212
+ const controller = this.playerNode.getComponent(PlayerController);
213
+ if (!controller) {
214
+ throw new Error('PlayerController not found');
215
+ }
216
+ this.playerController = controller;
217
+ }
218
+
219
+ protected update(dt: number): void {
220
+ this.playerController.update(dt);
221
+ }
222
+ }
223
+
224
+ // Severity: 🟡 Important
225
+ // Impact: Significant performance overhead
226
+ // Fix: Cache component references in start()
227
+ ```
228
+
229
+ ## Summary: Architecture Review Checklist
230
+
231
+ **🔴 Critical (Must Fix):**
232
+ - [ ] No component access in onLoad() (use start())
233
+ - [ ] All event listeners unregistered in onDisable()
234
+ - [ ] Required @property references validated in onLoad()
235
+ - [ ] Resources released in onDestroy()
236
+ - [ ] Zero allocations in update() loop
237
+ - [ ] readonly used for @property fields not reassigned
238
+
239
+ **🟡 Important (Should Fix):**
240
+ - [ ] Component references cached (not getComponent in update)
241
+ - [ ] Expensive operations throttled (every N frames)
242
+ - [ ] Node references cached (not find() in update)
243
+ - [ ] Arrays cleared with .length = 0 (not new array)
244
+
245
+ **🟢 Nice to Have:**
246
+ - [ ] Object pooling for frequent spawn/despawn
247
+ - [ ] WeakMap for auto-cleanup caches
248
+ - [ ] Disposable pattern for subscription management
249
+
250
+ **Always fix lifecycle and event cleanup issues - they cause crashes and memory leaks.**
@@ -0,0 +1,288 @@
1
+ # Playable Ads Performance Review
2
+
3
+ This review focuses on performance issues specific to playable ads including DrawCall optimization, bundle size, update loop performance, and resource management.
4
+
5
+ ## DrawCall Explosion (Critical for Playables)
6
+
7
+ **Target: <10 DrawCalls for 60fps playables**
8
+
9
+ ```typescript
10
+ // ❌ CRITICAL: Individual textures (multiple DrawCalls)
11
+ @ccclass('DrawCallBad')
12
+ export class DrawCallBad extends Component {
13
+ @property(SpriteFrame)
14
+ private sprite1: SpriteFrame | null = null; // DrawCall 1
15
+
16
+ @property(SpriteFrame)
17
+ private sprite2: SpriteFrame | null = null; // DrawCall 2
18
+
19
+ @property(SpriteFrame)
20
+ private sprite3: SpriteFrame | null = null; // DrawCall 3
21
+
22
+ // 10 sprites = 10 DrawCalls! (BAD)
23
+ }
24
+
25
+ // ✅ CORRECT: Sprite atlas (single DrawCall)
26
+ @ccclass('DrawCallGood')
27
+ export class DrawCallGood extends Component {
28
+ @property(SpriteAtlas)
29
+ private readonly characterAtlas: SpriteAtlas | null = null; // 1 DrawCall for all
30
+ }
31
+
32
+ // Severity: 🔴 Critical
33
+ // Impact: Frame drops, poor performance
34
+ // Target: <10 DrawCalls total
35
+ // Fix: Use sprite atlases for all sprites
36
+ ```
37
+
38
+ ## Update Loop Allocations
39
+
40
+ ```typescript
41
+ // ❌ CRITICAL: Allocating in update
42
+ @ccclass('UpdateAllocationsBad')
43
+ export class UpdateAllocationsBad extends Component {
44
+ protected update(dt: number): void {
45
+ // Creates new Vec3 every frame
46
+ const pos = this.node.position.clone(); // 60 allocations/second!
47
+ pos.y += 10 * dt;
48
+ this.node.setPosition(pos);
49
+
50
+ // Creates array every frame
51
+ const enemies = this.getAllEnemies().filter(e => e.active); // 60 arrays/second!
52
+ }
53
+ }
54
+
55
+ // ✅ CORRECT: Zero allocations
56
+ @ccclass('UpdateAllocationsGood')
57
+ export class UpdateAllocationsGood extends Component {
58
+ private readonly tempVec3: Vec3 = new Vec3();
59
+ private readonly activeEnemies: Enemy[] = [];
60
+ private cacheRDirty: boolean = true;
61
+
62
+ protected update(dt: number): void {
63
+ // Reuse preallocated vector
64
+ this.node.getPosition(this.tempVec3);
65
+ this.tempVec3.y += 10 * dt;
66
+ this.node.setPosition(this.tempVec3);
67
+
68
+ // Use cached array
69
+ const enemies = this.getActiveEnemies();
70
+ }
71
+
72
+ private getActiveEnemies(): Enemy[] {
73
+ if (this.cacheDirty) {
74
+ this.activeEnemies.length = 0;
75
+ // Rebuild cache
76
+ this.cacheDirty = false;
77
+ }
78
+ return this.activeEnemies;
79
+ }
80
+ }
81
+
82
+ // Severity: 🔴 Critical
83
+ // Impact: Frame drops, GC pauses
84
+ // Fix: Preallocate objects, reuse in update
85
+ ```
86
+
87
+ ## No Object Pooling
88
+
89
+ ```typescript
90
+ // ❌ IMPORTANT: instantiate/destroy in gameplay
91
+ @ccclass('NoPoolingBad')
92
+ export class NoPoolingBad extends Component {
93
+ public shoot(): void {
94
+ const bullet = instantiate(this.bulletPrefab!); // Allocates
95
+ this.scheduleOnce(() => {
96
+ bullet.destroy(); // GC overhead
97
+ }, 2.0);
98
+ }
99
+ }
100
+
101
+ // ✅ CORRECT: Object pooling
102
+ @ccclass('NoPoolingGood')
103
+ export class NoPoolingGood extends Component {
104
+ private readonly bulletPool: NodePool = new NodePool();
105
+
106
+ protected onLoad(): void {
107
+ // Prewarm pool
108
+ for (let i = 0; i < 20; i++) {
109
+ const bullet = instantiate(this.bulletPrefab!);
110
+ this.bulletPool.put(bullet);
111
+ }
112
+ }
113
+
114
+ public shoot(): void {
115
+ const bullet = this.bulletPool.get() ?? instantiate(this.bulletPrefab!);
116
+ this.scheduleOnce(() => {
117
+ this.bulletPool.put(bullet);
118
+ }, 2.0);
119
+ }
120
+ }
121
+
122
+ // Severity: 🟡 Important
123
+ // Impact: Allocations, GC pauses
124
+ // Fix: Implement object pooling for frequent spawn/despawn
125
+ ```
126
+
127
+ ## Unthrottled Expensive Operations
128
+
129
+ ```typescript
130
+ // ❌ IMPORTANT: Expensive operations every frame
131
+ @ccclass('UnthrottledBad')
132
+ export class UnthrottledBad extends Component {
133
+ protected update(dt: number): void {
134
+ this.recalculatePathfinding(); // A* every frame (60 times/second)!
135
+ this.updateComplexAI(); // Expensive every frame!
136
+ }
137
+ }
138
+
139
+ // ✅ CORRECT: Throttle expensive operations
140
+ @ccclass('UnthrottledGood')
141
+ export class UnthrottledGood extends Component {
142
+ private frameCount: number = 0;
143
+
144
+ protected update(dt: number): void {
145
+ this.frameCount++;
146
+
147
+ // Pathfinding once per second
148
+ if (this.frameCount % 60 === 0) {
149
+ this.recalculatePathfinding();
150
+ }
151
+
152
+ // AI 6 times per second
153
+ if (this.frameCount % 10 === 0) {
154
+ this.updateComplexAI();
155
+ }
156
+
157
+ // Cheap operations every frame
158
+ this.moveTowardsTarget(dt);
159
+ }
160
+ }
161
+
162
+ // Severity: 🟡 Important
163
+ // Impact: Poor performance, frame drops
164
+ // Fix: Throttle to every N frames (10-60)
165
+ ```
166
+
167
+ ## Bundle Size >5MB
168
+
169
+ ```typescript
170
+ // ❌ CRITICAL: Bundle exceeds playable limit
171
+ // Build output: 7.2MB (too large for most ad networks!)
172
+
173
+ // Common causes:
174
+ // 1. Uncompressed textures → Enable compression
175
+ // 2. Oversized textures → Reduce to 512x512 max
176
+ // 3. Uncompressed audio → Use MP3/OGG at 64-128kbps
177
+ // 4. Unused assets → Remove from project
178
+ // 5. No code minification → Enable in build settings
179
+
180
+ // ✅ CORRECT: Optimized to <5MB
181
+ // - Enable texture compression (Project Settings)
182
+ // - Use sprite atlases (combine textures)
183
+ // - Compress audio (64-128kbps)
184
+ // - Remove unused assets
185
+ // - Enable code minification (drop_console, dead_code)
186
+
187
+ // Severity: 🔴 Critical
188
+ // Impact: Playable rejected by ad networks
189
+ // Target: <5MB total bundle
190
+ // Fix: Apply size optimization techniques
191
+ ```
192
+
193
+ ## Loading Resources During Gameplay
194
+
195
+ ```typescript
196
+ // ❌ IMPORTANT: Loading during gameplay
197
+ @ccclass('LoadingInGameplayBad')
198
+ export class LoadingInGameplayBad extends Component {
199
+ protected update(dt: number): void {
200
+ if (this.shouldSpawnEnemy()) {
201
+ // Loading causes frame drop!
202
+ resources.load('sprites/enemy', SpriteFrame, (err, sprite) => {
203
+ this.spawnEnemy(sprite);
204
+ });
205
+ }
206
+ }
207
+ }
208
+
209
+ // ✅ CORRECT: Preload at startup
210
+ @ccclass('LoadingInGameplayGood')
211
+ export class LoadingInGameplayGood extends Component {
212
+ private enemySprite: SpriteFrame | null = null;
213
+
214
+ protected start(): void {
215
+ // Preload once
216
+ resources.load('sprites/enemy', SpriteFrame, (err, sprite) => {
217
+ if (!err) {
218
+ this.enemySprite = sprite;
219
+ }
220
+ });
221
+ }
222
+
223
+ protected update(dt: number): void {
224
+ if (this.shouldSpawnEnemy() && this.enemySprite) {
225
+ this.spawnEnemy(this.enemySprite); // Instant, no loading
226
+ }
227
+ }
228
+ }
229
+
230
+ // Severity: 🟡 Important
231
+ // Impact: Frame drops during loading
232
+ // Fix: Preload all resources at startup
233
+ ```
234
+
235
+ ## GPU Skinning Disabled
236
+
237
+ ```typescript
238
+ // ❌ IMPORTANT: CPU skinning (slower)
239
+ @ccclass('CPUSkinningBad')
240
+ export class CPUSkinningBad extends Component {
241
+ @property(SkeletalAnimation)
242
+ private skeleton: SkeletalAnimation | null = null;
243
+
244
+ protected onLoad(): void {
245
+ // Using default CPU skinning (slower)
246
+ }
247
+ }
248
+
249
+ // ✅ CORRECT: Enable GPU skinning
250
+ @ccclass('GPUSkinningGood')
251
+ export class GPUSkinningGood extends Component {
252
+ @property(SkeletalAnimation)
253
+ private readonly skeleton: SkeletalAnimation | null = null;
254
+
255
+ protected onLoad(): void {
256
+ if (this.skeleton) {
257
+ // GPU handles bone transformations (faster)
258
+ this.skeleton.useBakedAnimation = true;
259
+ }
260
+ }
261
+ }
262
+
263
+ // Severity: 🟢 Nice to Have
264
+ // Impact: Better performance for skeletal animations
265
+ // Fix: Enable useBakedAnimation for GPU skinning
266
+ ```
267
+
268
+ ## Summary: Performance Review Checklist
269
+
270
+ **🔴 Critical (Must Fix):**
271
+ - [ ] DrawCall count <10 (use sprite atlases)
272
+ - [ ] Zero allocations in update() loop
273
+ - [ ] Bundle size <5MB total
274
+ - [ ] No loading resources during gameplay
275
+
276
+ **🟡 Important (Should Fix):**
277
+ - [ ] Object pooling for bullets, effects, enemies
278
+ - [ ] Expensive operations throttled (every 10-60 frames)
279
+ - [ ] Component references cached (not getComponent in update)
280
+ - [ ] Node references cached (not find() in update)
281
+
282
+ **🟢 Nice to Have:**
283
+ - [ ] GPU skinning enabled (useBakedAnimation = true)
284
+ - [ ] Texture dimensions optimized (512x512 max)
285
+ - [ ] Audio compressed (64-128kbps)
286
+ - [ ] WeakMap for auto-cleanup caches
287
+
288
+ **Performance targets: 60fps, <10 DrawCalls, <5MB bundle for playable ads.**