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