cocos creator微信小游戏优化之路(一)

目前在做一个放置类的微信小游戏,时间过去了一个多月,大的功能已经很少了,是时候来一波优化了。策划那边还是在浏览器上查看游戏,反映了几个问题,主要是操作延迟。这个分为几个方面:

  • 网络延迟:包括资源服务器延迟,小程序的资源大部分都是放在资源服务器上的,加载这些资源会出现延迟;另外还有游戏逻辑服务器的延迟
  • IO延迟:从手机存储读取文件是很慢的,尤其是一堆文件的时候
  • 渲染延迟:组件太多、太深,渲染压力大
  • 性能问题:复杂的逻辑、计算密集型的任务导致主循环被持续占用,反映出来就是ui响应慢

路要一步一步走,饭要一口一口吃。我们今天就先来聊聊如何解决网络延迟的问题。

预下载所需资源

首先我们要看下,creator在小游戏环境中是如何下载资源的。creator提供了一个wxDownloader对象用来处理远程资源的加载,步骤如下:

  • 1、检查资源是否在小游戏包内
  • 2、不存在则查询本地缓存资源
  • 3、如果没有缓存就从远程服务器下载
  • 4、下载后保存到小游戏应用缓存内供再次访问时使用 具体请看官方文档 官方的实现是将wxDownloader作为加载资源的第一个管道,依旧是按需下载。但是,这样会导致首次访问慢的问题。现在,我们的工作就是将按需下载替换成提前预下载。这里需要在我们的loading页下载所有需要的资源,下载完毕之后再进入游戏。这里有几个问题:
  • 1、如何知道需要预下载的资源 这里我们需要再发布远程资源的时候附带生成一个manifest文件,用于记录该版本所有需要预加载的资源。
  • 2、并发地执行下载,但需要注意的是,同时超过10个网络请求会报错,所以需要限制你的并发数量 具体代码很简单,可以参照官方的wxDownloader的实现。并发那里我自己用promise封装了一下,将所有的处理步骤作流式处理,按照需要建立多个管道。大概是这样的:
preload(items){
    if(!items){
        this._onCompleted();
    }
    // 最后一条不读
    this._totalCount = items.length - 1;
    this._items = items;
    const pipeCount = Math.max(1, Math.min(this._totalCount, this.maxPipe));
    for(let i = 0; i < pipeCount; i++){
        this._nextHandle();
    }
},

_nextHandle(){
    const path = 'res' + this._items[this._processCount];
	// ttf不读
    if (path.substr(-3, 3) === 'ttf') {
        this._addProgress();
    } else {
        this.handle(path);
    }
},

_onCompleted(){
    if(this._completedFlag){
        return;
    }
    this._completedFlag = true;
    console.log('completed state:', this._savedCount, this._processCount, this._totalCount);
    console.log('fail to process:', this._failPathes);
    if(typeof this._onCompleteCallback === 'function'){
        this._onCompleteCallback();
    }
},

_addProgress(){
    this._savedCount++;
    this._process();
    if(this._processCount >= this._totalCount){
        this._onCompleted();
    }
},

_addFail(path){
    this._failPathes.push(path);
    this._process();
    if (this._processCount >= this._totalCount) {
        this._onCompleted();
    }
},

_process(){
    if (this._processCount >= this._totalCount) {
        return;
    }
    console.log('state:', this._savedCount, this._processCount, this._totalCount);
    this.stateLabel.string = this._processCount + '/' + this._totalCount;
    this._processCount++;
    this._nextHandle();
},

handle(path){
    console.log('handle:', path);
    this.existPromise(path).then(()=>{
        console.log(`${path} exist!!`);
    }, ()=>{
        return this.downloadFilePromise(path);
    }).then(()=>{
        this._addProgress();
    }).catch(()=>{
        this._addFail();
    })
},

转圈动画

是的,加一个转圈动画,或者延迟加一个转圈动画对玩家的感受真的不一样。不要笑!!之前做过一个手游项目,由于服务器的问题,导致玩家经常会感知到转圈,客服收到无数投诉,大家拼命催促后端小哥优化性能。这时候我灵机一动,把特定rpc的转圈动画出现延迟了0.5秒,发出热更,结果玩家纷纷发帖表示网络好了(我当时就笑趴在了桌子上),直到几个特定rpc的性能问题被修复都再没有玩家向我们投诉这个问题

TO BE CONTINUE

猜你喜欢

转载自my.oschina.net/u/3905200/blog/1858469