cocos creator微信小遊戲優化之路(一)
阿新 • • 發佈:2018-11-25
目前在做一個放置類的微信小遊戲,時間過去了一個多月,大的功能已經很少了,是時候來一波優化了。策劃那邊還是在瀏覽器上檢視遊戲,反映了幾個問題,主要是操作延遲。這個分為幾個方面:
- 網路延遲:包括資源伺服器延遲,小程式的資源大部分都是放在資源伺服器上的,載入這些資源會出現延遲;另外還有遊戲邏輯伺服器的延遲
- 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的效能問題被修復都再沒有玩家向我們投訴這個問題