@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.
- package/cli.js +63 -0
- package/dist/__tests__/checkpoint.test.d.ts +2 -0
- package/dist/__tests__/checkpoint.test.d.ts.map +1 -0
- package/dist/__tests__/fs-handler-decode.test.d.ts +2 -0
- package/dist/__tests__/fs-handler-decode.test.d.ts.map +1 -0
- package/dist/__tests__/idle-sweeper.test.d.ts +2 -0
- package/dist/__tests__/idle-sweeper.test.d.ts.map +1 -0
- package/dist/__tests__/mcp-config.test.d.ts +2 -0
- package/dist/__tests__/mcp-config.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-runtime-spawn.test.d.ts +2 -0
- package/dist/__tests__/schedule-runtime-spawn.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-runtime.test.d.ts +2 -0
- package/dist/__tests__/schedule-runtime.test.d.ts.map +1 -0
- package/dist/__tests__/session-limit.test.d.ts +2 -0
- package/dist/__tests__/session-limit.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-cli-client.test.d.ts +2 -0
- package/dist/__tests__/swarm-cli-client.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-control-dispatch.test.d.ts +2 -0
- package/dist/__tests__/swarm-control-dispatch.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-session-bridge.test.d.ts +2 -0
- package/dist/__tests__/swarm-session-bridge.test.d.ts.map +1 -0
- package/dist/backend-adapter.d.ts +43 -0
- package/dist/backend-adapter.d.ts.map +1 -1
- package/dist/checkpoint.d.ts +67 -0
- package/dist/checkpoint.d.ts.map +1 -0
- package/dist/{chunk-RIK7IXSW.js → chunk-WJWCYGLQ.js} +1130 -147
- package/dist/chunk-WJWCYGLQ.js.map +1 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/fs-handler.d.ts.map +1 -1
- package/dist/hub-connection.d.ts +13 -0
- package/dist/hub-connection.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/schedule-runtime.d.ts +125 -0
- package/dist/schedule-runtime.d.ts.map +1 -0
- package/dist/session-manager.d.ts +102 -0
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/skill-loader.d.ts +20 -0
- package/dist/skill-loader.d.ts.map +1 -1
- package/dist/start.d.ts +2 -0
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +1 -1
- package/dist/swarm-cli-client.d.ts +24 -0
- package/dist/swarm-cli-client.d.ts.map +1 -0
- package/dist/swarm-cli-client.js +83 -0
- package/dist/swarm-cli-client.js.map +1 -0
- package/dist/swarm-control-dispatch.d.ts +47 -0
- package/dist/swarm-control-dispatch.d.ts.map +1 -0
- package/dist/swarm-session-bridge.d.ts +22 -0
- package/dist/swarm-session-bridge.d.ts.map +1 -0
- package/package.json +6 -4
- package/skills/cocos-creator-3x-cn/SKILL.md +475 -0
- package/skills/cocos-creator-3x-cn/references/framework/asset-management.md +322 -0
- package/skills/cocos-creator-3x-cn/references/framework/component-system.md +348 -0
- package/skills/cocos-creator-3x-cn/references/framework/event-patterns.md +410 -0
- package/skills/cocos-creator-3x-cn/references/framework/playable-optimization.md +257 -0
- package/skills/cocos-creator-3x-cn/references/language/performance.md +363 -0
- package/skills/cocos-creator-3x-cn/references/language/quality-hygiene.md +307 -0
- package/skills/cocos-creator-3x-cn/references/review/architecture-review.md +183 -0
- package/skills/cocos-creator-3x-cn/references/review/quality-review.md +251 -0
- package/skills/cocos-performance-optimizer/SKILL.md +214 -0
- package/skills/game-development/2d-games/SKILL.md +129 -0
- package/skills/game-development/3d-games/SKILL.md +145 -0
- package/skills/game-development/SKILL.md +175 -0
- package/skills/game-development/game-art/SKILL.md +195 -0
- package/skills/game-development/game-audio/SKILL.md +200 -0
- package/skills/game-development/game-design/SKILL.md +139 -0
- package/skills/game-development/mobile-games/SKILL.md +118 -0
- package/skills/game-development/multiplayer/SKILL.md +142 -0
- package/skills/game-development/pc-games/SKILL.md +154 -0
- package/skills/game-development/vr-ar/SKILL.md +133 -0
- package/skills/game-development/web-games/SKILL.md +160 -0
- package/skills/game-engine/SKILL.md +140 -0
- package/skills/game-engine/assets/2d-maze-game.md +528 -0
- package/skills/game-engine/assets/2d-platform-game.md +1855 -0
- package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
- package/skills/game-engine/assets/paddle-game-template.md +1528 -0
- package/skills/game-engine/assets/simple-2d-engine.md +507 -0
- package/skills/game-engine/references/3d-web-games.md +754 -0
- package/skills/game-engine/references/algorithms.md +843 -0
- package/skills/game-engine/references/basics.md +343 -0
- package/skills/game-engine/references/game-control-mechanisms.md +617 -0
- package/skills/game-engine/references/game-engine-core-principles.md +695 -0
- package/skills/game-engine/references/game-publishing.md +352 -0
- package/skills/game-engine/references/techniques.md +894 -0
- package/skills/game-engine/references/terminology.md +354 -0
- package/skills/game-engine/references/web-apis.md +1394 -0
- package/skills/theone-cocos-standards/SKILL.md +557 -0
- package/skills/theone-cocos-standards/references/framework/component-system.md +645 -0
- package/skills/theone-cocos-standards/references/framework/event-patterns.md +433 -0
- package/skills/theone-cocos-standards/references/framework/playable-optimization.md +429 -0
- package/skills/theone-cocos-standards/references/framework/size-optimization.md +308 -0
- package/skills/theone-cocos-standards/references/language/modern-typescript.md +658 -0
- package/skills/theone-cocos-standards/references/language/performance.md +580 -0
- package/skills/theone-cocos-standards/references/language/quality-hygiene.md +582 -0
- package/skills/theone-cocos-standards/references/review/architecture-review.md +250 -0
- package/skills/theone-cocos-standards/references/review/performance-review.md +288 -0
- package/skills/theone-cocos-standards/references/review/quality-review.md +239 -0
- package/dist/chunk-RIK7IXSW.js.map +0 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# 架构审查清单 — Cocos Creator 3.8
|
|
2
|
+
|
|
3
|
+
> 📖 本文件为 `cocos-creator-3x-cn` 技能参考文件,提供代码架构审查的标准清单。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 审查优先级
|
|
8
|
+
|
|
9
|
+
| 级别 | 说明 | 要求 |
|
|
10
|
+
|------|------|------|
|
|
11
|
+
| 🔴 P0 - 阻断 | 必须修复才能合并 | 运行时崩溃、资源泄漏、事件泄漏 |
|
|
12
|
+
| 🟡 P1 - 重要 | 建议当前迭代修复 | 架构违规、性能隐患 |
|
|
13
|
+
| 🟢 P2 - 建议 | 下次迭代修复 | 代码风格、可读性 |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. 模块导入审查
|
|
18
|
+
|
|
19
|
+
### 检查项
|
|
20
|
+
|
|
21
|
+
- [ ] 🔴 所有引擎 API 通过 `import { ... } from 'cc'` 导入,不使用 `cc.` 前缀
|
|
22
|
+
- [ ] 🔴 环境宏通过 `import { DEBUG } from 'cc/env'` 导入,不使用 `CC_DEBUG`
|
|
23
|
+
- [ ] 🟡 导入按规范顺序排列(引擎核心 → UI 组件 → 项目公共 → 当前模块)
|
|
24
|
+
- [ ] 🟡 没有未使用的导入
|
|
25
|
+
- [ ] 🟢 没有 `import * as` 风格的全量导入
|
|
26
|
+
|
|
27
|
+
### 示例
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// ✅ 正确
|
|
31
|
+
import { _decorator, Component, Node, Vec3, Sprite } from 'cc';
|
|
32
|
+
import { DEBUG } from 'cc/env';
|
|
33
|
+
import { GameManager } from '../manager/GameManager';
|
|
34
|
+
|
|
35
|
+
// ❌ 错误
|
|
36
|
+
const { ccclass } = cc._decorator; // 2.x 风格
|
|
37
|
+
if (CC_DEBUG) { } // 2.x 宏
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. 组件声明审查
|
|
43
|
+
|
|
44
|
+
### 检查项
|
|
45
|
+
|
|
46
|
+
- [ ] 🔴 `@ccclass('Name')` 参数与类名一致且全局唯一
|
|
47
|
+
- [ ] 🔴 属性 `@property` 正确声明类型
|
|
48
|
+
- [ ] 🟡 引用类型属性使用 `Type | null = null` 或 `Type = null!`(非空断言仅限确定编辑器赋值的场景)
|
|
49
|
+
- [ ] 🟡 不在构造函数中初始化逻辑(使用 `onLoad`/`start`)
|
|
50
|
+
- [ ] 🟢 组件遵循单一职责原则
|
|
51
|
+
- [ ] 🟢 使用 `@requireComponent` 声明依赖
|
|
52
|
+
|
|
53
|
+
### 示例
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// ✅
|
|
57
|
+
@ccclass('PlayerController')
|
|
58
|
+
export class PlayerController extends Component {
|
|
59
|
+
@property(Node)
|
|
60
|
+
private readonly target: Node | null = null;
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
private readonly speed = 10;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ❌ cc 类名与类名不一致
|
|
67
|
+
@ccclass('Player')
|
|
68
|
+
export class PlayerController extends Component { }
|
|
69
|
+
|
|
70
|
+
// ❌ 未声明类型的引用属性
|
|
71
|
+
@property
|
|
72
|
+
target = null; // 编辑器无法识别类型
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 3. 生命周期审查
|
|
78
|
+
|
|
79
|
+
### 检查项
|
|
80
|
+
|
|
81
|
+
- [ ] 🔴 `onEnable` 中注册的事件在 `onDisable` 中全部注销
|
|
82
|
+
- [ ] 🔴 `onDestroy` 中释放了所有动态加载的资源(`decRef` / `releaseAsset`)
|
|
83
|
+
- [ ] 🔴 `onDestroy` 中停止了所有缓动和定时器
|
|
84
|
+
- [ ] 🟡 `onLoad` 不依赖其他组件的 `start` 初始化结果
|
|
85
|
+
- [ ] 🟡 不在 `update` 中每帧调用 `find`/`getComponent`
|
|
86
|
+
- [ ] 🟢 `update` 中不创建临时对象(`new Vec3()` 等)
|
|
87
|
+
|
|
88
|
+
### 事件配对检查器
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
onEnable 调用的 on() → onDisable 必须有对应 off()
|
|
92
|
+
onLoad 调用的 on() → onDestroy 必须有对应 off()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 4. 事件系统审查
|
|
98
|
+
|
|
99
|
+
### 检查项
|
|
100
|
+
|
|
101
|
+
- [ ] 🔴 使用枚举常量注册事件(`Node.EventType.TOUCH_START`),不使用字符串
|
|
102
|
+
- [ ] 🔴 事件回调使用named function/方法引用,不使用匿名函数(否则无法 off)
|
|
103
|
+
- [ ] 🔴 自定义事件类继承自 `Event`,不直接 `new Event()`(Event 是抽象类)
|
|
104
|
+
- [ ] 🟡 `EventTarget` 用于自定义事件,不通过 `Node` 做自定义事件
|
|
105
|
+
- [ ] 🟡 `emit` 参数不超过 5 个
|
|
106
|
+
- [ ] 🟢 触摸事件穿透使用 `event.preventSwallow`
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 5. 资源管理审查
|
|
111
|
+
|
|
112
|
+
### 检查项
|
|
113
|
+
|
|
114
|
+
- [ ] 🔴 动态加载的资源有明确的释放策略(`addRef`/`decRef` 或手动 `releaseAsset`)
|
|
115
|
+
- [ ] 🔴 `resources` 目录仅包含需要动态加载的资源
|
|
116
|
+
- [ ] 🔴 加载回调处理了 `err` 参数
|
|
117
|
+
- [ ] 🟡 使用预加载(`preload`)优化体验
|
|
118
|
+
- [ ] 🟡 大量资源使用 Asset Bundle 分模块
|
|
119
|
+
- [ ] 🟡 场景勾选自动释放(高频主场景除外)
|
|
120
|
+
- [ ] 🟢 加载路径使用常量/配置,不硬编码
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 6. 性能架构审查
|
|
125
|
+
|
|
126
|
+
### 检查项
|
|
127
|
+
|
|
128
|
+
- [ ] 🔴 频繁创建销毁的节点使用对象池
|
|
129
|
+
- [ ] 🟡 Draw Call 在合理范围(2D < 50)
|
|
130
|
+
- [ ] 🟡 使用图集合并碎图
|
|
131
|
+
- [ ] 🟡 低频逻辑使用 `schedule` 而非 `update`
|
|
132
|
+
- [ ] 🟢 使用 `Vec3.set/copy` 复用对象,避免 `new Vec3()`
|
|
133
|
+
- [ ] 🟢 使用距离平方比较替代距离比较
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 7. TypeScript 质量审查
|
|
138
|
+
|
|
139
|
+
### 检查项
|
|
140
|
+
|
|
141
|
+
- [ ] 🔴 没有 `any` 类型(必要时使用 `unknown` + 类型守卫)
|
|
142
|
+
- [ ] 🔴 没有未捕获的异步错误
|
|
143
|
+
- [ ] 🟡 使用可选链 `?.` 和空值合并 `??`
|
|
144
|
+
- [ ] 🟡 枚举在编辑器使用时调用了 `Enum()`
|
|
145
|
+
- [ ] 🟡 `const enum` 用于纯代码常量(编译内联)
|
|
146
|
+
- [ ] 🟢 调试代码用 `DEBUG` 宏包裹
|
|
147
|
+
- [ ] 🟢 没有 `console.log` 残留(或有 `DEBUG` 保护)
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 8. 项目结构审查
|
|
152
|
+
|
|
153
|
+
### 检查项
|
|
154
|
+
|
|
155
|
+
- [ ] 🟡 文件命名 PascalCase 与类名一致
|
|
156
|
+
- [ ] 🟡 目录结构清晰(common/manager/ui/game/config/data)
|
|
157
|
+
- [ ] 🟡 没有循环依赖
|
|
158
|
+
- [ ] 🟡 公共工具类提取到 common 目录
|
|
159
|
+
- [ ] 🟢 README 文档更新
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 审查报告模板
|
|
164
|
+
|
|
165
|
+
```markdown
|
|
166
|
+
## 架构审查报告
|
|
167
|
+
|
|
168
|
+
**文件**: `PlayerController.ts`
|
|
169
|
+
**审查日期**: YYYY-MM-DD
|
|
170
|
+
**审查人**: XXX
|
|
171
|
+
|
|
172
|
+
### P0 - 阻断
|
|
173
|
+
- [ ] `onEnable` 注册了 TOUCH_START 但 `onDisable` 未注销 (L42)
|
|
174
|
+
- [ ] 动态加载的 Prefab 未调用 `addRef`,可能被意外释放 (L78)
|
|
175
|
+
|
|
176
|
+
### P1 - 重要
|
|
177
|
+
- [ ] `update` 中每帧调用 `find('Canvas/Enemy')` (L55)
|
|
178
|
+
- [ ] 缺少加载错误处理 (L78)
|
|
179
|
+
|
|
180
|
+
### P2 - 建议
|
|
181
|
+
- [ ] 使用魔法数字 `0.5` 作为移动倍率 (L60),建议提取常量
|
|
182
|
+
- [ ] 残留 `console.log` (L90)
|
|
183
|
+
```
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# 代码质量审查清单 — Cocos Creator 3.8
|
|
2
|
+
|
|
3
|
+
> 📖 本文件为 `cocos-creator-3x-cn` 技能参考文件,提供代码质量审查的详细清单。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 代码正确性
|
|
8
|
+
|
|
9
|
+
### 1.1 类型安全
|
|
10
|
+
|
|
11
|
+
| 检查项 | 严重级 | 说明 |
|
|
12
|
+
|--------|--------|------|
|
|
13
|
+
| 无 `as any` 类型断言 | 🔴 | 使用正确类型或 `unknown` + 类型守卫 |
|
|
14
|
+
| 属性正确声明可空性 | 🔴 | `Node \| null = null` 或 `Node = null!` |
|
|
15
|
+
| 无隐式 `any` | 🟡 | tsconfig 开启 `strict` / `noImplicitAny` |
|
|
16
|
+
| 回调参数类型正确 | 🟡 | `(event: EventTouch)` 而非 `(event: any)` |
|
|
17
|
+
| 泛型类型明确 | 🟢 | `assetManager.loadRemote<ImageAsset>(...)` |
|
|
18
|
+
|
|
19
|
+
### 1.2 空值安全
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// ✅ 审查通过模式
|
|
23
|
+
const sprite = this.node.getComponent(Sprite);
|
|
24
|
+
if (!sprite) {
|
|
25
|
+
console.error('Sprite component not found');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
sprite.spriteFrame = newFrame;
|
|
29
|
+
|
|
30
|
+
// ✅ 可选链 + 提前返回
|
|
31
|
+
private onTouchStart(event: EventTouch): void {
|
|
32
|
+
const target = this.targetNode;
|
|
33
|
+
if (!target) return;
|
|
34
|
+
// 安全使用 target
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ❌ 审查不通过
|
|
38
|
+
const sprite = this.node.getComponent(Sprite)!; // 危险的非空断言(除非确定一定存在)
|
|
39
|
+
sprite.spriteFrame = newFrame;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. 资源生命周期
|
|
45
|
+
|
|
46
|
+
### 2.1 加载-释放配对
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
每个 resources.load / bundle.load → 必须有对应的释放策略
|
|
50
|
+
每个 addRef() → 必须有对应的 decRef()
|
|
51
|
+
每个 instantiate() → 必须有对应的 destroy()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 2.2 审查清单
|
|
55
|
+
|
|
56
|
+
| 检查项 | 严重级 |
|
|
57
|
+
|--------|--------|
|
|
58
|
+
| load 回调处理了 err 参数 | 🔴 |
|
|
59
|
+
| 动态加载并长期持有的资源调用了 addRef | 🔴 |
|
|
60
|
+
| onDestroy 中为持有资源调用了 decRef | 🔴 |
|
|
61
|
+
| 对象池 clear 时释放资源引用 | 🔴 |
|
|
62
|
+
| instantiate 的节点在不需要时 destroy | 🟡 |
|
|
63
|
+
| 场景勾选自动释放(除主场景外) | 🟡 |
|
|
64
|
+
| 不在 resources 目录放不需要动态加载的资源 | 🟡 |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 3. 事件生命周期
|
|
69
|
+
|
|
70
|
+
### 3.1 事件配对表
|
|
71
|
+
|
|
72
|
+
审查时构建以下配对表,确认每个 `on` 都有对应的 `off`:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
┌─────────────┬──────────────────────┬───────────────────────┐
|
|
76
|
+
│ 注册位置 │ on() 调用 │ off() 对应位置 │
|
|
77
|
+
├─────────────┼──────────────────────┼───────────────────────┤
|
|
78
|
+
│ onEnable │ input.on(TOUCH,...) │ onDisable: input.off │
|
|
79
|
+
│ onEnable │ node.on(TOUCH,...) │ onDisable: node.off │
|
|
80
|
+
│ onLoad │ eventBus.on(...) │ onDestroy: eventBus.off│
|
|
81
|
+
└─────────────┴──────────────────────┴───────────────────────┘
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3.2 常见问题
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// ❌ 匿名函数无法取消监听
|
|
88
|
+
onEnable() {
|
|
89
|
+
input.on(Input.EventType.TOUCH_START, (e) => this.handleTouch(e), this);
|
|
90
|
+
// onDisable 中无法 off 这个匿名函数!
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ✅ 使用方法引用
|
|
94
|
+
protected onEnable(): void {
|
|
95
|
+
input.on(Input.EventType.TOUCH_START, this.handleTouch, this);
|
|
96
|
+
}
|
|
97
|
+
protected onDisable(): void {
|
|
98
|
+
input.off(Input.EventType.TOUCH_START, this.handleTouch, this);
|
|
99
|
+
}
|
|
100
|
+
private handleTouch(event: EventTouch): void: void { /* ... */ }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 4. 缓动与定时器
|
|
106
|
+
|
|
107
|
+
### 审查清单
|
|
108
|
+
|
|
109
|
+
| 检查项 | 严重级 |
|
|
110
|
+
|--------|--------|
|
|
111
|
+
| onDestroy 中调用了 `Tween.stopAllByTarget(this.node)` | 🔴 |
|
|
112
|
+
| onDestroy 中调用了 `this.unscheduleAllCallbacks()` | 🔴 |
|
|
113
|
+
| 缓动目标节点仍然有效(未被销毁) | 🟡 |
|
|
114
|
+
| 长时间运行的缓动有停止条件 | 🟡 |
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// ✅ 标准清理模式
|
|
118
|
+
protected onDestroy(): void {
|
|
119
|
+
Tween.stopAllByTarget(this.node);
|
|
120
|
+
this.unscheduleAllCallbacks();
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 5. update 循环质量
|
|
127
|
+
|
|
128
|
+
### 审查清单
|
|
129
|
+
|
|
130
|
+
| 检查项 | 严重级 | 说明 |
|
|
131
|
+
|--------|--------|------|
|
|
132
|
+
| 无 `new Vec3/Vec2/Color` 等对象创建 | 🟡 | 使用类成员缓存 |
|
|
133
|
+
| 无 `find()` / `getComponent()` 调用 | 🟡 | 提前缓存引用 |
|
|
134
|
+
| 无字符串拼接 | 🟢 | 缓存或使用模板 |
|
|
135
|
+
| 有提前返回跳过不必要逻辑 | 🟢 | `if (!this._active) return;` |
|
|
136
|
+
| 低频逻辑移到 schedule | 🟢 | AI/碰撞检测等 |
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// ✅ 审查通过的 update
|
|
140
|
+
private _tempVec = new Vec3();
|
|
141
|
+
private _isPlaying = false;
|
|
142
|
+
|
|
143
|
+
protected update(dt: number): void {
|
|
144
|
+
if (!this._isPlaying) return;
|
|
145
|
+
|
|
146
|
+
Vec3.set(this._tempVec, this.speed * dt, 0, 0);
|
|
147
|
+
const pos = this.node.position;
|
|
148
|
+
this.node.setPosition(pos.x + this._tempVec.x, pos.y, pos.z);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 6. 编码风格
|
|
155
|
+
|
|
156
|
+
### 6.1 命名审查
|
|
157
|
+
|
|
158
|
+
| 检查项 | 严重级 |
|
|
159
|
+
|--------|--------|
|
|
160
|
+
| 类名 PascalCase | 🟡 |
|
|
161
|
+
| @ccclass 参数与类名一致 | 🟡 |
|
|
162
|
+
| 方法/属性 camelCase | 🟢 |
|
|
163
|
+
| 私有成员 `_` 前缀 | 🟢 |
|
|
164
|
+
| 常量 UPPER_SNAKE_CASE | 🟢 |
|
|
165
|
+
| 事件名 kebab-case | 🟢 |
|
|
166
|
+
|
|
167
|
+
### 6.2 代码组织
|
|
168
|
+
|
|
169
|
+
| 检查项 | 严重级 |
|
|
170
|
+
|--------|--------|
|
|
171
|
+
| 文件不超过 300 行 | 🟢 |
|
|
172
|
+
| 函数不超过 50 行 | 🟢 |
|
|
173
|
+
| 嵌套不超过 3 层 | 🟢 |
|
|
174
|
+
| Import 排列有序 | 🟢 |
|
|
175
|
+
| 无重复代码块 (>10行) | 🟡 |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 7. 调试与日志
|
|
180
|
+
|
|
181
|
+
| 检查项 | 严重级 |
|
|
182
|
+
|--------|--------|
|
|
183
|
+
| 无裸露的 `console.log`(需 `DEBUG` 保护) | 🟡 |
|
|
184
|
+
| 错误日志使用 `console.error` | 🟢 |
|
|
185
|
+
| 无 `debugger` 语句 | 🔴 |
|
|
186
|
+
| 调试工具代码在 BUILD 模式下排除 | 🟡 |
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// ✅ 正确的日志模式
|
|
190
|
+
import { DEBUG } from 'cc/env';
|
|
191
|
+
|
|
192
|
+
if (DEBUG) {
|
|
193
|
+
console.log('Debug info:', data);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 错误始终记录
|
|
197
|
+
console.error('Critical error:', err);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 8. 3.8 特定检查
|
|
203
|
+
|
|
204
|
+
### 从 2.x 升级相关
|
|
205
|
+
|
|
206
|
+
| 检查项 | 严重级 | 说明 |
|
|
207
|
+
|--------|--------|------|
|
|
208
|
+
| 不使用 `cc.` 前缀 | 🔴 | 3.x 使用 ES Module 导入 |
|
|
209
|
+
| 不使用 `CC_DEBUG` / `CC_EDITOR` | 🔴 | 使用 `import { DEBUG, EDITOR } from 'cc/env'` |
|
|
210
|
+
| 不使用 `cc.systemEvent` | 🟡 | 使用 `input` 对象 |
|
|
211
|
+
| 不使用 `Event.EventCustom` | 🟡 | 自定义类继承 `Event` |
|
|
212
|
+
| 不使用 `cc.Class({})` 声明 | 🔴 | 使用 `@ccclass` 装饰器 |
|
|
213
|
+
| 不使用 `cc.tween()` | 🟡 | 使用 `import { tween } from 'cc'` |
|
|
214
|
+
|
|
215
|
+
### 3.8 新特性检查
|
|
216
|
+
|
|
217
|
+
| 检查项 | 严重级 | 说明 |
|
|
218
|
+
|--------|--------|------|
|
|
219
|
+
| 正确使用 `@property` 声明类型 | 🟡 | 引用类型必须显式声明 |
|
|
220
|
+
| 使用 `input` 替代废弃的 `systemEvent` | 🟡 | v3.4+ 推荐 |
|
|
221
|
+
| Bundle 配置在项目设置中正确配置 | 🟡 | v3.8 移到项目设置 |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 审查流程
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
1. 打开变更文件列表
|
|
229
|
+
2. 按优先级顺序检查:
|
|
230
|
+
a. P0 阻断项 → 必须全部通过
|
|
231
|
+
b. P1 重要项 → 确认修复计划
|
|
232
|
+
c. P2 建议项 → 记录到改进清单
|
|
233
|
+
3. 输出审查报告
|
|
234
|
+
4. 跟踪修复状态
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 快速审查命令
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# 搜索 2.x 风格代码
|
|
241
|
+
grep -rn "cc\.\|CC_DEBUG\|CC_EDITOR\|systemEvent" --include="*.ts" assets/scripts/
|
|
242
|
+
|
|
243
|
+
# 搜索裸露的 console.log
|
|
244
|
+
grep -rn "console\.log" --include="*.ts" assets/scripts/ | grep -v "DEBUG"
|
|
245
|
+
|
|
246
|
+
# 搜索 any 类型
|
|
247
|
+
grep -rn ": any\|as any" --include="*.ts" assets/scripts/
|
|
248
|
+
|
|
249
|
+
# 搜索未处理的 err
|
|
250
|
+
grep -rn "err," --include="*.ts" assets/scripts/ | grep -v "if.*err"
|
|
251
|
+
```
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cocos-performance-optimizer
|
|
3
|
+
description: 对 Cocos Creator 3.x(TypeScript)项目进行运行时性能优化,重点在减少函数调用开销、降低运算复杂度、复用对象与排查内存问题。当用户报告 Cocos 项目卡顿/掉帧/CPU 高/GC 抖动/包体或内存问题,要求优化 update/lateUpdate/tick、对象池、Vec2/Vec3 复用,或贴出 DevTools / Cocos Profiler / Performance Call Tree 截图与日志时触发。也适用于审查热点脚本、可试玩广告 60fps 调优、Profiler 分析指导。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Cocos Creator 性能优化专家
|
|
8
|
+
|
|
9
|
+
帮助 Cocos Creator 3.x(TypeScript)项目把 CPU 帧时间和内存抖动压下去。聚焦三件事:**少调用、少计算、多复用**,并提供一套从 Profiler 读数据 → 定位热点 → 给出可落地代码改动的工作流。
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
|
|
13
|
+
- 用户说 Cocos 项目卡顿、掉帧、`update`/`lateUpdate`/`tick` 占用高
|
|
14
|
+
- 用户贴出 Chrome DevTools Performance、Cocos Profiler、Frame 分析截图或火焰图
|
|
15
|
+
- 需要审查/重构高频调用的脚本(粒子、子弹、敌人 AI、UI 频繁刷新等)
|
|
16
|
+
- 需要引入或复审对象池(NodePool、自定义池)、Vec2/Vec3 复用、`out` 参数模式
|
|
17
|
+
- 可试玩广告(playable ads)需要稳定 60fps、低端机适配
|
|
18
|
+
- 出现 GC 抖动、内存增长、监听器 / 计时器泄漏
|
|
19
|
+
|
|
20
|
+
## When NOT to Use
|
|
21
|
+
|
|
22
|
+
- **包体瘦身 / 资源压缩**:用 `cocos-playable-optimizer` 或 `theone-cocos-standards` 里的资源章节
|
|
23
|
+
- **架构、模块拆分、依赖治理**:用 `architecture` 或 `cocos-creator-3x-cn`
|
|
24
|
+
- **3.x API 用法本身的问题**(不是性能):用 `cocos-creator-3x-cn`
|
|
25
|
+
- **渲染管线、Shader 级别 GPU 优化**:超出本 skill 范围,提示用户走专门通道
|
|
26
|
+
- **没有数据的"感觉慢"**:先让用户跑 Profiler 拿到数据再回来
|
|
27
|
+
|
|
28
|
+
## 核心优化目标
|
|
29
|
+
|
|
30
|
+
1. **减少函数调用开销** — 合并高频小函数、降低调用层级、缓存函数引用
|
|
31
|
+
2. **降低运算复杂度** — 缓存结果、循环外提、避免在 tick 里重算不变量
|
|
32
|
+
3. **最大化对象复用** — 对象池 + 临时数学对象复用,杜绝热路径 `new`
|
|
33
|
+
|
|
34
|
+
## 工作流(按顺序执行)
|
|
35
|
+
|
|
36
|
+
### Step 1:先要数据,不猜
|
|
37
|
+
|
|
38
|
+
在改任何代码前,要求或确认以下至少一项:
|
|
39
|
+
|
|
40
|
+
- Chrome DevTools → Performance 面板的录制(含 Main thread 火焰图、Bottom-Up)
|
|
41
|
+
- Cocos Creator 编辑器 / 真机 Profiler 截图(FPS、Draw Call、Logic、Render 时间)
|
|
42
|
+
- 帧时间日志:`game.frameTime`、`director.getDeltaTime()` 趋势
|
|
43
|
+
- 复现场景描述:低端机型号、复现步骤、现象(卡帧/掉帧/启动慢/操作后卡)
|
|
44
|
+
|
|
45
|
+
如果用户只说"慢",不要凭空改代码。**先指导他们怎么采集数据**(见 §Profiler 分析指南)。
|
|
46
|
+
|
|
47
|
+
### Step 2:定位热点
|
|
48
|
+
|
|
49
|
+
按以下优先级查瓶颈:
|
|
50
|
+
|
|
51
|
+
1. **Main Thread Long Tasks > 50ms** — 单帧爆点
|
|
52
|
+
2. **Self Time Top 10 函数** — 自身耗时大户,多半是热路径主体
|
|
53
|
+
3. **Total Time Top 10 函数** — 调用链顶部的协调者,删一处省一片
|
|
54
|
+
4. **Bottom-Up 高频叶子函数** — 被疯狂调用的小函数,最适合内联/缓存
|
|
55
|
+
5. **GC / Minor GC 抖动** — 锯齿状帧时间通常是临时对象太多
|
|
56
|
+
|
|
57
|
+
记录定位结果(哪个文件 / 哪个函数 / 调用次数 / 单次耗时 / 帧占比),再进入 Step 3。
|
|
58
|
+
|
|
59
|
+
### Step 3:按类别套优化清单
|
|
60
|
+
|
|
61
|
+
#### 3.1 函数调用优化
|
|
62
|
+
|
|
63
|
+
- [ ] `update / lateUpdate / tick` 里被调用的所有函数过一遍:能内联的内联
|
|
64
|
+
- [ ] 把"每帧不变的查询"挪到 `onLoad / onEnable / start`:`getComponent`、`find`、`getChildByName`
|
|
65
|
+
- [ ] 缓存方法引用:`const setPos = this.node.setPosition.bind(this.node)`,避免 `.` 链式查找
|
|
66
|
+
- [ ] 合并相似职责的小函数(`updatePosX` + `updatePosY` → `updatePos`)
|
|
67
|
+
- [ ] 减少深层嵌套调用链:3 层以上的同模块调用通常可拍平
|
|
68
|
+
- [ ] `EventTarget.emit` 在热路径慎用,改直接函数调用或回调引用
|
|
69
|
+
|
|
70
|
+
#### 3.2 运算优化
|
|
71
|
+
|
|
72
|
+
- [ ] **循环外提**:所有循环不变量提到 `for` 之外(包括 `arr.length`)
|
|
73
|
+
- [ ] **缓存结果**:本帧多处用到的值算一次存到局部变量
|
|
74
|
+
- [ ] **减少高开销函数**:`Math.sqrt` 用平方距离替代、`Math.sin/cos` 用查表
|
|
75
|
+
- [ ] **位运算替代**:整数乘除 2 的幂用 `<<` `>>`;`Math.floor(x)` 用 `x | 0`(仅当 x ∈ int32)
|
|
76
|
+
- [ ] **避免热路径 `new`**:`new Vec3()`、`new Color()`、字面量数组 / 对象都算
|
|
77
|
+
- [ ] **字符串拼接热点**:用模板字符串或预生成;不要在 update 里拼 path
|
|
78
|
+
|
|
79
|
+
#### 3.3 对象复用
|
|
80
|
+
|
|
81
|
+
- [ ] 频繁创建/销毁的节点 → `NodePool`(先 `put` 再 `get`)
|
|
82
|
+
- [ ] 频繁 new 的数据对象 → 自定义对象池(数组栈,`acquire/release`)
|
|
83
|
+
- [ ] 数学对象用 **静态临时变量** 复用:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
private static readonly _tmpV3 = new Vec3();
|
|
87
|
+
// 热路径里
|
|
88
|
+
Vec3.subtract(MyClass._tmpV3, a, b);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- [ ] 优先使用带 `out` 参数的 API:`Vec3.add(out, a, b)` 而不是 `a.clone().add(b)`
|
|
92
|
+
- [ ] 数组预分配:`const arr = new Array(n)`,避免 `push` 触发扩容
|
|
93
|
+
- [ ] 事件对象复用:自定义事件 payload 用同一个对象重置字段
|
|
94
|
+
|
|
95
|
+
#### 3.4 内存与生命周期
|
|
96
|
+
|
|
97
|
+
- [ ] `onDestroy` 里:`node.off(...)` / `EventTarget.off`、清 `setTimeout/Interval`、`unschedule`
|
|
98
|
+
- [ ] 资源释放:`assetManager.releaseAsset` / `bundle.release` 的时机正确
|
|
99
|
+
- [ ] 循环引用:父子节点互相持有时考虑弱引用或显式解开
|
|
100
|
+
- [ ] 监听器去重:注册前判断或先 `off` 再 `on`
|
|
101
|
+
|
|
102
|
+
### Step 4:给出可落地的代码改动
|
|
103
|
+
|
|
104
|
+
每条建议**必须**包含:
|
|
105
|
+
|
|
106
|
+
1. **位置**:文件:行号(或"在 XxxComponent.update 中")
|
|
107
|
+
2. **优化前 / 优化后** 代码对比
|
|
108
|
+
3. **优化原因**:哪条清单 + 为什么省
|
|
109
|
+
4. **预估收益**:定性("减少每帧 N 次 GC 分配")或定量("调用次数 60→1,自身耗时 -85%")
|
|
110
|
+
5. **风险点**:是否影响行为、是否需要重测某个场景
|
|
111
|
+
|
|
112
|
+
### Step 5:复测
|
|
113
|
+
|
|
114
|
+
要求用户用相同场景再跑一次 Profiler 比对:
|
|
115
|
+
|
|
116
|
+
- FPS / 帧时间均值 + 99 分位
|
|
117
|
+
- 目标函数的 Self Time / Total Time
|
|
118
|
+
- GC 次数与停顿时长
|
|
119
|
+
|
|
120
|
+
如果改完没变好,回 Step 2 重新定位(说明你打错靶子了)。
|
|
121
|
+
|
|
122
|
+
## Profiler 分析指南
|
|
123
|
+
|
|
124
|
+
### A. Chrome DevTools Performance(H5 / 预览模式)
|
|
125
|
+
|
|
126
|
+
**采集**:F12 → Performance → 录制 5–10 秒 → Stop。
|
|
127
|
+
|
|
128
|
+
**关键面板**:
|
|
129
|
+
|
|
130
|
+
1. **Main 轨道(火焰图)**
|
|
131
|
+
- 找黄色 Scripting 块里的"长条"——长 = 单次耗时高
|
|
132
|
+
- 找密集的窄条——窄 + 多 = 高频调用
|
|
133
|
+
- 红色三角 = Long Task(>50ms),优先处理
|
|
134
|
+
|
|
135
|
+
2. **Bottom-Up(自下而上)**
|
|
136
|
+
- 按 **Self Time** 倒序:自身耗时榜,热点函数本体
|
|
137
|
+
- 按 **Total Time** 倒序:含子调用的总耗时,找上游入口
|
|
138
|
+
- 展开 → 查看调用来源,定位到具体业务代码
|
|
139
|
+
|
|
140
|
+
3. **Call Tree(自上而下)**
|
|
141
|
+
- 看 `requestAnimationFrame → director._tick → ...` 这条主链
|
|
142
|
+
- 找 `Component.update` 类别下的大头
|
|
143
|
+
|
|
144
|
+
4. **Memory + Performance 联看**
|
|
145
|
+
- 锯齿状内存曲线 = GC 频繁 → 找热路径的对象分配
|
|
146
|
+
- 持续上涨不回落 = 泄漏 → Heap Snapshot 对比
|
|
147
|
+
|
|
148
|
+
### B. Cocos Creator Profiler(编辑器 / 真机)
|
|
149
|
+
|
|
150
|
+
- **FPS**:稳定值 vs 抖动 → 抖动通常是 GC 或偶发长任务
|
|
151
|
+
- **Logic(逻辑) vs Render(渲染)** 时间占比:
|
|
152
|
+
- Logic 高 → 脚本优化(本 skill 主战场)
|
|
153
|
+
- Render 高 → Draw Call、合批、Shader(不在本 skill)
|
|
154
|
+
- **Draw Call**:>100 在低端机就要警惕;本 skill 不深入,但要识别
|
|
155
|
+
- **Triangles / Vertices**:突变说明有大模型/特效进出
|
|
156
|
+
|
|
157
|
+
### C. 真机数据采集(Android)
|
|
158
|
+
|
|
159
|
+
- USB 连接 → Chrome `chrome://inspect` 调试 WebView
|
|
160
|
+
- 或 Cocos `--debug` 包配合 `cc.profiler.showStats()`
|
|
161
|
+
- 关注**低端机**而不是开发机;iPhone Pro 上看不到的问题,红米上一抓一大把
|
|
162
|
+
|
|
163
|
+
## 输出格式
|
|
164
|
+
|
|
165
|
+
回复用户时按以下结构组织:
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
## 性能瓶颈定位
|
|
169
|
+
- 热点 1:<文件:行> | Self Time XX ms | 调用次数 N
|
|
170
|
+
- 热点 2:...
|
|
171
|
+
|
|
172
|
+
## 优化方案
|
|
173
|
+
|
|
174
|
+
### 优化点 A:<标题>
|
|
175
|
+
**位置**:path/to/file.ts:123
|
|
176
|
+
**类别**:函数调用优化 / 运算优化 / 对象复用 / 内存
|
|
177
|
+
|
|
178
|
+
**优化前:**
|
|
179
|
+
```ts
|
|
180
|
+
// ...原代码...
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**优化后:**
|
|
184
|
+
```ts
|
|
185
|
+
// ...新代码...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**原因**:<对应清单条目 + 解释>
|
|
189
|
+
**预估收益**:<定量或定性>
|
|
190
|
+
**风险**:<行为差异 / 需要回归的场景,或"无">
|
|
191
|
+
|
|
192
|
+
### 优化点 B:...
|
|
193
|
+
|
|
194
|
+
## 复测建议
|
|
195
|
+
- 跑一次 <场景>,对比 <指标>
|
|
196
|
+
- 重点验证 <可能受影响的功能>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Anti-Patterns(不要这么做)
|
|
200
|
+
|
|
201
|
+
- **没数据先改代码** — 90% 的"优化"会打错靶子,可能反而变慢
|
|
202
|
+
- **过度对象池化** — 一次性、低频对象别建池,池本身有维护成本
|
|
203
|
+
- **过早微优化** — 还没找到瓶颈就到处 `x | 0`,可读性崩了收益为零
|
|
204
|
+
- **改完不复测** — 你以为快了,可能只是浏览器缓存热了
|
|
205
|
+
- **盲目用 `requestAnimationFrame` 替代 `update`** — Cocos 的调度链你绕不开
|
|
206
|
+
- **把 `update` 改成 `schedule(fn, 0)`** — 调度开销可能更高
|
|
207
|
+
- **对临时变量用 `static` 但忘了线程安全** — 单线程 JS 没事,但被嵌套调用时会互相覆盖
|
|
208
|
+
|
|
209
|
+
## Related Skills
|
|
210
|
+
|
|
211
|
+
- `cocos-creator-3x-cn` — 3.x API 正确用法(先把 API 用对,再谈优化)
|
|
212
|
+
- `theone-cocos-standards` — TheOne Studio 的代码规范与 playable 约束
|
|
213
|
+
- `cocos-playable-optimizer` — 包体大小 / 资源压缩(互补维度)
|
|
214
|
+
- `code-review` — 优化改动较大时配合做一轮系统化 review
|