外观
Stage02|Engine Loop
Lesson018|active、activeInHierarchy、enabled 如何影响调度?
Tags: #Creator2.x #Stage02 #active #activeInHierarchy #enabledDifficulty: ⭐⭐⭐⭐☆
一、本课目标
Stage01 已经区分过三个状态,本课把它们放回 Engine Loop:
一个节点或组件状态改变后,调度系统在本帧和后续帧如何响应?
完成本课后,你应该能够:
- 解释
active、activeInHierarchy、enabled的层级差异。 - 判断父节点关闭时子节点为什么不再 update。
- 解释同一帧启用、禁用和销毁的工程风险。
- 选择局部停用、整棵节点树停用或全局暂停。
二、三个状态分别表示什么
text
Node.active:节点自身的意愿
Node.activeInHierarchy:结合父节点后的最终状态
Component.enabled:某个组件自己的工作开关例如:
text
Root.active = true
Panel.active = false
Button.active = true结果是:
text
Panel.activeInHierarchy = false
Button.activeInHierarchy = false但 Button.active 自己仍然可以是 true。父节点没有替它改写本地属性,只改变了它在场景树中的最终状态。
三、update 的调度条件
一个组件的 update 想被正常调用,通常要满足:
text
组件实现 update
组件 enabled = true
节点 activeInHierarchy = true
对象没有待销毁
游戏主循环正在推进因此下面的状态:
text
child.active = true
child.enabled = true
parent.active = false仍然不能让 child 的 update 执行,因为:
text
child.activeInHierarchy = false四、关闭父节点时发生什么
ts
this.panel.active = false;可以从传播角度理解:
text
Panel.active 变为 false
↓
Panel.activeInHierarchy 变为 false
↓
子节点 activeInHierarchy 递归变化
↓
相关组件收到禁用状态变化
↓
后续 update / 事件 / 渲染不再按启用状态进行重点是:
不是因为父节点的 update 不执行,所以子节点的 update 不执行;而是子节点最终不再满足调度条件。
五、enabled 和 active 的差异
只关闭组件
ts
this.countDown.enabled = false;影响:
text
countDown 不再 update
countDown 的生命周期状态发生变化
Node 仍可能显示
同节点其他组件仍可能工作
子节点不因它单独关闭关闭节点
ts
this.panel.active = false;影响:
text
Panel 和子树 activeInHierarchy 变为 false
相关组件停止正常调度
渲染和交互通常停止
节点对象仍然存在,可以重新 active六、同一帧内改变状态的边界
假设:
ts
update() {
this.enabled = false;
this.node.x = 100;
cc.log('after disable');
}通常不能把 enabled = false 理解为“当前 JavaScript 函数立刻被强行中断”。当前函数已经进入执行,代码会继续执行到函数返回;组件是否进入后续调度,要看引擎下一次检查和当前阶段。
工程上不要依赖这种边界写复杂逻辑。更清晰的写法是:
ts
update(dt: number) {
if (this.shouldStop) {
this.enabled = false;
return;
}
this.runFrame(dt);
}七、重新启用节点会发生什么
ts
this.panel.active = true;如果父节点也激活,子树可能重新获得:
text
activeInHierarchy = true
↓
相关组件 onEnable
↓
重新进入可调度状态
↓
后续 update 恢复但以下内容不会自动重置:
- 业务字段。
- 倒计时剩余值。
- 列表滚动位置。
- 外部服务状态。
所以“重新 active”不是“重新创建一个全新的对象”。需要重置数据时,应提供显式的 reset 或 open 方法。
八、active、enabled、interactable 不是一层
按钮相关状态经常混在一起:
text
node.active = false
→ 节点树不可见、不可正常交互
button.enabled = false
→ Button 组件停止工作
button.interactable = false
→ 按钮通常仍显示,但不可点击具体视觉效果还可能受 Transition、Sprite、脚本和父节点影响。排查“按钮点不了”时应该逐层检查,而不是只改一个布尔值。
九、案例:弹窗三种关闭方式
方式 A:反复打开关闭
ts
this.popup.active = false;适合频繁使用的弹窗。对象保留,打开时恢复 active。
方式 B:只暂停倒计时
ts
this.countDown.enabled = false;适合弹窗仍需显示,但某个逻辑暂时停止。
方式 C:确定不再使用
ts
this.popup.destroy();适合一次性对象或确定不会复用的节点,但要处理引用、事件和资源关系。
十、常见误区
误区一:父节点 active=false 会把子节点 active 属性改成 false
通常不会。改变的是子节点的 activeInHierarchy。
误区二:activeInHierarchy 可以直接当作配置写入
它是结合层级计算出的最终状态,通常用于读取和判断。
误区三:enabled=false 会隐藏组件对应的 Sprite
脚本组件禁用不等于 Sprite 组件禁用。要隐藏显示,应控制节点或渲染组件。
误区四:重新 active=true 会重新执行 start
不要依赖这一点。需要每次打开执行的逻辑放在 onEnable 或显式方法。
误区五:关闭根节点就是全局暂停
根节点之外的 Scheduler、网络、音频和常驻系统可能继续工作。
十一、练习与答案
练习
给出状态:
text
Root.active = true
Panel.active = false
Button.active = true
ButtonScript.enabled = true回答:
- Button.active 是什么?
- Button.activeInHierarchy 是什么?
- ButtonScript.update 会执行吗?
- 如果只将 Panel.active=true,可能恢复什么?
- 如果只将 ButtonScript.enabled=false,Button 是否一定消失?
参考答案
- true。
- false,因为 Panel 没有激活。
- 不会,因为节点不满足 activeInHierarchy 条件。
- Button 的 activeInHierarchy、显示、交互和脚本调度可能恢复,前提是其他状态正常。
- 不一定。只关闭脚本组件,Button 或 Sprite 组件仍可能显示。
十二、Creator 2.4.x 可复现实验:状态矩阵
准备父节点 Panel、子节点 Button 和 ButtonScript,每隔 0.5 秒打印:
ts
cc.log({
active: this.node.active,
activeInHierarchy: this.node.activeInHierarchy,
enabled: this.enabled,
valid: this.node.isValid
});依次执行:Panel.active=false、Panel.active=true、Button.active=false、ButtonScript.enabled=false、ButtonScript.enabled=true。把每一步的状态和 update 日志填入表格。预期 activeInHierarchy 是父链最终结果;关闭脚本不必隐藏节点;销毁后不能再把对象当作可用实例。
典型故障
“按钮看得见但点不了”先检查 Button 组件和 activeInHierarchy,再查遮挡和事件;“脚本不更新但节点可见”检查脚本 enabled、父节点 active 和全局 pause;“重新打开后状态错乱”检查是否只改了 active,却没有恢复业务数据或重新注册监听。
十三、版本边界
active、activeInHierarchy、enabled 和 isValid 是 Creator 2.4.x 的公开状态入口。状态变更何时从当前调度队列移除、同帧剩余组件是否继续,属于具体调度实现;业务代码不应依赖“关闭后这一帧一定还会执行几次”。
十四、应用题与推导答案
题目: 对象池回收一个敌人时,应该销毁节点还是设为 inactive?
答案: 对象池通常设为 inactive 以保留实例和资源,取出时再 active 并重置速度、血量、事件和定时器;真正永久移除且没有复用计划时才 destroy。两种操作都不能替代业务状态重置和监听清理。
十五、本课总结
text
active 是 Node 自身状态。
activeInHierarchy 是层级传播后的最终状态。
enabled 是 Component 自身状态。
父节点关闭会让子节点失去最终激活状态。
重新 active 不等于重建对象。
局部关闭、组件关闭、销毁和全局暂停必须分层选择。十六、下一课预告
text
Lesson019|schedule、Action、Tween、Animation 的时间由谁推进?