作者寫的很好,看了他的書收穫很大。以下內容摘自:
既然要聊unity3d執行時候的記憶體優化,那我們自然首先要知道unity3d遊戲引擎是如何分配記憶體的。大概可以分成三大部分:
unity3d內部的記憶體
mono的託管記憶體
若干我們自己引入的dll或者第三方dll所需要的記憶體。
第3類不是我們關注的重點,所以接下來我們會分別來看一下unity3d內部記憶體和mono託管記憶體,最後還將分析乙個官網上assetbundle的案例來說明記憶體的管理。
unity3d內部記憶體
unity3d的內部記憶體都會存放一些什麼呢?各位想一想,除了用**來驅動邏輯,乙個遊戲還需要什麼呢?對,各種資源。所以簡單總結一下unity3d內部記憶體存放的東西吧:
mono託管記憶體
因為我們的遊戲指令碼是用c#寫的,同時還要跨平台,所以帶著乙個mono的託管環境顯然必須的。那麼mono的託管記憶體自然就不得不放到記憶體的優化範疇中進行考慮。那麼我們所說的mono託管記憶體中存放的東西和unity3d內部記憶體中存放的東西究竟有何不同呢?其實mono的記憶體分配就是很傳統的執行時記憶體的分配了:
而mono託管堆中的那些封裝的物件,除了在在mono託管堆上分配封裝類例項化之後所需要的記憶體之外,還會牽扯到其背後對應的遊戲引擎內部控制項在unity3d內部記憶體上的分配。
舉乙個例子:
乙個在.cs指令碼中宣告的www型別的物件www,mono會在mono託管堆上為www分配它所需要的記憶體。同時,這個例項物件背後的所代表的引擎資源所需要的記憶體也需要被分配。
乙個www例項背後的資源:
如圖:
那麼下面就舉乙個assetbundle的例子:
assetbundle的記憶體處理
ienumerator downloadandcache () // memory is freed from the web stream (www.dispose() gets called implicitly)}}記憶體分配的三個部分匹夫已經在**中標識了出來:
web stream:包括了壓縮的檔案,解壓所需的快取,以及解壓後的檔案。
assetbundle:web stream中的檔案的對映,或者說引用。
例項化之後的物件:就是引擎的各種資源檔案了,會在記憶體中建立出來。
那就分別解析一下:
www www = www.loadfromcacheordownload (bundleurl, version)將壓縮的檔案讀入記憶體中
建立解壓所需的快取
將檔案解壓,解壓後的檔案進入記憶體
關閉掉為解壓建立的快取
assetbundle bundle = www.assetbundle;assetbundle此時相當於乙個橋梁,從web stream解壓後的檔案到最後例項化建立的物件之間的橋梁。
所以assetbundle實質上是web stream解壓後的檔案中各個物件的對映。而非真實的物件。
實際的資源還存在web stream中,所以此時要保留web stream。
instantiate(bundle.mainasset);通過assetbundle獲取資源,例項化物件
最後各位可能看到了官網中的這個例子使用了:
using(www www = www.loadfromcacheordownload (bundleurl, version))這種using的用法。這種用法其實就是為了在使用完web stream之後,將記憶體釋放掉的。因為www也繼承了idispose的介面,所以可以使用using的這種用法。其實相當於最後執行了:
//刪除web streamok,web stream被刪除掉了。那還有誰呢?對assetbundle。那麼使用www.dispose();
//刪除assetbundleok,寫到這裡就先打住啦。寫的有點超了。有點趕也有點臨時,日後在補充編輯。bundle.unload(false);
這篇文章當時寫的時候略顯倉促,因此並沒有特別介紹unity profiler工具,也更談不上用unity profiler工具來監測記憶體的使用狀態了。但是使用unity profiler工具來監測還是十分必要的,下面就簡單補充一下這方面的知識。
在profiler工具中提供了兩種模式供我們監測記憶體的使用情況,即簡易模式和詳細模式。在簡易模式中,我們可以看到總的記憶體(total)列出了兩列,即used total(使用總記憶體)和reserved total(預定總記憶體)。used total和reserved 均是物理記憶體,其中reserved是unity向系統申請的總記憶體,unity底層為了不經常向系統申請開闢記憶體,開啟了較大一塊記憶體作為快取,即所謂的reserved記憶體,而執行時,unity所使用的記憶體首先是向reserved中來申請記憶體,當不使用時也是先向reserved中釋放記憶體,從而來保證遊戲執行的流暢性。一般來說,used total越大,則reserved total越大,而當used total降下去後,reserved total也是會隨之下降的(但並不一定與used total同步)。
unity3d的記憶體從大體上可以分為以下幾個部分:
unity:位unity3d的底層**所分配的記憶體。
mono:即託管堆。mono執行時在執行遊戲指令碼時所需要的記憶體,換句話說託管堆的大小與我們的gameobject數量、資源量無關,僅是指令碼**造成的。這部分記憶體是有垃圾**機制的。
gfxdriver:可以理解為gpu視訊記憶體開銷,主要由texture,vertex buffer以及index buffer組成。所以盡可能地減少或釋放texture和mesh等資源,即可降低gfxdriver記憶體。
fmod:音訊的記憶體開銷。
profiler
而在簡易模式下的監視器最下方,則列出了常見的一些資源以及它們所消耗的記憶體。
紋理網格
材質動作
音訊遊戲物件的數量
而詳細模式則需要點選「take sample」按鈕來捕獲詳細的記憶體使用情況。需要注意的是,由於獲得資料需要花費一定的時間,因此我們無法獲得實時的詳細記憶體的使用情況。在詳細模式中,我們可以觀察每個具體資源和遊戲物件的記憶體使用情況。
Unity 優化方面的總結
其中textasset並不是真正意義上的text,而是編譯好的dll檔案,是以binary形式存在的。參考官方文件 text asset 中的 binary data 一節 發布包的美術資源加密 對於所有平台,最常見的是對貼圖進行加密,通過assetbundle和textasset來實現。程式發布後...
Unity記憶體優化
一 大概標準 1.紋理 40m 2.mono 30m 3.animation 20m 4.mesh 10m 6.font 10m 7.audio 5m 8.gfxdriver 25m 9.resourcemanager 視情況而定 跟 你resourcemanager裡放了多少檔案 該標準是我做 m...
Unity3D移動端記憶體優化(NGUI方面)
做3d移動端記憶體一直是人們頭疼的問題,載入的資源釋放了,還有其它的須要釋放。比方ngui釋放,事實上主要是ngui的texture和sprite釋放,假設你指令碼程式沒用到ngui組建的引用的話,切換場景後第一時間呼叫 resources.unloadunusedassets 就會釋放掉。可是假設...