Cocos Creator 脚本组件的生与死!
onLoad
start
update
lateUpdate
onDestroy
onEnable
onDisable
测试脚本
const { ccclass, property } = cc._decorator;@ccclassexport default class LifeCycle extends cc.Component {// LIFE-CYCLE CALLBACKS:__preload() {debugger}onLoad() {debugger}onEnable() {debugger}start() {debugger}update(dt) {// debugger}lateUpdate(dt) {// debugger}onDisable() {debugger}onDestroy() {debugger}clickEvent() {// this.node.active = false;// this.node.active = true;// this.node.destroy();this.destroy();}}
触发顺序

调用时机
1__preload onLoad onEnable


active: {get () {return this._active;},set (value) {value = !!value;if (this._active !== value) {this._active = value;var parent = this._parent;if (parent) {// 父节点的激活状态var couldActiveInScene = parent._activeInHierarchy;if (couldActiveInScene) {// 更改节点激活状态cc.director._nodeActivator.activateNode(this, value);}}}}}
activateNode (node, active) {// 激活if (active) {var task = activateTasksPool.get();this._activatingStack.push(task);// 递归激活所有子节点及节点上的所有组件this._activateNodeRecursively(node, task.preload, task.onLoad, task.onEnable);// 调用 __preload()task.preload.invoke();// 调用 onLoad()task.onLoad.invoke();// 调用 onEnable()task.onEnable.invoke();this._activatingStack.pop();activateTasksPool.put(task);}// 禁用else {// 递归禁用所有子节点及节点上的所有组件this._deactivateNodeRecursively(node);// remove children of this node from previous activating tasks to debounce// (this is an inefficient operation but it ensures general case could be implemented in a efficient way)var stack = this._activatingStack;for (var i = 0; i < stack.length; i++) {var lastTask = stack[i];lastTask.preload.cancelInactive(IsPreloadStarted);lastTask.onLoad.cancelInactive(IsOnLoadStarted);lastTask.onEnable.cancelInactive();}}node.emit('active-in-hierarchy-changed', node);}
_activateNodeRecursively (node, preloadInvoker, onLoadInvoker, onEnableInvoker) {// 如果节点正在反激活的过程中则返回if (node._objFlags & Deactivating) {// 对相同节点而言,无法撤销反激活,防止反激活 - 激活 - 反激活的死循环发生。// 这样设计简化了一些引擎的实现,而且对调用者来说能保证反激活操作都能成功。cc.errorID(3816, node.name);return;}node._activeInHierarchy = true;// component maybe added during onEnable, and the onEnable of new component is already called// so we should record the origin lengthvar originCount = node._components.length;// 激活该节点所有组件for (let i = 0; i < originCount; ++i) {let component = node._components[i];if (component instanceof cc.Component) {this.activateComp(component, preloadInvoker, onLoadInvoker, onEnableInvoker);} else {_componentCorrupted(node, component, i);--i;--originCount;}}node._childArrivalOrder = node._children.length;// activate children recursivelyfor (let i = 0, len = node._children.length; i < len; ++i) {let child = node._children[i];// 根据子节点排列顺序设置 _localZOrderchild._localZOrder = (child._localZOrder & 0xffff0000) | (i + 1);if (child._active) {// 递归调用this._activateNodeRecursively(child, preloadInvoker, onLoadInvoker, onEnableInvoker);}}node._onPostActivated(true);}
zIndex = _localZOrder >> 16_localZOrder = (_localZOrder & 0x0000ffff) | (value << 16)
activateComp: function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) {if (!cc.isValid(comp, true)) {// destroyed before activatingreturn;}if (!(comp._objFlags & IsPreloadStarted)) {comp._objFlags |= IsPreloadStarted;if (comp.__preload) {if (preloadInvoker) {preloadInvoker.add(comp);} else {comp.__preload();}}}if (!(comp._objFlags & IsOnLoadStarted)) {comp._objFlags |= IsOnLoadStarted;if (comp.onLoad) {if (onLoadInvoker) {onLoadInvoker.add(comp);} else {comp.onLoad();comp._objFlags |= IsOnLoadCalled;}} else {comp._objFlags |= IsOnLoadCalled;}}if (comp._enabled) {var deactivatedOnLoading = !comp.node._activeInHierarchy;if (deactivatedOnLoading) {return;}// 启用组件cc.director._compScheduler.enableComp(comp, onEnableInvoker);}}

enabled: {get () {return this._enabled;},set (value) {if (this._enabled !== value) {this._enabled = value;if (this.node._activeInHierarchy) {var compScheduler = cc.director._compScheduler;if (value) {// 启动该组件compScheduler.enableComp(this);} else {// 禁用该组件compScheduler.disableComp(this);}}}},visible: false,animatable: true}
enableComp: function (comp, invoker) {if (!(comp._objFlags & IsOnEnableCalled)) {if (comp.onEnable) {if (invoker) {invoker.add(comp);return;} else {comp.onEnable();var deactivatedDuringOnEnable = !comp.node._activeInHierarchy;if (deactivatedDuringOnEnable) {return;}}}this._onEnabled(comp);}}
_onEnabled (comp) {cc.director.getScheduler().resumeTarget(comp);comp._objFlags |= IsOnEnableCalled;// scheduleif (this._updating) {// 如果在当前帧内激活该组件,则会被放入到延时队列中this._deferredComps.push(comp);} else {this._scheduleImmediate(comp);}
lateUpdatePhase (dt) {this.lateUpdateInvoker.invoke(dt);// End of this framethis._updating = false;this._startForNewComps();}
if (!(comp._objFlags & IsPreloadStarted)) {comp._objFlags |= IsPreloadStarted;xxx}if (!(comp._objFlags & IsOnLoadStarted)) {comp._objFlags |= IsOnLoadStarted;xxx}
if (comp._enabled) {xxx}
3start update lateUpdate

mainLoop: function (now) {if (this._purgeDirectorInNextLoop) {this._purgeDirectorInNextLoop = false;this.purgeDirector();} else {// calculate "global" dtthis.calculateDeltaTime(now);// Updateif (!this._paused) {// before updatethis.emit(cc.Director.EVENT_BEFORE_UPDATE);// Call start for new added componentsthis._compScheduler.startPhase();// Update for componentsthis._compScheduler.updatePhase(this._deltaTime);// Engine update with schedulerthis._scheduler.update(this._deltaTime);// Late update for componentsthis._compScheduler.lateUpdatePhase(this._deltaTime);// User can use this event to do things after updatethis.emit(cc.Director.EVENT_AFTER_UPDATE);// Destroy entities that have been removed recentlyObj._deferredDestroy();}// Renderthis.emit(cc.Director.EVENT_BEFORE_DRAW);renderer.render(this._scene, this._deltaTime);// After drawthis.emit(cc.Director.EVENT_AFTER_DRAW);eventManager.frameUpdateListeners();this._totalFrames++;}}
4onDisable onDestroy

_deactivateNodeRecursively (node) {// 设置标志位node._objFlags |= Deactivating;node._activeInHierarchy = false;// 禁用该节点所有组件var originCount = node._components.length;for (let c = 0; c < originCount; ++c) {let component = node._components[c];if (component._enabled) {cc.director._compScheduler.disableComp(component);if (node._activeInHierarchy) {// reactivated from rootnode._objFlags &= ~Deactivating;return;}}}// 递归调用for (let i = 0, len = node._children.length; i < len; ++i) {let child = node._children[i];if (child._activeInHierarchy) {this._deactivateNodeRecursively(child);if (node._activeInHierarchy) {// reactivated from rootnode._objFlags &= ~Deactivating;return;}}}node._onPostActivated(false);node._objFlags &= ~Deactivating;}

disableComp: : function (comp) {if (comp._objFlags & IsOnEnableCalled) {if (comp.onDisable) {comp.onDisable();}this._onDisabled(comp);}}
destroy () {if (cc.Object.prototype.destroy.call(this)) {this.active = false;}}
prototype.destroy = function () {if (this._objFlags & Destroyed) {cc.warnID(5000);return false;}if (this._objFlags & ToDestroy) {return false;}// 设置标志位this._objFlags |= ToDestroy;// 放入待销毁队列,在当帧结束时统一回收组件objectsToDestroy.push(this);return true;};
destroy () {if (CC_EDITOR) {var depend = this.node._getDependComponent(this);if (depend) {return cc.errorID(3626,cc.js.getClassName(this), cc.js.getClassName(depend));}}if (this._super()) {if (this._enabled && this.node._activeInHierarchy) {cc.director._compScheduler.disableComp(this);}}}

function deferredDestroy () {var deleteCount = objectsToDestroy.length;for (var i = 0; i < deleteCount; ++i) {var obj = objectsToDestroy[i];if (!(obj._objFlags & Destroyed)) {// 立即销毁obj._destroyImmediate();}}// if we called b.destory() in a.onDestroy(), objectsToDestroy will be resized,// but we only destroy the objects which called destory in this frame.if (deleteCount === objectsToDestroy.length) {objectsToDestroy.length = 0;} else {objectsToDestroy.splice(0, deleteCount);}if (CC_EDITOR) {deferredDestroyTimer = null;}}
生命周期回调:



评论
