Cocos Creator 脚本组件的生与死!
COCOS
共 15738字,需浏览 32分钟
·
2021-05-12 23:38
onLoad
start
update
lateUpdate
onDestroy
onEnable
onDisable
测试脚本
const { ccclass, property } = cc._decorator;
@ccclass
export 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 length
var 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 recursively
for (let i = 0, len = node._children.length; i < len; ++i) {
let child = node._children[i];
// 根据子节点排列顺序设置 _localZOrder
child._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 activating
return;
}
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;
// schedule
if (this._updating) {
// 如果在当前帧内激活该组件,则会被放入到延时队列中
this._deferredComps.push(comp);
} else {
this._scheduleImmediate(comp);
}
lateUpdatePhase (dt) {
this.lateUpdateInvoker.invoke(dt);
// End of this frame
this._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" dt
this.calculateDeltaTime(now);
// Update
if (!this._paused) {
// before update
this.emit(cc.Director.EVENT_BEFORE_UPDATE);
// Call start for new added components
this._compScheduler.startPhase();
// Update for components
this._compScheduler.updatePhase(this._deltaTime);
// Engine update with scheduler
this._scheduler.update(this._deltaTime);
// Late update for components
this._compScheduler.lateUpdatePhase(this._deltaTime);
// User can use this event to do things after update
this.emit(cc.Director.EVENT_AFTER_UPDATE);
// Destroy entities that have been removed recently
Obj._deferredDestroy();
}
// Render
this.emit(cc.Director.EVENT_BEFORE_DRAW);
renderer.render(this._scene, this._deltaTime);
// After draw
this.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 root
node._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 root
node._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;
}
}
生命周期回调:
评论