最全的Creator遊戲優化方案(一)

今天下午閒下來也來寫寫creator中的優化方案。歡迎各位拍磚,過程中會使用到一些別人的圖片還請見諒!


1.加載速度優化

1.避免使用單像素的大圖,儘量使用9宮方式進行拉昇。

在我們加載的時候降低遊戲資源,加載小資源紋理自然就會加快了速度。而卻也減小了包體。


2.對於一些想降低drawcall數使用很多相同圖片,但是隻是顏色不同的圖片來說,這點需要大家自行取捨。

3.將圖片進行模塊合批處理


這樣做有以下好處:

 

1. 提高了加載的速度(避免了來回打開/關閉不同圖集所消耗的時間)
2. 降低了drawcall(所有的圖都在一張圖中,gl接口只會繪製被調用一次,這樣一來就大大降低了drawcall,比如需要10drawcall的資源現在只用1次就可以了)
3. 降低包文件的體積(將多張圖片放在一起,一般會有一定程度上的縮減)

同樣這樣做可以將一些通用資源統一加載到內存中常駐,這樣就會避免了頻繁的加載與釋放所帶來的不必要的開銷。
4.圖片資源壓縮


對於圖片上的壓縮想必大家會有很多的方法,這一塊呢其實對其加載速度上的影響不是很大,畢竟人家cpu的速度還是很快的,但是壓縮還是很有必要的同樣的圖片大小不一樣,證明包含的數據信息量不同,那麼你想一下是大點好還是小點好呢。
先來看一張圖:

比如RGBA8888這種pixelformat,它意味着rgba每一位佔用8個bit,這樣每個像素佔用4個字節,因此這個壓縮模式對於圖片可以最大限度的保真,但壓縮比方面沒有其他的大。

在和大家提一下,圖片的體積並不是意味着就是內存中的體積,換算方式是這樣的

長*寬*4 = 內存體積
比如一張600k大小的1024*1024的圖片,在內存中的佔用大小爲1024*1024*4 = 4M。

這裏推薦兩款壓縮的工具:


1.TinyPNG,https://tinypng.com/一個在線壓縮圖片的網站,我稱他爲‘熊貓壓縮’
2.另一個是[pngquant](https://pngquant.org/)的命令行壓縮圖片,你可以很好的集成到打包工具中使用。

對於不同格式的圖片資源不同平臺的機器支持的也不近相同


1.ios中支持比較好的就是使用PVR格式的資源,因爲他可以直接被PowerVR顯卡使用,這樣就省下了不少cpu上傳gpu的時間
2.android中支持ETC格式的資源比較好,而ETC的話,ETC1只能在android上使用。ETC2可以在目前的iOS上和android上同時使用,不過太低端的機子就不行了。

5.預製體的優化

預製體的耗時一般會出現在兩個地點,1.在load加載時候,2.在實例化的時候

我們先來看一張creator預製體的加載圖:
1.合理拆分預製體

將衆多的組件拆分爲多個預製體,這樣可以有效的降低節點的複雜度,加快還原節點的速度。(那麼有的人會說了,那打開的文件次數不就多了加大了io的消耗,哎,你要是能跟得上io的速度,全當我沒說, 對於這點我們總是要捨棄一方面的,二者不可兼得)


2.延遲加載資源
creator中也爲我們提供了加載方式的選擇:延時加載資源

勾選這個選項可以減少prefab的加載耗時,但首次顯示的耗時會增加。

這是由於勾選後,prefab所引用的資源,像圖片、音效這些,不會在load時加載,而是會在prefab第一次顯示的時候再進行資源的加載,根據具體情況選擇使用。

3.勾選優化策略
對於優化策略,creator也給出了方案,1.優化單次渲染2.優化多次渲染
單次渲染優化:
這個選項是,prefab加載後會跳過預處理的步驟,這樣在加載時的耗時會減少很多,但實例化時的耗時會增加。例如一些固定UI界面,由於方便加載場景或者時進行功能劃分,通常會做成prefab,這種prefab只會加載一次的,就可以選擇這個選項,提升加載的性能。
多次渲染優化:
這個選項是,Prefab加載後會進行一個預處理的操作,這個預處理其實就是動態生成一些prefab的實例化代碼,並把這些代碼交給jit去進行優化。這樣在實例化時的耗時將會大大減少,相應的,在load時的耗時會有所增加。這是必然的。

6.場景優化


1.合理使用預製體佈置界面,分批異步加載,對於界面首次顯示不需要的界面可以通過動態添加的方式加入界面。
2.儘量少使用spine動畫區佈置主界面,有可能會導致內存大幅度上升,出現卡頓。
3.選用場景的延時加載資源的方式,避免同一時間加載大量的預製體。
4.避免同一時間實例化大量對象,避免內存的突然飆升。推薦使用async異步初始化方式,借用第三方庫async

     async.eachLimit(array,  100,  (index,cb)  =>  {
            var node = new cc.instantiate(‘自己的預製體’);
           //其他操作
        });

 

2.渲染優化


對於渲染的優化主要目的就是降低Drawcall
draw call是openGL的描繪次數
一個簡單的openGL的繪圖次序是:設置顏色→繪圖方式→頂點座標→繪製→結束。
一般情況下一張圖片都是繪製一次,也就是drawcall+1。

1.通常我們選擇自動圖集批處理。

那在實際的項目過程中,既然已經有了自動圖集批處理的機制,爲何我們的draw call還居高不下?
這是因爲並不是所有的紋理都可以放到自動圖集批處理中。
使用自動圖集批處理有幾個限制:
1、單圖尺寸小於512*512並且大於88*88
2、渲染buffer必須爲MeshBuffer類型的資源才能批處理(引擎中renderComponent源碼,像bmfont label和sprite都是MeshBuffer,所以它們可以進入到批處理中。而像9ScaleSprite,Spine這些所使用的爲QuadBuffer,因此沒辦法進行批處理)
3、對節點部分特殊的操作不能進入批處理(比如Mask,Color)

給大家一個表僅供參考



       creator 2.x(2.0~2.0.6)的版本中,支持Bmfont Label和Sprite進入批處理,其他的節點或者操作會打斷批處理。這裏所說的Color和Opacity是指node節點上的color屬性或者是opacity屬性不相同的話,就算使用同一張圖片資源,也會打斷批處理。
       creator 2.1版本和2.0.7(公測版)中,Bmfont,Sprite,9ScaleSprite,Color,Opacity都會進行自動批處理。


2.使用Camera和RenderTexture降低drawcall
對於這樣的預製體我們會如何處理呢?

代碼:

 

cc.Class({
    extends: cc.Component,

    properties: {
        camera : cc.Camera,
        layout : cc.Node
    },


    start () {
        let renderTexture = new cc.RenderTexture();
        let gl = cc.game._renderContext;
        let width = 100;
        let height = 100;
        renderTexture.initWithSize(width, height, gl.STENCIL_INDEX8);
        this.camera.targetTexture = renderTexture;
        this.camera.render();
        for (let i = 0; i < 100; i++) {
            var node = new cc.Node();
            node.addComponent(cc.Sprite);
            node.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(renderTexture);
            node.parent = this.layout;
        }
    },
});


通過上述方法可以將所有節點顯示都繪製在同一renderTexture中,將drawcall大幅度降下來。不過此方法限制也很大。適用於刷新率不高,或者刷新情況比較固定的顯示。
(未完待續)
留下個人博客以供學習:taoqy666.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章