unity3d 自动变化大小_【Unity游戏开发】AB学习(三)--加载AB和实例化操作对应的内存变化...
生活随笔
收集整理的這篇文章主要介紹了
unity3d 自动变化大小_【Unity游戏开发】AB学习(三)--加载AB和实例化操作对应的内存变化...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
了解一下加載AB和實例化操作對應的內存變化,有助于我們更好的理解內存管理
很經典的對稱造型,用多少釋放多少。
這是各階段的內存和其他數據變化
說明:
綜上:
- AssetBundle.Load 內存++【多了文件鏡像】
- 實例化Prefab,顯存++【多了可視對象】
下面我們詳細說一下細節概念:
一、ab加載與釋放
- AssetBundle.Unload(flase)是釋放AssetBundle文件的內存鏡像,不包含Load創建的Asset內存對象。
- AssetBundle.Unload(true)是釋放那個AssetBundle文件內存鏡像和并銷毀所有用Load創建的Asset內存對象。
二、實例化
一個Prefab從assetBundle里Load出來,里面可能包括:Gameobject、transform、mesh、texture、material、shader、script和各種其他Assets。
你 Instaniate一個Prefab,是一個對Assets進行Clone(復制)+引用結合的過程,GameObject、transform 是Clone是新生成的。
- 其他mesh / texture / material / shader 等,這其中些是純引用的關系的,包括:Texture和TerrainData,
- 還有引用和復制同時存在的,包括:Mesh/material /PhysicMaterial。
- 引用的Asset對象不會被復制,只是一個簡單的指針指向已經Load的Asset對象。這種含糊的引用加克隆的混合, 大概是搞糊涂大多數人的主要原因。
總結一下各種釋放
- Destroy: 主要用于銷毀克隆對象,也可以用于場景內的靜態物體,不會自動釋放該對象的所有引用。雖然也可以用于Asset,但是概念不一樣要小心,如果用于銷毀從文 件加載的Asset對象會銷毀相應的資源文件!但是如果銷毀的Asset是Copy的或者用腳本動態生成的,只會銷毀內存對象。
- AssetBundle.Unload(false):釋放AssetBundle文件內存鏡像
- AssetBundle.Unload(true):釋放AssetBundle文件內存鏡像同時銷毀所有已經Load的Assets內存對象
- Reources.UnloadAsset(Object):顯式的釋放已加載的Asset對象,只能卸載磁盤文件加載的Asset對象
- Resources.UnloadUnusedAssets():用于釋放所有沒有引用的Asset對象
- GC.Collect():強制垃圾收集器立即釋放內存 Unity的GC功能不算好,沒把握的時候就強制調用一下
舉兩個例子幫助理解
例子1:
一個常見的錯誤:
- 你從某個AssetBundle里Load了一個prefab并克隆之:obj = Instaniate(AssetBundle1.Load('MyPrefab”);
- 這個prefab比如是個npc
- 然后你不需要他的時候你用了:Destroy(obj);你以為就釋放干凈了
- 其實這時候只是釋放了Clone對象,通過Load加載的所有引用、非引用Assets對象全都靜靜靜的躺在內存里。
- 這種情況應該在Destroy以后用:AssetBundle1.Unload(true),徹底釋放干凈。
- 如果這個AssetBundle1是要反復讀取的 不方便Unload,那可以在Destroy以后用:Resources.UnloadUnusedAssets()把所有和這個npc有關的Asset都銷毀。
- 當然如果這個NPC也是要頻繁創建 銷毀的 那就應該讓那些Assets呆在內存里以加速游戲體驗。
- 由此可以解釋另一個之前有人提過的話題:為什么第一次Instaniate 一個Prefab的時候都會卡一下?
例子2:
- 從磁盤讀取一個1.unity3d文件到內存并建立一個AssetBundle1對象
- AssetBundle AssetBundle1 = AssetBundle.CreateFromFile("1.unity3d");
- 從AssetBundle1里讀取并創建一個Texture Asset,把obj1的主貼圖指向它
- obj1.renderer.material.mainTexture = AssetBundle1.Load("wall") as Texture;
- 把obj2的主貼圖也指向同一個Texture Asset
- obj2.renderer.material.mainTexture =obj1.renderer.material.mainTexture;
- Texture是引用對象,永遠不會有自動復制的情況出現(除非你真需要,用代碼自己實現copy),只會是創建和添加引用
- 如果繼續:
- AssetBundle1.Unload(true) 那obj1和obj2都變成黑的了,因為指向的Texture Asset沒了
- 如果:
- AssetBundle1.Unload(false) 那obj1和obj2不變,只是AssetBundle1的內存鏡像釋放了
- 繼續:
- Destroy(obj1); //obj1被釋放,但并不會釋放剛才Load的Texture
- 如果這時候:
- Resources.UnloadUnusedAssets();
- 不會有任何內存釋放 因為Texture asset還被obj2用著
- 如果
- Destroy(obj2);
- obj2被釋放,但也不會釋放剛才Load的Texture
- 繼續
- Resources.UnloadUnusedAssets();
- 這時候剛才load的Texture Asset釋放了,因為沒有任何引用了
- 最后CG.Collect();
- 強制立即釋放內存
由此可以引申出論壇里另一個被提了幾次的問題,如何加載一堆大圖片輪流顯示又不爆掉?
不考慮AssetBundle,直接用www讀圖片文件的話等于是直接創建了一個Texture Asset 假設文件保存在一個List里
TLlist<string> fileList; int n=0; IEnumerator OnClick() {WWW image = new www(fileList[n++]);yield return image;obj.mainTexture = image.texture;n = (n>=fileList.Length-1)?0:n;Resources.UnloadUnusedAssets(); }這樣可以保證內存里始終只有一個巨型Texture Asset資源,也不用代碼追蹤上一個加載的Texture Asset,但是速度比較慢
或者:
這樣卸載比較快
參考:
Unity3D內存釋放 (很詳細的)
總結
以上是生活随笔為你收集整理的unity3d 自动变化大小_【Unity游戏开发】AB学习(三)--加载AB和实例化操作对应的内存变化...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows桌面键盘怎么调出来
- 下一篇: 堆叠柱形图上自定义数字_用Excel绘制