作者: colinsusie 奎特尔星球 前天
前言
Creator 2.x出来有一段时间了,在原生应用上仍然不能让人满意,许多小伙伴花了大量精力把项目升级到2.x,结果发现性能内存大打折扣。
官方也意识这个问题,他们正组织核心人马,在对原生框架进行各种优化,包括Spine,Dragonbones,压缩纹理,文字优化等等,相信在不久的将来可以见到一些成效。
不过如果项目急着要上线,现在可能来不及了,并且优化的成果如何,也要实际放出来时测试过才能知道。在这种情况下,比较可行的方法是先用1.x发布你的应用,但在代码上作一些兼容性处理,确保到时升级时尽量平滑。甚至在最坏情况要回退,也少一些麻烦。
这篇文章试图将1.9和2.x的差异列举出来,并且告诉你如何写出在两个版本都可以运行的代码。1.10我们没有用过,使用1.10的小伙伴只能自行研究。
先定义版本常量
//如果是1.x的项目定义为true,如果是2.x的项目定义为false
window.CC_1X = true
ZOrder的差异
1.9可以用node.setLocalZOrder
或node.zIndex
,2.x去掉了setLocalZOrder
函数,要兼容的话统一使用node.zIndex
。
setCascadeOpacityEnabled废除
2.x去掉了node.setCascadeOpacityEnabled
,1.9要兼容的话就不能使用。另外cc.Node上还有多个API被废除,详见Creator API文档,链接:https://docs.cocos.com/creator/api/zh/。
播放声音的差异
- 1.9的例子:
let sId = cc.audioEngine.play(cc.url.raw("resources/sound/test.mp3")), loop, volume);
- 2.x的例子:
cc.loader.loadRes("sound/test", cc.AudioClip, function (err, clip) {
if (err) {console.error(err); return;}
let sId = cc.audioEngine.play(clip, !!loop, volume);
});
- 兼容的做法是写一个包装函数:
playSound = function (name, loop, volume=1, cb) {
if (CC_1X) {
let sId = cc.audioEngine.play(cc.url.raw("resources/sound/"+name+".mp3", !!loop, volume);
if (cb) {
cb(sId);
}
} else {
cc.loader.loadRes("sound/"+name, cc.AudioClip, function (err, clip) {
if (err) { console.error(err); return;}
let sId = cc.audioEngine.play(clip, !!loop, volume);
if (cb) {
cb(sId);
}
});
}
};
自定义事件的差异
- 1.9的事件
// message 会被保存在回调函数的 event 参数的 detail 属性上
eventTarget.emit(type, message);
eventTarget.on(type, function (event) {
// 通过 event.detail 获取message
});
- 2.x的事件
// emit 时可以传递至多五个额外参数,都会被扁平的直接传递给回调函数
eventTarget.emit(type, message, target);
eventTarget.on(type, function (message, target) {
// 直接通过回调参数来获取 emit 时传递的事件参数
});
- 兼容的做法是确保参数只传一个,然后在事件处理是这样判断:
eventTarget.on(type, function (event) {
let msg = event.detail ? event.detail : event;
// 这样就能兼容1.9和2.x的事件机制
});
- 由于自定义事件的变化,导致按钮,动画组件等事件也有相应的变化,兼容的做法如下:
// 按钮的
button.node.on("click", this.onClick, this);
onClick(event) {
let button = event.detail ? event.detail : event;
}
// 动画的
anim.on("finished", this.onFinished, this);
onFinished(event, target) {
var aniState = target ? target : event.target;
}
一些API的变化:
- radiansToDegrees
if (CC_1X) {
return cc.radiansToDegrees(dirRad);
} else {
return cc.misc.radiansToDegrees(dirRad);
}
- cc.KEY
if (CC_1X) {
cc.macro.KEY = cc.KEY;
}
- setKeepScreenOn
if (CC_1X) {
cc.Device.setKeepScreenOn(true);
} else {
jsb.Device.setKeepScreenOn(true);
}
- 其他API不同,通过查询文档,然后用上面的方式写一个包装函数。
prefab的差异
我们当时将项目从2.0.5回退到1.9的时候,发现修改代码还不能成功,有些组件序列化格式的变化,导致用1.9打开会失败。
所以这里也将一些不兼容的地方列出来,方便有像我们一样想回退的小伙伴参考:
-
RichText:如果在2.0中设置了字符串,1.9打不开,解决办法是先在2.0编辑器中,将RichText的文本清空,1.9编辑器就可以正常打开了。
-
ScaleX和ScaleY属性如果不是1,回退到1.9会恢复成1。这也是因为格式不一致导致1.9没法解析出来。似乎没有好的办法,只能手动一个个修正过来。
-
EditBox 2.0多出几个子结点,要回到1.9只能手动删掉了,请看下图:
-
TTF字体:当字体文件体积大于10M时,2.0会加载失败,这应该属于引擎的BUG,期待后面修复。
meta文件的修改
- .meta文件的版本号有变化,在2.x中有些是2.0.0的,如果想回退,可以用批处理替换回1.0.1。
其它差异
-
2.x资源不存在直接报错,在运行时,1.x时资源不存在时只是做警告提示,2.x资源不存在直接报错。
-
2.x构建资源全部以UUID命名:如果要在2.x上做热更新,需要建立Assets资源与构建资源的对应关系,相比1.x要复杂一些了。
-
rect.contains废弃使用cc.rectContainsPoint代替
- cc.pXXX系列函数被废弃,使用cc.Vec2成员函数
cc.pAdd需改为p.add,cc.pMult改为p.mul
两个点的距离计算cc.pDistance改为p1.sub(p2).mag()。
###「奎特尔星球」快突破900人了,在这里真诚邀请大家前来投稿,分享你的经验,在游戏开发的道路上我们一起结伴砥砺前行!