日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

unity3d 自动变化大小_【Unity游戏开发】AB学习(三)--加载AB和实例化操作对应的内存变化...

發布時間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity3d 自动变化大小_【Unity游戏开发】AB学习(三)--加载AB和实例化操作对应的内存变化... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

了解一下加載AB和實例化操作對應的內存變化,有助于我們更好的理解內存管理

很經典的對稱造型,用多少釋放多少。

這是各階段的內存和其他數據變化

說明:

  • 初始狀態
  • AssetBundle.Load文件后 ==》 內存多了文件鏡像,Memory+4.4MB,Total Object和Assets+1(AssetBundle也是object)
  • 載入Texture后 ==》 Memory+4MB,因為多了Texture Asset占用的內存,Total Objects和Assets+1
  • 載入Prefab后 ==》 內存無明顯變化,因為最占內存的Texture已經加載,Materials+1是因為多了Prefab的材質,Total Objects和Assets+6,因為 Perfab 包含很多 Components
  • 實例化Prefab以后 ==》 顯存(Texture Memory)+4MB、GameObject、Total Objects in Scene上升,都是因為實例化了一個可視的對象
  • 下面是開始對稱的操作
  • 銷毀實例后 ==》 Texture Memory-4MB,GameObject、Total Objects in Scene下降
  • 卸載AssetBundle文件后 ==》 AssetBundle文件鏡像占用的內存被釋放Memory-4.3MB(??泄露了?),相應的Assets和Total Objects Count也減1
  • 直接Resources.UnloadUnusedAssets ==》 沒有任何變化,因為所有Assets引用并沒有清空
  • 把Prefab引用變量設為null以后,再Resources.UnloadUnusedAssets ==》 整個Prefab除了Texture外都沒有任何引用了,所以被UnloadUnusedAssets銷毀,Assets和Total Objects Count -6,Materials-1
  • 再把Texture的引用變量設為null,再Resources.UnloadUnusedAssets ==》 之后也被UnloadUnusedAssets銷毀,內存被釋放Texture Memory-4MB,assets和Total Objects Count -1,基本還原到初始狀態
  • 綜上:

    • AssetBundle.Load 內存++【多了文件鏡像】
    • 實例化Prefab,顯存++【多了可視對象】
    Texture加載以后是到內存,顯示的時候才進入顯存的Texture Memory。所有的東西基礎都是ObjectLoad的是Asset,Instantiate的是GameObject和Object in SceneLoad的Asset要Unload,new的或者Instantiate的object可以Destroy

    下面我們詳細說一下細節概念:

    一、ab加載與釋放

  • AssetBundle.CreateFromFile運行時加載:只是個AssetBundle內存鏡像數據塊
  • AssetBundle.Load(同Resources.Load) 這才會從AssetBundle的內存鏡像里讀取并創建一個Asset對象,創建Asset對象同時也會分配相應內存用于存放(反序列化)
  • AssetBundle的釋放:
    • 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的時候都會卡一下?
    因為在你第一次Instaniate之前,相應的Asset對象還沒有被創建,要加載系統內置的 AssetBundle并創建Assets。第一次以后你雖然Destroy了,但Prefab的Assets對象都還在內存里,所以就很快了。

    例子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,但是速度比較慢
    或者:

    IEnumerator OnClick() {WWW image = new www(fileList[n++]);yield return image;Texture tex = obj.mainTexture;obj.mainTexture = image.texture;n = (n>=fileList.Length-1)?0:n;Resources.UnloadAsset(tex); }

    這樣卸載比較快


    參考:

    Unity3D內存釋放 (很詳細的)

    總結

    以上是生活随笔為你收集整理的unity3d 自动变化大小_【Unity游戏开发】AB学习(三)--加载AB和实例化操作对应的内存变化...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。