外观
Lesson 008|onLoad、start、update 到底什么时候执行?
Tags: #Creator2.x #Component #Lifecycle #Update #EventDifficulty: ⭐⭐☆☆☆
🎯 本课目标
- 理解 Component 生命周期
- 理解 onLoad、onEnable、start、update、onDisable、onDestroy 的职责
- 理解 onLoad 和 start 的区别
- 理解为什么空 update 也有成本
- 理解事件注册和取消的正确时机
🧩 上节课回顾
上一课我们讲了 Node + Component 架构。
Component 一个重要特点是:
它有生命周期。
你每天写的:
ts
onLoad() {}
start() {}
update(dt) {}
onEnable() {}
onDisable() {}
onDestroy() {}都属于 Component 生命周期。
💡 生命周期是什么?
生命周期可以理解成:
引擎在不同时间点自动调用你的函数。
常见流程:
text
节点 / 组件被创建
↓
onLoad
↓
节点激活
↓
onEnable
↓
第一帧 update 前
↓
start
↓
每一帧
↓
update
↓
组件或节点被禁用
↓
onDisable
↓
节点被销毁
↓
onDestroy🧠 onLoad
onLoad 可以理解成:
组件初始化时调用。
常用于:
text
获取节点引用
初始化变量
绑定固定引用
读取配置
建立组件之间的关系例如:
ts
onLoad() {
this.icon = this.node.getChildByName("Icon");
this.button = this.node.getComponent(cc.Button);
}🧠 start
start 可以理解成:
第一次 update 之前调用。
onLoad 更早,start 更晚。
有时候你需要等所有组件都 onLoad 完,再做某些逻辑,这时 start 更合适。
🧠 update
update(dt) 是每帧调用。
例如:
ts
update(dt) {
this.node.x += 100 * dt;
}dt 是上一帧到这一帧经过的时间。
如果游戏 60 FPS:
text
dt ≈ 0.016所以移动常写:
ts
this.node.x += speed * dt;而不是:
ts
this.node.x += speed;因为后者会受帧率影响。
🧠 onEnable 和 onDisable
onEnable
组件进入启用状态时调用。
常用于注册事件:
ts
onEnable() {
this.node.on(cc.Node.EventType.TOUCH_END, this.onClick, this);
}onDisable
组件退出启用状态时调用。
常用于取消事件:
ts
onDisable() {
this.node.off(cc.Node.EventType.TOUCH_END, this.onClick, this);
}重要习惯:
onEnable 注册的事件,优先在 onDisable 取消。
🧠 onDestroy
onDestroy 是组件销毁时调用。
常用于:
text
释放资源
清理引用
取消定时器
取消全局事件监听
取消网络回调尤其是全局事件、网络回调、定时器,如果不清理,可能导致对象销毁后仍然被回调。
🔍 常见执行顺序
text
onLoad
↓
onEnable
↓
start
↓
update / lateUpdate
↓
onDisable
↓
onDestroy其中:
text
onLoad:初始化
onEnable:开始启用
start:第一次 update 前
update:每帧逻辑
lateUpdate:每帧后半段逻辑
onDisable:停止启用
onDestroy:销毁清理🔍 onLoad 和 start 怎么选?
放在 onLoad
text
获取自身节点引用
初始化字段
绑定固定引用
准备基础数据放在 start
text
依赖其他组件已经初始化
依赖场景中其他节点 onLoad 完成
第一次显示前执行逻辑🧠 为什么空 update 也有成本?
只要组件实现了:
ts
update(dt) {
}引擎就可能把它加入每帧调度列表。
即使函数是空的,也有成本:
text
调度列表记录
每帧遍历
enabled / activeInHierarchy 判断
函数调用所以:
不用 update,就不要写空 update。
💼 工作中的真实案例
事件重复绑定
如果写了:
ts
onEnable() {
this.node.on("click", this.onClick, this);
}但没有:
ts
onDisable() {
this.node.off("click", this.onClick, this);
}节点反复 active true / false 后,可能导致事件重复绑定。
结果可能是:
text
点一次按钮,回调执行多次⚠️ 常见误区
- onLoad 和 start 不应该随便混用。
- 空 update 也有成本。
- 事件注册后要考虑取消。
- active = false 不只是隐藏,也会触发 onDisable,影响 update、事件响应和子节点激活状态。
🎤 面试会怎么问
onLoad 和 start 有什么区别?
onLoad 在组件初始化时调用,通常用于初始化自身引用和变量;start 在第一次 update 之前调用,通常用于依赖其他组件 onLoad 完成后的逻辑。
enabled = false 会触发什么?
组件从启用状态切到禁用状态时,会触发 onDisable;如果之后重新 enabled = true,并且节点处于 activeInHierarchy 状态,会触发 onEnable。
为什么不建议写空 update?
只要组件实现了 update,引擎就可能把它加入每帧调度列表。即使函数为空,也会有调度、遍历、状态判断和函数调用成本。
onEnable 注册事件,应该在哪里取消?
通常应该在 onDisable 中取消。onDestroy 可以做最终兜底清理,特别是全局事件、网络回调和定时器。
📝 今日练习参考答案
- 正常顺序:
text
onLoad
↓
onEnable
↓
start
↓
update / lateUpdate 每帧执行
↓
onDisable
↓
onDestroy如果节点
active = false,通常触发onDisable,并停止 update、事件响应和渲染相关逻辑。如果组件
enabled = false,通常也会触发onDisable。区别是:node.active = false:影响整个节点和子树component.enabled = false:只影响这个组件
空 update 也会被每帧调度和调用,有成本。
在
onEnable注册事件,通常应该在onDisable取消事件。onDestroy可以做兜底清理。
🚀 能力成长
学完本课后,你应该能:
- 解释 Component 生命周期
- 区分 onLoad 和 start
- 解释 update 的调度成本
- 正确处理事件注册与取消
- 初步分析生命周期导致的重复事件、内存泄漏和性能问题
✅ 本课总结
text
onLoad:初始化自身。
onEnable:组件进入启用状态。
start:第一次 update 前。
update:每帧执行。
onDisable:组件退出启用状态。
onDestroy:销毁清理。工程习惯:
text
onEnable 注册的事件,优先在 onDisable 取消。
不用 update,就不要写空 update。下一课: active、enabled、destroy 的区别