标准周期
http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
creator提供了7种生命周期函数,分别是:onLoad,start,update,lateUpdate,onDestroy,onEnable,onDisable。
其中:onDestroy,onEnable,onDisable为触发式调用,可以参考官方文档,此处不说明。
另外4种的调用顺序是onLoad -> start -> update -> lateUpdate。
在标准周期中插入方法
结论:onload -> test-function -> start -> update = > lateupdate
例子:有1个prefab和挂载在prefab上的脚本test,1个主脚本
// test.tsconst { ccclass, property } = cc._decorator;@ccclassexport class test extends cc.Component {onLoad() {cc.log("onload")}start() {cc.log("start")}flag_update = trueupdate() {if (this.flag_update) {this.flag_update = falsecc.log("update")}}flag_late_update = truelateUpdate() {if (this.flag_late_update) {this.flag_late_update = falsecc.log("lateupdate")}}test() {cc.log("test-function")}}
// 主脚本******onLoad() {this.create_some_node()}@property(cc.Prefab)some_prefab: cc.Prefab = nullcreate_some_node() {let n = cc.instantiate(this.some_prefab)n.parent = this.noden.getComponent(test).test()}******
scheduleOnce()在update()之前还是之后?
结论:update -> scheduleOnce
// 修改脚本 test.ts******onLoad() {this.scheduleOnce(() => {cc.log("onload")}, 0)}start() {this.scheduleOnce(() => {cc.log("start")}, 0)}******
原理浅析:帧
- 游戏内所有的逻辑以帧为基础。
- 引擎可以做到渲染帧、逻辑帧、物理帧等分离。cocos-creator中渲染帧和逻辑帧未分离。
// 将test.ts改回去,无schedule
// 修改主脚本,以3帧为例子******onLoad() {// this.create_some_node()}count = 0update() {if (this.count < 3) {cc.log("update:", this.count)for (let i = 0; i < 1000; i += 1) {cc.log(1) // 本项目是为了阻塞帧的执行}if (this.count === 1) {this.create_some_node()}this.count += 1}}******
执行结果为:
可以从结果看出,除了循环会阻碍帧的进程以外,子函数create_some_node也会阻碍帧的进程,并且在此帧内会执行到子脚本的start方法。
优化方向1:减少单帧内的计算,放到多帧去执行
这点的逻辑很容易理解,即将一些无关的计算从单帧放到多帧中去执行。
creator中的api:schedule()中参数interval=0是为间隔帧执行,或者传入时间也可以了。
(错误的)优化方向2:异步化
由于js单线程的原因,即使是异步的promise也会一定程度上的阻塞执行。
在creator中则体现在:在某一帧中使用的promise,一定会在当前帧中执行完毕。
// 清理主脚本,仅创建,无其他调用或者输出// 修改test.ts******onLoad() {cc.log("onload")}start() {cc.log("start")}count = 0update() {if (this.count < 5) {cc.log("update", this.count)if (this.count === 0) {this.test()}this.count += 1}}test() {Promise.resolve().then(() => {for (let i = 0; i < 1000; i += 1) {cc.log(1)}})cc.log("test-function")}******
执行结果为:
可以看到,1000次输出被卡在第1帧中了。
