1. 程式人生 > >cocos creator微信小遊戲優化之路(一)

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