cocos-creatorlisted
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# Cocos Creator 最佳实践
## 何时用
- 编写任何 Cocos Creator TypeScript 组件脚本前。
- 发现内存持续上涨、资源释放后再加载仍占用内存时。
- 节点引用丢失、组件生命周期回调顺序不符合预期时。
- EventTarget 事件监听器未被正确注销,导致重复触发或内存泄漏时。
- prefab 频繁 instantiate/destroy 造成帧率抖动时。
## 核心规则
### 1. 组件化:@property 暴露,生命周期时序清楚
**规则:** 逻辑封装在继承自 `Component` 的脚本里,Inspector 可调属性用 `@property` 装饰器声明;`onLoad` 做自身初始化,`start` 做跨组件依赖初始化,`onEnable`/`onDisable` 管理激活态资源,`onDestroy` 清理一切外部引用。
**为什么:** AI 生成 Creator 组件时最常见的错误是在 `onLoad` 里调用另一个组件的方法——但另一个组件的 `onLoad` 还没执行,得到 undefined 或抛出"Cannot read property of undefined"。新手则把所有逻辑都堆进 `start`,`onEnable`/`onDisable` 完全不用,导致节点被反复激活时调度器和事件重复注册,表现为每激活一次组件,事件就多响应一次。正确的分层:`onLoad` = 自身组件引用缓存;`start` = 订阅事件、跨节点通信;`onEnable` = 恢复运行状态;`onDisable` = 暂停运行状态;`onDestroy` = 注销事件、释放资源。
**怎么做:**
- `@property(cc.Node) targetNode: cc.Node = null!;` — Inspector 拖拽赋值,不在代码里 find。
- `onLoad` 里只缓存 `this.getComponent`、`this.node.getChildByName` 等本节点树内的引用。
- 跨节点通信(如 GameManager)的引用在 `start` 里获取,保证对方 `onLoad` 已完成。
- `onDestroy` 里注销所有 EventTarget 监听器,停止所有 tween,清空定时器。
---
### 2. 节点引用:缓存引用,prefab 高频对象用对象池
**规则:** 节点或组件引用在 `onLoad` 里缓存成私有字段,绝不在 `update` 或高频函数里调用 `find`、`getChildByName`、`getComponent`;频繁实例化销毁的对象(子弹、特效、列表项)用 `NodePool` 管理,不用 `instantiate` + `destroy`。
**为什么:** `node.getChildByName("xxx")` 是线性遍历子节点树,在 `update` 里每帧调用、节点树稍大时就能感受到 CPU 消耗。AI 写原型代码时习惯"需要用谁就 find 谁",在单个脚本里看起来没问题,但一旦场景有几十个同类组件并发运行,性能立刻崩塌。对象池的价值:移动端 `instantiate` 一个复杂 prefab 耗时可达数十毫秒(涉及资源解析、组件初始化),批量生成敌人或特效时直接造成卡顿帧;`NodePool` 复用已有节点,激活耗时降一个数量级。新手不用对象池的另一个原因是不知道如何处理"归还时重置