生命周期:何时初始化、监听和清理
场景里的对象会创建、启用、停用和销毁。你需要在合适的阶段接线,并在不再使用时断开。最常见的故障是:第一次正确,重进后一次点击执行两遍。
先记住这条主线
这是常见生命周期的教学主线。不要依赖不同节点上同名回调的偶然执行顺序;有依赖就明确初始化顺序。
完整例子:移动并可暂停
Mover.ts
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('Mover')
export class Mover extends Component {
@property
speed = 120;
private moving = true;
onEnable() {
this.node.on(Node.EventType.TOUCH_END, this.toggle, this);
}
onDisable() {
this.node.off(Node.EventType.TOUCH_END, this.toggle, this);
}
private toggle() { this.moving = !this.moving; }
update(dt: number) {
if (!this.moving) return;
const p = this.node.position;
this.node.setPosition(p.x + this.speed * dt, p.y, p.z);
}
}
挂在一个带 UITransform 和可见 Sprite 的节点上。点击可停止/继续,停用再启用不会增加监听数量。这个例子没有限制移动范围,测试时留足屏幕空间。
清理哪些东西
| 创建的行为 | 对应清理 |
|---|---|
node.on 或 input.on | 用同一函数引用和 target 调用 off |
schedule 定时任务 | 对应 unschedule,或组件职责范围内取消任务 |
| 组件拥有的 Tween | 明确停止,必要时复位属性 |
| 异步加载、网络回调 | 回来后检查对象是否仍有效、结果是否过期 |
| 对象池节点上的临时状态 | 回收时复位,取出时重新初始化 |
不要用两个不同的匿名函数分别 on 与 off。写法看起来一样,不代表是同一个函数对象。若使用箭头回调,把它保存为稳定字段。
验收与 AI 提问
连续启用/停用三次后点击一次,只触发一次;退出场景后无旧任务改 UI;重新开始不叠加倒计时。
给 AI:“请列出这个组件创建了哪些监听、定时器、Tween 和异步任务,每个分别在哪里清理。不要靠场景最终销毁来掩盖组件反复启用的问题。”