這篇文章包含哪些內容html
這篇文章從Unity的Profile組件入手,來探討一下Unity在開發環境和正式環境中的內存使用發麪的一些區別,架構
而且給出了最好控制內存的方法(我想你已經知道了...Prefab ) ,以及緣由。性能
提早須要閱讀的文章學習
在閱讀本文以前或以後我建議閱讀一下如下幾篇文章測試
雨鬆的spa
Unity3D研究院之Assetbundle的實戰 http://www.xuanyusong.com/archives/2405/3d
Unity3D研究院之Assetbundle的原理 http://www.xuanyusong.com/archives/2373htm
王巍的對象
Unity 3D中的內存管理 http://onevcat.com/2012/11/memory-in-unity3d/blog
星塵(不太肯定是不是原做者 哈)的
Unity3D佔用內存太大的解決方法 http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html
從NGUI的AltasPacker提及
事情的原由仍是由於我在學習使用NGUI(剛接觸Unity沒幾天…), 教程看了看都沒問題 本身動手操做的時候忽然發現...
NGUI 建立UI時候必須都先要建立Altas,那我建立好後的散圖是放在工程裏面呢 仍是要刪掉? 不刪會影響性能麼?
Google了一番並無發現滿意答案,因此只好本身Profile一下,因而有了以下實驗:
1· 首先創建一個空場景,運行,打開Profile. Texture(紋理)部分使用內存2.5MB
2·加入一張圖片,場景上不作任何引用。 該圖片顯存展開後大小爲1.5MB , 運行 而後再打開Profile
3· 奇蹟的事情發生了... 紋理佔用的內存大小直接變爲 5.8MB
5.8MB- 2.5MB = 3.3MB 很奇怪的一個數,因而我同時懷疑三件事
1· 即便素材徹底用不到可是若是工程中有導入則最後會被打包
2· 即便素材沒有被當前場景使用,Unity仍舊會加載 ( Unity啓動時候加載全部的素材??! )
3· Unity對素材在內存中有留有一份引用,3.3MB ~= 1.5MBx2 ( ??! )
若是以上三點有一個是真的(全是錯的), 那Unity無疑直接變爲廢柴....
因而乎就此三點我開始無限的刨根問底....
功夫不負有心人吧,終於在一片帖子上面找到了突破口
http://answers.unity3d.com/questions/57909/find-unused-assets-in-project.html
這篇文章說的很清楚,Unity在發佈時候會自動過濾掉未引用的全部資源,而且整個被打包進來的資源能夠經過Log查看
根據文章指出的位置找到Log,而且就上面的工程進行測試,打出Android包 (Mac下Log在 /Users/eran/Library/Logs/Unity/Editor.log , eran爲你的用戶名)
這樣的話 第一個心結就解開了, 看來Unity果然沒有這麼傻... 之後使用NGUI製做Atlas時候也不用擔憂是否須要刪除小圖這件事了.
既然知道了只有在真機設備上才能夠進行測試,因而須要再將剛纔作的測試重來一次了,只不過此次是在真機上面.
1· 首先創建一個空場景,運行,打開Profile. Texture(紋理)部分使用內存153.0KB
能夠注意到,在真機上面運行時候 內存佔用明顯下降了,而且開銷的線很平,再也不像編輯環境同樣會有波動.
2·加入一張圖片並放置在場景上面
雖然沒有像想象中的那樣爲1.5MB,不過 既然小於3MB,則Unity3D確定不可能留有一分內存的備份(DRAM一份 VRAM一份,DRAM的用於處理LostConext時候從新上傳GPU).
這裏面其實還有一個小插曲:
在Android上面 Rendering中顯示 使用的顯存爲0,這點和我理解的3D渲染原理不符呀,一直讓我困惑了好久。後來忽然想到 難道是由於手機是共享顯存的緣由?
果不其然 當我把項目發佈爲PC版本時候 再跑Profile,顯存佔用就有數字了. 而且顯存佔用數和我後面說道的動態剔除還有關係,說明顯存還發生了swap,這塊和所講的事情無關 就不細說了,若是大神對這塊很瞭解 但願指點我一下.
ok 繼續說上面提到一嘴的 動態剔除,這個是我無心發現的,
我把上面那張圖加了一個Animation 讓其左右移動,當我真機測試時候,當這張圖片移出屏幕時候DrawCall會減1,也就是隻要屏幕看不到的東西Unity會自動幫你剔除,
減小DrawCall, 其實細想一想, 這個是很正常的一個事情,由於Unity是一個徹底的3D引擎,這也是爲何在Unity裏面沒有像素 進來單位是Unit,沒有屏幕的寬高,只能調整攝像機的視野.
相比之下以前用的Starling,Cocos,雖然底層也在使用GPU進行渲染,可是他的總體引擎架構是基於2D的,因此天然沒法在底層完成這種自動剔除以及顯存交換的行爲.相比之下Unity要優越許多.
就此Unity的一大謎題得以解開,根據上面的實驗我獲得了以下兩條結論
結論: 即便項目中有許多未使用的圖片,只要未放置在特殊文件夾下(Resource,StreamingAssets)而且沒有被Prefab引用,最終導出時候不會被打包,更不會佔用顯存,可是在開發階段會.
結論: Unity 會自行對移出場景的對象進行剔除從而減小DrawCall
Prefab 最好的管理內存(顯存)的方式
個人刨根問底行爲到這裏並無結束, 既然知道了Unity如何加載素材,那他何時卸載呢?
我又作了以下實驗:
創建兩個場景,SceneA,SceneB. 在SceneA中加載一張紋理,同時提供一個跳轉到SceneB的按鈕.
點擊按鈕跳轉到SceneB,SceneB是一個空場景 什麼都不放.
預期的是當切換到SceneB時候SceneA中所佔用的顯存應該會被釋放,不過結果卻又是讓人大失所望... 仍舊沒有變化
即便我在SceneB中調用GC都沒用(其實看過GC介紹的朋友也應該知道在那裏調GC原本就應該沒用)
最後又是一通Google,不過此次沒有像上次那麼走運 沒有任何的收穫,這也是我後來轉向開始研究Prefab的緣由. 不過仍是繼續把這裏說完.
又是一次意外的測試,我發現當我再創建一個SceneC時候, 由SceneA->SceneB->SceneC 這個時候 SceneA中的顯存會獲得釋放. 就此問題我還發了一個Question.
有個朋友給了他項目上的證明,Unity確實如此 http://ask.unitymanual.com/question/36097
既然Unity自動管理的內存須要跨兩個場景才能消除,那咱們有沒有辦法本身控制呢? 方法是有的 那就是使用Prefab.
如何建立及如何使用Prefab 鬆雨的那兩篇文章已經說的很是明白了,我就不重複造輪子了.
結論: Unity自身的顯存回收是須要通過跨兩個場景,若是使用Prefab在調用assetBundle.Unload (true)時候能夠釋放顯存。
以上是我這幾天經過實驗摸索的一些經驗,但願能對你有所幫助。若是哪裏說的不對還請大神指出
謝謝