1. 程式人生 > >Unity 的一些優化總結 (難度3 推薦4)

Unity 的一些優化總結 (難度3 推薦4)

rdo serial 分配內存 down 物理系統 頂點 最大 nbsp ade

原文地址:

http://www.jianshu.com/p/3acee1101fe4

從別的地方看到一些資源使用方面的文章,從中抽取一些細節在這裏總結一下:

Draw Call數量、Triangle數量 和 可見蒙皮網格數量

一般來說,Draw Call 數量、Triangle 數量 和 可見蒙皮網格數量 的推薦值需根據平臺的不同而不同。對於 Mobile 低端移動設備來說,建議 Draw Call 數量的主要範圍在 [0,200] 區間內,Triangle 數量保持在 10萬 以下,可見蒙皮網格數量保持在 50 以下。

Contacts 數量、Rigidbody 數量 和 碰撞體數量

Contacts 數量為碰撞對(Contact Pair)數量。所謂“碰撞對”,是指當前空間中發生碰撞的物體之間的接觸點,每個 “碰撞對” 均連接兩個相互產生碰撞的物體。一般來說,Contacts 數量越大,則表明碰撞物體的數量越多,即物理系統的CPU開銷越大。

Rigidibody數量 和 碰撞體數量, 其標準值需因運行平臺的不同而不同。對於Mobile移動設備來說,建議 Rigidibody數量 控制在 50 以下,碰撞體數量(靜態碰撞體和動態碰撞體) 控制在 100 以下。

貼圖資源

在紋理資源的優化方面,建議盡可能降低其內存上的占用,其主要影響因素包括紋理分辨率、紋理格式、Mipmap等。對於紋理格式,則盡可能采用適合於發布平臺的硬件支持紋理格式,比如對於Android平臺,建議使用ETC1格式,對於iOS平臺,建議使用PVRTC格式,對於PC,建議使用DXT格式等等。

註意:在Android平臺上,ETC1格式不支持半透明紋理,所以半透明紋理可以直接轉換成RGBA16格式進行渲染。當然,更為出色的辦法是,將半透明紋理拆分成兩張紋理,記錄RGB通道信息的RGB24格式紋理和記錄Alpha通道信息的Alpha8格式紋理,然後再分別轉成ETC1格式進行保存。這種方法既可以最大限度地保證渲染質量,又可以極大降低紋理內存的占用。
紋理從RGBA32轉換成RGBA16、ETC1或PVRTC格式時,均會帶來一定程度的質量損失,甚至出現難以接受的 “色階” 效果。究其原因,是因為紋理圖像中的過渡色所致。因此,建議您在顯示效果和性能效率方面進行權衡,盡可能降低過渡色的跨度範圍

“多余” 數據的危害還體現在網格拼合上。Unity 引擎的 Draw Call Batching 功能或您自己調用的 StaticBatchingUtility API 均可以將場景中的網格數據進行拼合,從而形成一個或幾個較大的 VBO(Combined Mesh)。這種做法是渲染優化時的常見方法,主要用於降低渲染模塊的Draw Call數量,從而提升渲染效率。這本身是一個非常棒的功能,但您需要註意的是,網格合並時一定要保證網格數據結構的統一性,否則會大大增加拼合網格(Combined Mesh)的數據量!舉個例子,當拼合100個網格模型時,如果99個模型網格數據中僅含有Vertex、UV等數據,而僅有1個模型網格數據中含有Vertex、UV、Normal、Color和Tangent數據,則拼合後,拼合網格中的所有頂點均會添加上 Normal、Color 和 Tangent 數據,大量的 “多余” 數據也就由此產生了...

總內存和使用內存

Reserved Total 和 Used Total 為Unity引擎在內存方面的總體分配量和總體使用量。 一般來說,引擎在分配內存時並不是向操作系統 “即拿即用”,而是首先獲取一定量的連續內存,然後供自己內部使用,待空余內存不夠時,引擎才會向系統再次申請一定量的連續內存進行使用。Reserved Total 的內存占用量略大於 Used Total, 且兩者走勢基本一致。

註意:對於絕大多數平臺而言,Reseved Total內存 = Reserved Unity內存 + GFX內存 + FMOD內存 + Mono內存

通過針對大量項目的深度分析,我們發現導致 Reserved Unity 內存分配較大的原因主要有以下幾種:

  1. WebStream內存占用:WebStream為項目通過特定API(WWW、CreateFormMemory等)加載AssetBundle文件所開辟的較大塊內存。主要用於存放AssetBundle的原始數據和解壓後數據。
  2. 序列化信息內存占用:Unity引擎的序列化信息種類繁多,其中最為常見且內存占用較大的為SerializedFile。該序列化信息的內存分配主要為項目通過特定API(WWW.LoadFromCacheOrDownload、CreateFromFile等)加載AssetBundle文件所致。
  3. 資源內存占用:主要包括Mesh、AnimationClip、RenderTexture等資源。在默認情況下,當FBX模型導入時,其 “Read/Write Enable” 選項是默認開啟的,即其Mesh網格數據會在 Reserved Unity 中保留一份,便於項目在運行時對Mesh數據進行實時的編輯和修改。同時,如果研發團隊同樣開啟了紋理資源的 “Read/Write Enable” 選項(默認情況下為關閉),則紋理資源同樣會在 Reserved Unity 中保留一份,進而造成其更大的內存占用。

GFX內存 為底層顯卡驅動所反饋的內存分配量,該內存分配由底層顯卡驅動所控制。一般來說,該部分內存占用主要由渲染相關的資源量所決定,包括紋理資源、Mesh資源、Shader資源以及解析這些資源的相關庫所分配的內存等。

托管堆內存 表示項目運行時代碼分配的托管堆內存分配量。對於使用Mono進行代碼編譯的項目,其托管堆內存主要由Mono分配和管理;對於使用IL2CPP進行代碼編譯的項目,其托管堆內存主要由Unity自身分配和管理。目前,除iOS平臺外,其他平臺的絕大多數項目還在使用Mono來進行代碼編譯。
對於Mono堆內存來說,由於Mono自身的限制,其堆內存分配是 “只升不降” 的,即內存一旦分配給Mono,不論以後該內存是否繼續被使用,都不會再歸還給系統。因此,建議您對於代碼的堆內存分配進行嚴格的控制,避免不必要的Mono堆內存分配。

Instantiate實例化操作

一般情況下,我們不建議項目在運行過程中頻繁地調用 Instantiate 和 Destroy 來創建和銷毀一個GameObject。這種做法不僅可能會造成頻繁且較高的CPU占用,更重要的是,它將造成大量的內存碎片,從而造成越來越多的堆內存分配,進而加速系統垃圾回收操作(Garbage Collection)的到來

Unity 的一些優化總結 (難度3 推薦4)