天天看点

编写兼容Creator 1.x和2.x的代码引言先定义版本常量

编写兼容Creator 1.x和2.x的代码引言先定义版本常量

有幸结识到社区中大名顶顶的Colin,Shawn在论坛上第一次看到Colin的团队用Cocos Creator开发的《热血暗黑》时就被深深地震撼到了!更为重要的是,Colin将他的技术心得和宝贵开发经验写成文字,每一篇分享都是满满的干活,而且幸运的是Shawn得到Colin的授权许可,将他的文章散播到奎特尔星球,与你一起欣赏一起成长!

引言

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只能手动删掉了,请看下图:
编写兼容Creator 1.x和2.x的代码引言先定义版本常量
  • 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代替
编写兼容Creator 1.x和2.x的代码引言先定义版本常量
  • cc.pXXX系列函数被废弃,使用cc.Vec2成员函数 cc.pAdd需改为p.add,cc.pMult改为p.mul
编写兼容Creator 1.x和2.x的代码引言先定义版本常量
  • 两个点的距离计算cc.pDistance改为p1.sub(p2).mag()。
编写兼容Creator 1.x和2.x的代码引言先定义版本常量