Unity3d優化之路

Unity3d優化之路.U3D的架構部分已經講了很多了,這裏我想講講對於U3D優化的親身體驗。

優化之路分三塊:

一.渲染級別。

GUI部分:我使用的是NGUI,它對動態移動、旋轉、縮放GUI支持的是比較差的,所以我儘量不要把過多的移動旋轉縮放的部分寫在GUI中,但很多情況下是避免不了的,比如:大量的傷害數字,物品掉落,圖標的移動和旋轉等,爲了不讓GUI去控制這些渲染物體,一小部分我使用3D面片代替,而大部分使用程序去生成面片渲染脫離了GUI的控制。另外在那些靜態的GUI中,我使用了靜態物體優化的屬性,加上排除不必要的GUI設置,使得GUI部分效率足夠高。

3D部分:特效是對畫面效果最最有影響的部分,我儘量不使用粒子或者將粒子的數量減少到最小。儘量減少燈光的使用,而使用烘培後的圖來代替。剔除那些不需要顯示的模型。

2D部分:特效不放在GUI內,而是把特效放在非GUI的另一個攝像頭內代替。所以,最終攝像頭會有多各,總共疊層是這樣的:top:gui_effect_camera , middle:gui_camera , bottom:3d_camera;

二.減少佔用空間大小。

1.我使用的是動態資源的加載方式WWW方式。所以在導出資源時我使用BuildAssetBundleOptions.DisableWriteTypeTree 的打包方式,減少包的大小。

因爲WWW緩存方式在下載後解壓後還是會增大空間佔用量,所以我使用StreamAssets這個在Unity3D裏固定文件夾,把WWW資源放在那裏,在遊戲開始後進行緩衝讀取,這樣既減少了空間佔用量,也可以進行異步的讀取資源方式,唯一的缺點是但凡更改資源就需要玩家下載新的遊戲包。對於兩種方式的WWW資源加載,在具體項目當中可以共同使用,一部分使用網絡加載,一部分使用本地StreamAssets加載。

2.對每張Texture,都設置對圖片進行壓縮。

3.讓美術減少模型面片數,並在fbx模型設置中,設置對模型進行壓縮

3.讓美術減少動畫幀數,並在動畫設置中,設置對動畫進行壓縮

4.不使用System,System.Xml以及其他系統自帶的DLL,他會多出幾兆空間,而用開源的源碼代替。

三.內存

1.最基本的就是對需要的資源進行加載,使用完畢後,釋放。

2.GUI部分在GUIManager管理類中增加 對GUI進行定時檢查的部分,對不展示的GUI資源進行釋放。

3.因爲有些時候一次性加載的資源過多,內存一下子會膨脹,IO過慢導致奔潰,所以我選擇資源異步加載。使得加載這麼多資源不那麼可怕,並且平滑。

4.內存釋放:這裏有個重點,我重點測試了一下內存釋放的忽視點。在我們利用ngui,或者2dtoolkit進行gui編程時,在釋放其gui節點時通常會忘記將gui引用置爲null,這就導致了內存泄漏。一些不再使用的貼圖或者實例數據仍然繼續存留在內存中。對於是否有需要將這些gui變量置爲null的說法,我還做了一個實驗。

首先將屏幕置空,沒有任何多餘內存,再將gui展示,接着隱藏gui銷燬gameobject,先將所有引用變量置爲null,然後再展示,再銷燬,這次銷燬,不將變量置爲null。得出得內存結論就是,不將gui組件變量置爲null的,貼圖內存還會滯留。如下圖:


測試代碼如下:

    using UnityEngine;
    using System.Collections;
    public class testgui
    {
        private tk2dSprite tex;
        private GameObject root;
        private tk2dSprite tex1;
        private GameObject root1;
        private tk2dSprite tex2;
        private GameObject root2;
        public void show()
        {
            root =  GameObject.Instantiate( Resources.Load(“GameObject”) ) as GameObject;
            root.transform.parent = GameObject.Find(“ROOT/MIDDLE_CENTER”).transform;
            tex = root.GetComponent<tk2dSprite>();
            root1 =  GameObject.Instantiate( Resources.Load(“GameObject1″) ) as GameObject;
            root1.transform.parent = GameObject.Find(“ROOT/MIDDLE_CENTER”).transform;
            tex1 = root1.GetComponent<tk2dSprite>();
            root2 =  GameObject.Instantiate( Resources.Load(“GameObject2″) ) as GameObject;
            root2.transform.parent = GameObject.Find(“ROOT/MIDDLE_CENTER”).transform;
            tex2 = root2.GetComponent<tk2dSprite>();
        }
        public void hiden1()
        {
            GameObject.Destroy(root);
            GameObject.Destroy(root1);
            GameObject.Destroy(root2);
            Resources.UnloadUnusedAssets();
        }
        public void hiden()
        {
            GameObject.Destroy(root);
            GameObject.Destroy(root1);
            GameObject.Destroy(root2);
            root = null;
            root1 = null;
            root2 = null;
            tex = null;
            tex1 = null;
            tex2 = null;
            Resources.UnloadUnusedAssets();
        }
    }

請看紅框內綠色曲線,第一次是置空的情況,內存立刻銷燬,而第二次是不置空的情況,內存仍然駐留。結論很明顯了,所以,在你編程時,將引用置空是件非常重要的事,這會直接影響到你的內存使用量。這也事c#垃圾回收機制引起的,當實例沒有引用數量時內存纔會被回收,並且徹底銷燬。

 

筆者最後提醒優化無極限,其實都在細節中,能省一點CPU是一點,能省一點內存是一點。你不打敗99.5%的其他人,你就沒有機會功成名就。

轉載請註明出處:http://www.luzexi.com


發佈了54 篇原創文章 · 獲贊 17 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章