外观
Lesson 009|active、enabled、destroy 的区别
Tags: #Creator2.x #Node #Component #active #enabled #destroyDifficulty: ⭐⭐☆☆☆
🎯 本课目标
- 理解
node.active、component.enabled、node.destroy()的区别 - 理解
active和activeInHierarchy - 理解父节点
active=false为什么会影响子节点 - 理解什么时候隐藏、什么时候禁用组件、什么时候销毁
- 为 UI 管理、对象池、性能优化打基础
🧩 上节课回顾
上一课我们讲了 Component 生命周期:
text
onLoad
↓
onEnable
↓
start
↓
update
↓
onDisable
↓
onDestroy并且记住了:
text
onEnable 注册事件,优先在 onDisable 取消。
不用 update,就不要写空 update。这一课我们把几个经常混用的概念彻底分清楚:
text
node.active
component.enabled
node.destroy()💡 先给结论
这三个东西解决的问题完全不同:
text
active :控制 Node 以及子树是否激活
enabled :控制某个 Component 是否启用
destroy :销毁 Node 或 Component更直观一点:
text
node.active = false
↓
关闭整个节点 / 子树
component.enabled = false
↓
关闭某个组件
node.destroy()
↓
销毁这个节点所以它们不是同一个层级的东西。
🧠 active:控制节点和子树
active 是 Node 上的属性。
例如:
ts
this.panel.active = false;它表示:
这个节点自己是否想激活。
但它不仅影响自己,还会影响子节点的最终激活状态。
例如:
text
Panel
├── Title
├── Button
└── RewardList如果:
ts
Panel.active = false;那么通常:
text
Panel 不显示
Title 不显示
Button 不响应
RewardList 不显示
挂在这些节点上的组件 update 停止
子节点 activeInHierarchy 变 false所以 active=false 更像是:
把这一整棵节点树暂时从运行状态中关掉。
🧠 active 和 activeInHierarchy
Creator 里要区分:
text
active
activeInHierarchy可以这样理解:
text
active:我自己想不想激活
activeInHierarchy:结合父节点以后,我最终是否真的激活例如:
text
Panel.active = false
Button.active = true那么:
text
Button.active = true
Button.activeInHierarchy = false原因是:
Button 自己想激活,但它的父节点 Panel 是关闭的。
所以子节点最终是否激活,不只看自己,还要看父节点。
可以简单理解为:
text
child.activeInHierarchy =
parent.activeInHierarchy && child.active如果有多层父节点,则要一路往上判断。
🔍 父节点 active=false,会不会把子节点 active 改成 false?
不会。
例如:
ts
parent.active = false;
child.active = true;这时通常是:
text
parent.active = false
child.active = true
child.activeInHierarchy = false父节点关闭后,引擎不会简单粗暴地把:
ts
child.active = false;因为如果这么做,父节点重新打开时,子节点原本的状态就丢了。
例如:
text
Panel.active = false
Button.active = true
RedPoint.active = false之后:
ts
Panel.active = true;引擎需要恢复成:
text
Button 仍然 active = true
RedPoint 仍然 active = false所以父节点影响的是子节点的 activeInHierarchy,不是强行改掉子节点自己的 active。
🧠 enabled:控制某个组件
enabled 是 Component 上的属性。
例如:
ts
this.rotateScript.enabled = false;它表示:
关闭这个组件本身。
例如:
text
AvatarNode
├── Sprite
├── Button
└── RotateScript如果:
ts
rotateScript.enabled = false;那么通常:
text
RotateScript 不 update
RotateScript 的逻辑停止
Sprite 仍然显示
Button 仍然可以点击
AvatarNode 仍然 active所以 enabled=false 是局部关闭。
它不是隐藏节点,也不是销毁节点。
🔍 update 是否执行,看哪些条件?
一个组件的 update 是否执行,通常看:
text
1. 组件实现了 update
2. component.enabled = true
3. node.activeInHierarchy = true
4. 对象没有被 destroy所以如果父节点:
ts
Panel.active = false;子节点虽然:
text
StartButton.active = true
StartButtonScript.enabled = true但:
text
StartButton.activeInHierarchy = false因此:
text
StartButtonScript.update 不执行注意:
不是父节点 update 不调用,导致子节点 update 不调用。 而是子节点的 activeInHierarchy=false,所以它不进入 update 调度。
🧠 active 和 enabled 的区别
可以这样记:
text
active 管 Node
enabled 管 Component也可以类比:
text
active 是关电闸
enabled 是关某个电器开关例如:
text
房间 = Node
灯 = Sprite
门铃 = Button
风扇 = RotateScript如果:
text
node.active = false相当于房间断电。
灯不亮,门铃不响,风扇也停。
如果:
text
rotateScript.enabled = false只是风扇关了。
灯还亮,门铃还响。
🧠 destroy:销毁对象
destroy 和 active / enabled 完全不同。
ts
node.destroy();表示:
这个节点要被销毁。
销毁后,它不是暂时关闭,而是准备从场景中移除。
如果:
ts
rewardItem.destroy();那么这个节点以及子节点都会进入销毁流程。
销毁后不应该再继续使用。
🔍 destroy 不是简单的“马上凭空消失”
在 Creator 里,destroy() 通常可以先理解为:
text
destroy()
↓
标记这个对象要销毁
↓
当前帧后续流程中被清理
↓
onDestroy 被调用
↓
对象不应该再被使用所以写了:
ts
node.destroy();
console.log(node);变量可能还暂时有引用,但这个对象已经不应该继续当正常节点使用。
🧠 active=false 和 destroy 的区别
active=false
适合:
text
暂时隐藏
后面还会再显示
反复打开 / 关闭的界面
对象池中的对象例如:
ts
this.panel.active = false;以后还能:
ts
this.panel.active = true;恢复使用。
destroy
适合:
text
确定以后不用了
切场景清理
临时特效播放结束
一次性弹窗关闭后释放
列表 item 不再复用例如:
ts
this.effectNode.destroy();销毁后就不要再拿它继续操作。
🧠 enabled=false 和 destroy component 的区别
enabled=false
适合:
text
只是暂时关掉某个功能
节点还要显示
其他组件还要工作例如:
ts
this.rotateScript.enabled = false;头像还显示,只是不旋转。
destroy component
例如:
ts
this.rotateScript.destroy();适合:
text
这个组件以后真的不需要了但实际项目里,一般不建议频繁 destroy / addComponent,因为组件创建和销毁有成本。
更常见的是:
ts
component.enabled = false;💼 工作中的真实案例
案例一:弹窗关闭
如果是主界面常用弹窗:
text
ShopPanel
BagPanel
TaskPanel通常不建议每次关闭都 destroy。
更常见:
ts
panel.active = false;下次打开:
ts
panel.active = true;这样不用重新创建节点和组件。
但如果弹窗很占内存,且很少打开,也可以考虑销毁并释放资源。
案例二:列表 Item
ScrollView 里有很多 item。
不推荐频繁:
ts
item.destroy();再:
ts
cc.instantiate(prefab);因为创建销毁成本高。
更好的方式是:
text
对象池
item.active = false
下次复用 item.active = true
刷新数据案例三:按钮显示但不能点击
例如一个按钮在冷却中,想让它看得见,但不能点击。
不要写:
ts
buttonNode.active = false;因为这样按钮会消失。
更合适:
ts
button.getComponent(cc.Button).interactable = false;或者视情况:
ts
button.getComponent(cc.Button).enabled = false;一般“按钮显示但不可点击”,优先考虑 interactable=false。
案例四:特效播放结束
一次性爆炸特效播放结束后如果不再复用,可以:
ts
effectNode.destroy();如果这种特效频繁出现,建议使用对象池,而不是频繁 destroy / instantiate。
⚠️ 常见误区
误区一:active=false 就是 destroy
不是。
active=false 是暂时关闭,节点还在。
destroy() 是销毁,节点后续不应该再使用。
误区二:enabled=false 会隐藏节点
不一定。
enabled=false 只关闭某个组件。
例如关闭脚本组件不会让 Sprite 消失。
误区三:destroy 后马上还能安全继续用
不应该。
即使变量还引用着它,也不应该继续操作已经 destroy 的对象。
误区四:为了省性能,所有不用的东西都 destroy
不一定。
频繁 destroy / instantiate 也很耗性能。
对于会反复使用的对象,应该考虑:
text
active=false
对象池
复用🎤 面试会怎么问
active 和 enabled 有什么区别?
参考回答:
active 是 Node 的激活状态,会影响节点及其子树;enabled 是 Component 的启用状态,只影响当前组件。active=false 会让节点从 activeInHierarchy 中退出,影响显示、事件和 update;enabled=false 通常只关闭该组件的生命周期和功能。
active=false 和 destroy 有什么区别?
参考回答:
active=false 是暂时禁用节点,节点仍然存在,可以再次 active=true 恢复;destroy 是销毁对象,之后不应该再继续使用,通常会触发 onDestroy 并由引擎清理。
父节点 active=false,子节点 active=true,为什么子节点 update 不执行?
参考回答:
因为 update 是否执行看的是节点的 activeInHierarchy,而不只是 active。父节点 active=false 后,子节点自己的 active 仍然可以是 true,但子节点 activeInHierarchy 会变成 false,所以挂在子节点上的组件不会进入 update 调度。
为什么列表 item 不建议频繁 destroy?
参考回答:
频繁 destroy 和 instantiate 会带来对象创建、销毁、生命周期调用、内存分配和 GC 压力。对于列表 item,更推荐使用对象池和 active 控制显示隐藏。
📝 今日练习参考答案
题目:
text
ActivityPanel
├── CloseButton
│ ├── Sprite
│ └── Button
├── RewardList
└── CountDownScript答案:
- 如果只是临时关闭整个活动界面,应该用:
ts
ActivityPanel.active = false;- 如果关闭后确定这个界面以后不会再用,可以考虑:
ts
ActivityPanel.destroy();但真实项目里还要考虑资源释放、引用清理、事件解绑等问题。
- 如果 CloseButton 还要显示,但暂时不能点击,不应该关
CloseButton.active,应该关 Button 的交互,例如:
ts
closeButton.getComponent(cc.Button).interactable = false;- 如果只想暂停 CountDownScript 的 update,但界面还要显示,应该:
ts
this.countDownScript.enabled = false;- 列表 item 不建议频繁 destroy / instantiate,因为每次创建和销毁都有节点、组件、生命周期、内存分配、GC 和渲染数据重建成本。更推荐对象池复用。
🚀 能力成长
学完本课后,你应该能:
- 判断什么时候用 active,什么时候用 enabled,什么时候用 destroy
- 解释 active 和 activeInHierarchy 的关系
- 解释父节点 active=false 为什么会影响子节点 update
- 在 UI 管理中避免错误隐藏、错误销毁、错误禁用
- 为后续对象池和性能优化建立基础
✅ 本课总结
记住这几句话:
text
active:控制 Node 及其子树。
enabled:控制某个 Component。
destroy:销毁对象。
父节点 active=false,不会改掉子节点自己的 active。
父节点 active=false,会让子节点 activeInHierarchy=false。
update 是否执行,看 activeInHierarchy、enabled、是否实现 update、是否已销毁。
反复打开关闭的对象优先 active=false,不要频繁 destroy。下一课: Stage01 阶段复习:从 API 到引擎数据流