对象使用前要判断空,网页遇到空对象的执行,可能可以忽略错误继续执行下去,但编译成 Android 后,空必奔,所以前期开发要养成判空的好习惯,不够后面改起来就呵呵了。
在 onLoad、onEnable 和 start 方法里用代码方式生成节点时,如果该节点要使用其他节点的参数辅助生成时可能会出问题,因为这两个方法执行时,节点并没有渲染出来,一些基于屏幕的属性没有最终确定(比如基于世界节点的 position),这时候代码生成的节点基于这些属性去设置,就会出现问题,解决的方法是延迟一帧去做操作。这种情况也适用于,如果要对用代码添加的节点做类似于 position 这样的动画时,也会报找不到 _axxxx 的错误。
this.scheduleOnce(() => { // 回调 } )
调度一个只运行一次的回调函数,可以指定 0 让回调函数在下一帧立即执行或者在一定的延时之后执行:
/**
!#en Schedules a callback function that runs only once, with a delay of 0 or larger.
!#zh 调度一个只运行一次的回调函数,可以指定 0 让回调函数在下一帧立即执行或者在一定的延时之后执行。
@param callback A function wrapped as a selector
@param delay The amount of time that the first tick will wait before execution. Unit: s
*/
scheduleOnce(callback: Function, delay?: number): void;
然后要记住一点,如果一个行为是异步的,那么,这个方法要作用于异步回调之后,操作相应属性时,千万不能贪方便,直接加在行为上。之前就遇到过加在一个异步行为上,然后调起其他 app 页面,然后异步在没有回来之前回调了,这时还没有渲染,位置属性是没有的,回到 Cocos 页才开始渲染,然后位置不是预想的结果,最后搞了好久才发现这个问题。
scheduleOnce 算是神器来着,如果在跳到其它 app 后回来时要做某些事情,然后跳回来没有回调,这种情况,可以在离开本 app 前,scheduleOnce 一个任务,需要的话可以加一下延迟,然后,跳转后只要重新打开本 app,都会调用 scheduleOnce 指定的任务。
// 该方式在某些手机系统会报错
xxxString.includes('xxx')
// 采用该方式替代上面的方式
xxxString.indexOf('xxx') >= 0
加载一个预制资源,在加载还没有完成时,就跳到了其他 Scene,这时预制资源加载完成回调,在预制资源中设置 parent 时,如果采用如下方式设置,那么,这时的 parent 就不是原先预想的,而是刚打开的 Scene:
this.node.parent = cc.director.getScene();
parent 不是预想的,那么,如果在预制资源中通过下面的方式去获取目标节点,就会报错:
let targetNode = cc.find('Canvas/nodeParent/targetNode');
let nodeParent = targetNode.parent;
项目编译部署后,在相应 Scene 中,界面只有初始化的 UI,各种数据加载和交互都无效,不管点击哪个节点(该节点有点击的交互逻辑)都会报这个错误,也不指明报错位置,找了很久都没找出来,而且在 CocosCreater 中通过浏览器 debug 不会报错。只能形而上一回,把之前写的代码重新写一遍,还是一直解决不了,最后只能从 getComponent 入手,新写的代码中只用到一处 getComponent :
onClickBtn() {
this.share(() => {
this.tipNode.getComponent('haha').share(
() => {
this.close();
}
);
});
},
share(callBack) {
... ...
utils.bind(() => {
utils.userInfo(() => {
callBack && callBack();
})
}, () => {
this.close();
});
... ...
},
节点一定是挂载了,那就猜测是 this 作用域问题,毕竟这货经常惹事,一改,呵呵,果然是:
onClickBtn() {
let that = this;
this.share(() => {
that.tipNode.getComponent('haha').share(
() => {
that.close();
}
);
});
},
以后遇到要把回调函数传入另一个 js 的情况,一定要用 let that = this; 代替 this 的直接引用 !!!
然后,又遇到会有这个问题的另一种情况:如果一个 node 挂载了 Button,并且 Click Event 改成大于0,但是没有方法挂载上去,点击的时候也会报这个错误。