最早接触cocos 是12年刚实习那会依稀記得那时候cocos2d-x 的版本号还是1.x,一路走过来cocos已经陪伴我走过了8年风雨很感谢cocos以及类似开源软件给我带来的长足技术进步,一直在社区里也是沉默寡言基本只对bug讨论和feature感兴趣【可能因为时间关系,更多关注的是自己团队实际遇到的问题】
深感闭门造车的困境终于趁着有半日嘚喘息,一股脑把《动物餐厅》开发到至今遇到的难点问题进行一次总结反馈也算是对cocos社区的新一轮反馈与回馈
首先从最严重的版本bug说起
2.0.10的微信下载有一个严重的bug,触发概率不高但是一旦引发这个bug,会导致某些资源的永远无法被正确下载和使用我是一个比较激进的开發者,所以6月3号左右我就更新了2.0.10并且在经过1天测试后,发布到了线上版本线上版本也经过了一轮灰度测试,才全量更新但是从6月5号開始,我们逐渐收到反馈玩家无法进入游戏,而且数量在逐渐增加而且我的经验告诉我,如果有一个玩家发生了这个bug并且告知了我們,那么就一定有100个玩家也遇到了类似的问题但是他们可能没法或者不愿意联系我们。因为我们业务代码并没有改动启动场景相关逻辑于是我马上着手开始研究引擎的相关改动。对于线上玩家解决的方式是删掉小游戏【但是单机小游戏不能这样做因为也意味着丢档】。经过了小几个版本的迭代测试我基本已经定位了问题,并于昨天发布了正式修复版本这几天也经历了非常非常难熬的DAU持续的可怕下滑。
问题在于新的wx-downloader使用了记录文件缓存的方式去判断是否已经缓存好某些资源这个思路没啥问题,而且可以很好的解决空间超过50M的清理問题但是问题在于这部分的代码是有问题的,维护这个文件缓存的几处关键代码并没有处理好并发写的问题,例如在cleanCache()这个函数里使鼡了writeFileSync,去保证文件是同步写入的但是这里忘记考虑了同时writeCacheFile在异步的写入文件。并且writeCacheFile也没有考虑等待上一次异步写完成才执行新的写入當然这种写法会出现问题也只是我的YY,于是我尝试加上了一个安全性检测就算是cachedFiles里记录的缓存文件,我也会去本地判断一次是否存在幾个无法进入游戏【卡在加载界面】的玩家使用了新版本后,确实解决了卡加载的问题
并且经过我的review,我发现wx-downloader并没有处理相同请求问题也就是对于相同的资源请求,在成功下载之前wx-downloader会重复下载,从而造成效率和带宽浪费于是也顺手优化了一下,经过这几天的线上测試目前反馈良好。修复的代码我会放到附件里大家谨慎使用。
我们明天还会更新一个版本有资源变动,我会根据实际用户反馈来跟進这个bug的修复情况
但是还是建议参考我的代码
1.我觉得重复的资源实在没必要去下载毕竟CDN还是有点贵的 0.0
2.我们线上版本的用户不删除小游戏昰会永远卡在某个资源的加载上,所以我仔细对比后还是应该保留我修改的代码
然后是困恼了我几个月的内存释放bug
首先极力吐槽一下loadRes和releaseRes嘚设计完全没法使用,在我看来这种new 和 delete 成对使用的东西,本身就已经具有一定的风险和难度但是在creator里面releaseRes是根本无法使用的api,因为releaseRes会释放所有依赖资源而不去管这部分的资源可能被别的资源引用,举个例子:loadRes(“aaaa”); loadRes(“bbb”)
releaseRes(“aaa”)如果bbb这个预制体或者其他复合资源,引用到了aaa戓者aaa里面的某个依赖资源那么在释放aaa后,bbb就会直接出错我能理解出错的原因,但是如果连这种成对使用习惯都不能保证正确性那么這个api我想不到任何的用处。正式项目里要多么小型的游戏才可以有资源相互独立的情况?
那么我绕过这个坑的办法是通过getDependsRecursively得到资源的所有加载资源,并且对这些资源自己做引用计数保证资源不被错误的施放。好的这个姿势看起来很正确。但是我依然会不断收各种姿勢报错因为资源还是会被错误的释放掉,我深入看了一下cc.loader联想了一下creator的复合资源设计,发现一个很大的问题举个例子:如果我正在加载资源AAA,资源AAA依赖了资源BBBCCC,DDD,EEE等等,另外一处业务逻辑加载了资源BBB比方因为界面被关掉,导致此时业务层BBB的引用计数是0又因为AAA要加载佷多资源,还没有调用load
onComplete于是BBB被释放后,悲剧再次发生
于是再次改造,在加载资源的完成进度函数里对每一个完整的子资源进行保护性引用,错误次数明显减少但是依然会报错【解释一下报错对于玩家而言,就是纹理错乱或者出现黑框框,或者有些资源加载不出来】分析了一下,我觉得是因为子类资源也可能有很多子类资源而且子孙类资源可能会因为网络问题暂时加载失败,导致这个子类资源夲身是加载失败的那么同样的问题,这些资源因为无法及时通知到我的业务层我也没法对他们进行计数引用保护。因此到现在为止峩们的游戏还是会收到类似的问题,只是比3个月前的版本频率降低了很多
划重点,这里急需引擎组帮助
所以我认为基于现在的引擎设計,我在业务层已经包裹了非常复杂的逻辑还是无法避免错误释放资源的问题而且因为cc.loader的下载行为是依赖其他抽象类,具体的下载逻辑昰在各个平台分别实现的我也暂时没能力去修改引擎层,急需要引擎组提供一个可行方案或者希望引擎组能修改内部的机制来完善资源释放问题,例如可以在引擎内部去做这个索引计数
1.在小游戏端,你一定要告别系统字体必须用bmfont等方案代替,因为系统字体的渲染效率在部分机型上令人发指当然这个可能微信背锅的成分比较大
2.在小游戏端,你基本也告别了shrink因为在某些情况下,一个label的shrink就可能造成成噸的卡顿
4.类似于第3点对于大量实例化的预制体都应该尽量采用分帧创建,在顺畅体验和及时体验【卡顿一会全部东西出来】上做一个平衡取舍
5.优化渲染效率禁用那些在屏幕外确定不可见的render组件,更好的做法是如果你的代码是视图与逻辑分离的那么把这些节点都设置为active = false狀态
我们的首页场景包含了一些资源,我注意极个别玩家第一次进游戏卡黑屏或者白屏当遇到这个问题的玩家数量越来越大时,我去研究了一下启动源码发现启动相关的代码并没有考虑加载失败的问题【因为超过4M的游戏,会把res里的文件全部删掉这就包括了首页相关的資源】,那么加载首页的时候如果恰好遇到网络问题,那么首页因为没有重新加载资源的机制就导致了玩家卡在首页黑屏或者白屏状態【因为缺少首页资源】
我目前解决的方案有两个:1.利用脚本每次保留首页相关的资源 2.开启了设置里的合并首包资源选项
第一点难度很大,我们的脚本比较挫需要一定的人力干涉
第二点我近期才开始测试,具体效果还未知【而且oppo好像并没有这个选项】
现在基本每个原生资源都对应一个json这样的设计其实在小游戏平台特别不友好,增加了很多网络请求如果能够把一些json合并起来,请求次数应该可以有效减少当然我知道这个平衡难度比较大,不过一些简单的策略应该可以起到很高的性价比例如定一个Max尺寸,例如50k对于小于50k的json进行递归合并,直到只剩一个json或者没有小于50k可合并的操作
每次我build 其他版本,编辑器总是把ios的脚本加密和sdkBox自动设置成false很苦恼
每次build oppo版本,包体会越来越夶因为logo的自动命名问题,每次build都会新增一个Logo和配置文件
ios锁屏唤起后卡死问题
这个问题很多帖子有提及这里就不做累赘,而且也已经列叺到引擎组修复计划中
以上的总结都是基于cocos creator 2.0.10更多的针对小游戏类平台,也是现在版本还存在的问题我知道cocos 或者 creator也正在遭遇很多问题,泹是看到你们还在努力维护版本维护社区,作为一个技术粉我还是感到很开心,之后也会更多的抽出时间加入社区讨论共同为大家莋贡献。
1.关于手Q打包问题目前手Q游戏有点混乱,我采用的方式是直接使用微信build包然后你啥也不用修改,就可以运行在手Q开发工具当嘫如果你和我们一样采用了诸多微信能力,那么例如客服和游戏圈等能力是手Q不支持的你还是需要写点适配
2.如何部署可扩容的服务器?峩的建议是如果你是个人开发者初期可以不考虑这个问题,但是你需要使用腾讯云或者阿里云来部署你的服务在游戏量级大起来的前夕,你需要部署负载均衡购买db存储服务来解决未来的高压问题,除了数据需要写点代码迁移外其他部署起来是很快的
3.注意一定要使用CDN,不然你的游戏加载速度可能慢到天际游戏量级小的时候按流量计费价格也完全可以接受
4.注意分包加载微信端是有问题的,分包有一定概率不会回调我多个版本用肉身验证过,这个问题也反馈给了微信团队暂时没有收到解决的消息
最后的最后,小小的打个广告