从官方对creator引擎的产品定位中我们不难得知,cocos Creator是基于组件化脚本化开发,更具体点是基于js的脚本化,组件化开发

我们在组件脚本开发的时候首先注意的必定就是其生命周期了,目前creator提供给我们的生命周期回调函数主要有onLoad,start,update,lateUpdate,onDestroy,onEnable,
onDisable,我
们可以简单描述一下这些回调触发的时机

onLoad回调函数会在节点首次激活时触发,在任何start函数调用前执行

start回调函数会在组件第一次激活前,也就是第一次执行 update 之前触发

update在组件进行更新时执行, 每一帧渲染前更新物体的行为

lateUpdate在所有组件的 update 都执行完之后

onDestroy当组件或者所在节点调用了 destroy()

onEnable当组件的 enabled 属性从 false 变为 true 时,或者所在节点的 active 属性从 false 变为 true 时

onDisable当组件的 enabled 属性从 true 变为 false 时,或者所在节点的 active 属性从 true 变为 false 时

需要注意的是我们的初始化通常在start函数而不再onload函数中的原因:onload是场景加载完成执行,start是当前组件开始运行时执行。假设每个组件的初始化都在onload完成,当一个节点的初始化依赖于另一个节点的属性时,就有可能出现异常,因为有可能另一个节点还没有执行onload。而start是所有组件的onload都执行完了才会执行,这时无论获取哪个节点的属性都不会有问题,因为那个节点已经初始化完成了。所以节点的UI初始化最好放在start中。
知道了这些,我们在做开发的时候就会有了一个大概的流程概念,在合适的时机处理自己想要的操作,晓得这些回调函数是在什么时候触发的了,天生丽质的宝宝们都会追根到底,那为啥你说他那个时候触发他就那个时候触发啊,ok,接下来,我们就详细的解析一

从cocos官方文档中我们可得知 Cocos Creator 的引擎部分包括 JavaScript、Cocos2d-x-lite 和 adapter 三个部分,引擎代码大致分为js和原生的c++ 两种类型,分别在引擎安装目录resources/engine 和 resources/cocos2d-x下。

咱们就从web平台来分析吧,主要看的就是engine\cocos2d 目录下的源码。

我们常说打出来的空包就要1-2兆,其实一部分原因就是需要把这些模块依赖给打包进去…em,有点跑题了

creator对应打出来的web包,对应的cocos2d-js-min.js文件所有模块的源码。整个文件的执行周期,main.js是creator引擎的入口,他会在cocos2d-js-min.js加载完之后开始运行游戏
如果简化main.js 的内容大概是这样的

//main.js
window.boot =function() {//loading页面相关function setLoadingDisplay (){...};//主要是对Web和native游戏场景尺寸或者朝向的处理以及加载scene相关var onStart = function(){//以及调用上方的setLoadingDisplay 函数设置loading相关};//当前的游戏配置var option = function(){...};//s获取_CCSettings变量进行处理cc.AssetLibrary.init({...});//cc.game包含游戏主体信息并负责驱动游戏的游戏对象,传入配置参数//运行游戏,并且指定引擎配置和 onStart 的回调cc.game.run(option, onStart);
}
//调用
window.boot();

这里我们可以看到,如果简化来看,boot中就是声明和设置一些配置信息或者一些出来,以传参的形式传到run函数中
在run方法中,会根据配置进行引擎的准备工作,简单流程如下

//game
var game = {//运行游戏,并且指定引擎配置和 onStart 的回调。run(config, onStart){// 注册配置数据      this._initConfig(config);this.onStart = onStart;// 开始准备      this.prepare(game.onStart && game.onStart.bind(game));},//准备引擎prepare(cb){//如果已准备则执行回调返回if (this._prepared){          if (cb) cb();       return;    }let jsList = this.config.jsList;if (jsList && jsList.length > 0){var self = this;  // 加载准备脚本之后调用         cc.loader.load(jsList, function (err) {                if (err) throw new Error(JSON.stringify(err)); self._prepareFinished(cb);            });}else{this._prepareFinished(cb);}},prepareFinished(cb){/*//初始化引擎,设置帧循环事件等等方法       this._initEngine();                this._setAnimFrame();.....↑↑↑↑↑↑↑↑至此已经完成了引擎的准备工作*///开始运行主循环this._runMainLoop();//派发EVENT_GAME_INITED事件this.emit(this.EVENT_GAME_INITED);},
}

由上可知,运行的顺序在cocos2d-js-min.js加载完之后执行main.js的windows.boot,传入配置调cc.game.run函数,然后注册配置信息 开始准备prepare,加载脚本初始化引擎,设置帧事件,调用_runMainLoop开始运行主循环。
ok,到运行主循环这里就开始接触到我们要探究的生命周期回调函数了,

//Run game. _runMainLoop: function () {        if (CC_EDITOR) { return;       }        if (!this._prepared) return;var self = this, callback, config = self.config,            director = cc.director,            skip = true, frameRate = config.frameRate;// 设置在左下角是否显示fps信息debug.setDisplayStats(config.showFPS);callback = function (now) { // 非暂停状态           if (!self._paused) {//requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘                self._intervalId = window.requestAnimFrame(callback);                if (!CC_JSB && !CC_RUNTIME && frameRate === 30) {    // 每2帧跳1帧执行                if (skip = !skip) {                       return;                    }                }  // 执行下一帧循环             director.mainLoop(now);            }        };self._intervalId = window.requestAnimFrame(callback);        self._paused = false;   },

可以看出,利用 window.requestAnimationFrame 及其回调函数来实现循环,循环里调用的是 director.mainLoop(),

//CCDirector.js
//在初始化时 有sharedInit: function () {        this._compScheduler = new ComponentScheduler();        this._nodeActivator = new NodeActivator();cc.loader.init(this);    },mainLoop (now) {       if (this._purgeDirectorInNextLoop) {        this._purgeDirectorInNextLoop = false;           this.purgeDirector();        } else {            // 计算全局的时间增量,即 dt  this.calculateDeltaTime(now);          if (!this._paused) {//每个帧的开始时所触发的事件                this.emit(cc.Director.EVENT_BEFORE_UPDATE);               // 对最新加入的组件调用 `start` 方法            this._compScheduler.startPhase();               // 调用组件的 `update` 方法                     this._compScheduler.updatePhase(this._deltaTime);               //调用调度器的 `update` 方法  this._scheduler.update(this._deltaTime);                // 调用组件的 `lateUpdate` 方法this._compScheduler.lateUpdatePhase(this._deltaTime);               // 将在引擎和组件 “update” 逻辑之后所触发的事件。              this.emit(cc.Director.EVENT_AFTER_UPDATE);               // 回收内存             Obj._deferredDestroy();           }// 访问渲染场景树之前所触发的事件。            this.emit(cc.Director.EVENT_BEFORE_DRAW);           renderer.render(this._scene, this._deltaTime);// 渲染过程之后所触发的事件            this.emit(cc.Director.EVENT_AFTER_DRAW);eventManager.frameUpdateListeners();            this._totalFrames++;       }   }, 

ok,看到这里我们已经大概很明确这些回调了,接下来我们在深入的看一下ComponentScheduler类和NodeActivator类具体函数的实现,我们以start简化源码为例来看一下

//component-scheduler.js function ctor(){//开始this.startInvoker = new OneOffInvoker(invokeStart);this.updateInvoker = new ReusableInvoker(invokeUpdate);this.lateUpdateInvoker = new ReusableInvoker(invokeLateUpdate);//下一帧组件方法数组this.scheduleInNextFrame = [];// 一次循环中this._updating = false;},var OneOffInvoker = cc.Class({extends: LifeCycleInvoker,//....//....invoke () {...})};var invokeStar =  function (iterator) {var array = iterator.array;for (iterator.i = 0; iterator.i < array.length; ++iterator.i) {let comp = array[iterator.i];//调用组件的 start 方法comp.start();comp._objFlags |= IsStartCalled;}},startPhase () { // 当前帧开始       this._updating = true;if (this.scheduleInNextFrame.length > 0) {            this._deferredSchedule();        }//调用 startInvoker   this.startInvoker.invoke();},

我们可以看到在外部调用startPhase 方法后,他会去判断上个循环是否结束,然后调用this.startInvoke,而他在构造函数中已经实现。update,onenable等生命周期回调方法都在这个脚本中实现,而在NodeActivator类中的activateComp方法的工作就是调用并只调用一次组件的 onLoad 方法。这里就不在描述

好了,至此,已经分析了creator提供给我们的这些生命周期回调方法的实现。如有遗漏或不足,还请多多指教

creator源码分析(生命周期函数回调相关)相关推荐

  1. LIRE原理与源码分析(二)——相关接口

    1. LIRE原理与源码分析(二)-- 代码结构 2. LIRE原理与源码分析(二)-- 相关接口 上一篇文章介绍了LIRE的基本内容和源码的代码结构.本文针对LIRE中主要的三个接口(LireFea ...

  2. Android Binder机制情景源码分析之Binder回调注册和反注册

    我们在日常开发中,经常用到Binder来进行跨进程通信,有个比较常见的场景是向服务端注册Binder回调,比如: IActivityManager中有两个成对的方法,Client端向AMS所在的服务端 ...

  3. motan源码分析五:cluster相关

    上一章我们分析了客户端调用服务端相关的源码,但是到了cluster里面的部分我们就没有分析了,本章将深入分析cluster和它的相关支持类. 1.clustersupport的创建过程,上一章的Ref ...

  4. Linux kernel 3.10内核源码分析--slab原理及相关代码

    1.基本原理 我们知道,Linux保护模式下,采用分页机制,内核中物理内存使用buddy system(伙伴系统)进行管理,管理的内存单元大小为一页,也就是说使用buddy system分配内存最少需 ...

  5. 源码分析工具Joern的相关资料整理

    随着对joern的了解,发现这个工具的潜能挺大的.但实际上手起来还是有点难度.这里列举一些对学习joern有帮助的相关资料博客. joern官方文档:https://docs.joern.io/ jo ...

  6. Vue.js 源码分析(九) 基础篇 生命周期详解

    先来看看官网的介绍: 主要有八个生命周期,分别是: beforeCreate.created.beforeMount.mounted.beforeupdate.updated   .beforeDes ...

  7. 详述 Spring MVC 启动流程及相关源码分析

    文章目录 Web 应用部署初始化过程(Web Application Deployement) Spring MVC 启动过程 Listener 的初始化过程 Filter 的初始化 Servlet ...

  8. Lifecycle 使用与源码分析——彻底搞懂Lifecycle原理

    一.Lifecycle 介绍 Lifecycle是一个生命周期感知组件,一般用来响应Activity.Fragment等组件的生命周期变化,并将变化通知到已注册的观察者.有助于更好地组织代码,让代码逻 ...

  9. Lifecycle 使用与源码分析

    一.Lifecycle 介绍 Lifecycle是一个生命周期感知组件,一般用来响应Activity.Fragment等组件的生命周期变化,并将变化通知到已注册的观察者.有助于更好地组织代码,让代码逻 ...

最新文章

  1. win7安装mysql-5.7.18
  2. Yarn框架和工作流程研究
  3. spring mvc 异步_DeferredResult – Spring MVC中的异步处理
  4. Docker认识基础
  5. 前端学习(2325):angular之数据修改
  6. python库之numpy
  7. poj1236/luogu2746 Network of Schools (tarjan)
  8. idea使用数据库连接工具
  9. 3D控件Aspose.3D 8月新版V17.8发布 | 支持6面多维地图
  10. 地理空间数据免费获取(一)
  11. h3c服务器通过pxe安装系统,h3c服务器设置pxe启动
  12. 【Linux】U盘配合WinPE 安装debian8.6
  13. 干涉光强公式怎么计算_光强及计算
  14. 广东省的身份证号码开头
  15. “九个字、一只手、专有云”,有孚网络的云上之路
  16. potplay如何设置加速不变声
  17. 三年级计算机的组成教学设计,三年级计算机教学设计.docx
  18. 第三章 python基础
  19. idea中使用log4j(打开、关闭日志方法)
  20. 高速PCB基材介绍(铜箔、PP、基板)

热门文章

  1. mysql经典基础语录
  2. 3D游戏建模:这种方法制作枪械硬表面最快,可惜知道的人太少(Zbrush聚光灯)
  3. 中国式家长计算机入门怎么去的,中国式家长新手怎么玩 新手快速入门攻略
  4. 小程序仿微视_微信小程序仿抖音,微视上下滑动整屏切换视频带关注,收藏
  5. 图像处理20-多边形拟合曲线
  6. 程序员面试必备——《Java程序员面试笔试宝典》pdf
  7. 戴尔win10插耳机还外放_联想小新,win10系统,外放声音嘶哑,用耳机正常,现已找到解决办法,希望对面临同样困扰的朋友有所帮助!...
  8. 新倩女服务器维护,2020年12月17日周常维护服务器合并候选名单
  9. 如何设置计划任务程序 每6小时运行一次_如何使win10系统运行的更快?
  10. 你在实施PDM展开图纸明细表时遇到哪些问题(一)?