既然要聊unity3d執行時候的記憶體優化,那我們自然首先要知道
unity3d
遊戲引擎是如何分配記憶體的。大概可以分成三大部分:
1. unity3d內部的記憶體
2. mono的託管記憶體
3. 若干我們自己引入
的dll或者第三方
dll所需要的記憶體。
第3類不是我們關注的重點,所以
接下來我們會分別來看一下unity3d內部記憶體和
mono
託管記憶體,最後還將分析乙個官網上
assetbundle
的案例來說明記憶體的管理。
unity3d內部記憶體
unity3d的內部記憶體
都會存放一些什麼呢?各位想一想,除了用**來驅動邏輯,乙個遊戲還需要什麼呢?對,各種
資源。所以簡單總結一下unity3d內部記憶體存放的東西吧:
資源:紋理、網格、音訊等等
gameobject和各種元件。
引擎內部邏輯需要的記憶體:渲染器,物理系統,粒子系統等等
mono託管記憶體
因為我們的遊戲指令碼是用c#寫的,同時還要跨平台,所以帶著乙個
mono
的託管環境顯然必須的。那麼
mono
的託管記憶體自然就不得不放到記憶體的優化範疇中進行考慮。那麼我們所說的
mono
託管記憶體中存放的東西和
unity3d
內部記憶體中存放的東西究竟有何不同呢?其實
mono
的記憶體分配就是很傳統的執行時記憶體的分配了:
值型別:int型啦,
float
型啦,結構體
struct
啦,bool
啦之類的。它們都存放在堆疊上(注意額,不是堆所以不涉及
gc)。
引用型別:其實可以狹義的理解為各種類的例項。比如遊戲指令碼中對遊戲引擎各種控制項的封裝。其實很好理解,c#中肯定要有對應的類去對應遊戲引擎中的控制項。那麼這部分就是
c#中的封裝。由於是在堆上分配,所以會涉及到gc。
而mono託管堆中的那些封裝的物件,除了在在
mono
託管堆上分配封裝類例項化之後所需要的記憶體之外,還會牽扯到其背後對應的遊戲引擎內部控制項在
unity3d
內部記憶體上的分配。
舉乙個例子:
乙個在.cs指令碼中宣告的
www型別的物件
www,
mono
會在mono
託管堆上為
www分配它所需要的記憶體。同時,這個例項物件背後的所代表的引擎資源所需要的記憶體也需要被分配。
乙個www例項背後的資源:
壓縮的檔案
解壓縮所需的快取
解壓縮之後的檔案
如圖:那麼下面就舉乙個assetbundle的例子:
assetbundle的記憶體處理
assetbundle
的情景如下:
ienumerator downloadandcache (){
while (!caching.ready)
yield return null;
using(www www = www.loadfromcacheordownload (bundleurl, version)){
yield return www;
if (www.error != null)
throw new exception("www download had an error:" + www.error);
assetbundle bundle = www.assetbundle;
if (assetname == "")
instantiate(bundle.mainasset);
else
instantiate(bundle.load(assetname));
bundle.unload(false);
記憶體分配的三個部分匹夫已經在**中標識了出來:
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
的這種用法。其實相當於最後執行了:
www.dispose();
ok,web stream被刪除掉了。那還有誰呢?對
assetbundle
。那麼使用
bundle.unload(false);
ok,寫到這裡就先打住啦。寫的有點超了。有點趕也有點臨時,日後在補充編輯。
Unity學習小結3 Unity,你給我的坑
這個星期我覺得自己幾乎不同程度的栽到unity中那些大大小小的坑中。先說說boxcollider 我們很容易習慣使用在uisprite元件中勾選ajust boxcollider選項,在新增boxcollider之後勾選可以使碰撞器大小自適應元件的大小。但需要注意的是,如果這個元件是需要大量複製使用...
Unity學習小結3 Unity,你給我的坑
這個星期我覺得自己幾乎不同程度的栽到unity中那些大大小小的坑中。先說說boxcollider 我們很容易習慣使用在uisprite元件中勾選ajust boxcollider選項,在新增boxcollider之後勾選可以使碰撞器大小自適應元件的大小。但需要注意的是,如果這個元件是需要大量複製使用...
Unity 3D 優化記憶體
什麼是mipmap?mipmap旨在有效降低渲染頻寬的壓力,提公升遊戲的渲染效率。但是,開啟mipmap會將紋理記憶體提公升1.33倍。對於具有較大縱深感的3d遊戲來說,3d場景模型和角色我們一般是建議開啟mipmap功能的,但是在我們的測評專案中,經常會發現部分ui紋理也開啟了mipmap功能。這...