Unity運行時刻資源管理html
----------------------------------------------------------------------------------------算法
Asset Bundles 網絡
製做:BuildPipeline.BuildAssetBundle() 框架
加載:AssetBundle.Load() koa
卸載:AssetBundle.Unload(bool unloadAllLoadedObjects) 異步
unloadAllLoadedObjects = true:釋放解壓數據,全部已實例化的資源亦被釋放。 ide
unloadAllLoadedObjects = false:釋放解壓數據,已實例化的資源不釋放。函數
Resource Folders post
製做:Project視圖中任意名爲「Resources」文件夾下的資源,不管場景中是否用到。 性能
加載:Resources.Load()
卸載:Resources.UnloadUnusedAssets(),實例經過Object.Destroy()釋放。
工做方式: 全部Resources資源及其相關資源都存儲於resources.assets中,但若是有資源被某場景使用,該資源則被存儲於該場景對應的sharedassets<0~n>.assets中。 若是編譯目標平臺爲Streaming Web Player,則狀況略有不一樣。你能夠在設置中經過First Streamed Level With Resources一項指定全部Resources資源跟隨哪一場景(Level)加載。在該模式下,全部先於「First streamed Level」加載的場景,用到的Resource資源同上,都存儲於其對應的sharedassets中;後於「First streamed Level」加載的場景,其用到的Resource資源,卻存儲於resources.assets中。
----------------------------------------------------------------------------------------
Streaming Web Players
該模式中的Streaming是以場景(Level)爲單位的,你能夠在編譯設置中指定各個場景的載入順序,Unity Web Player會按該順序自發異步加載各場景。同時,Unity也提供了經過WWW加載.unity3d場景文件的API,使開發者對場景加載有更靈活的控制權。 實際上,WWW能夠用於網絡下載任意資源(紋理、文本、二進制文件),視頻和音頻也能夠經過WWW下載,並且能夠作到邊下載邊播放。
AssetBundle
----------------------------------------------------------------------------------------
想打包進AssetBundle中的二進制文件,其文件名後綴必須爲「.bytes」,Unity會將其視爲TextAssets對待。
AssetBundle bundle = www.assetBundle;
獲取WWW.assetBundle的一刻,由WWW下載的數據壓縮包被解壓,AssetBundle對象被建立,此時你能夠用AssetBundle.Load()實例化資源了。
除非使用AssetBundle.LoadAll()獲取全部資源,不然沒法獲得一個AssetBundle中的資源列表。通常作法是在該AssetBundle中放置一個定好名稱的TextAsset,在其中維護一份全部資源的名稱列表。
一個AssetBundle包能夠引用其餘AssetBundle包中的資源。製做時,須要調用BuildPipeline.PushAssetDependencies()和BuildPipeline.PopAssetDependencies()函數對;加載時,被引用的包須要先於引用包加載。 另外,重編這種包須要開啓BuildAssetBundleOptions.DeterministicAssetBundle,以保證每次重編時所使用的資源ID都是同樣的。
你能夠在一個遊戲裏使用另外一個遊戲的AssetBundle,前提是該AssetBundle中所引用的資源,要麼存在於該AssetBundle中,要麼已經被載入了遊戲中。爲確保AssetBundle引用的資源被編進同包中,製做時可使用BuildAssetBundleOptions.CollectDependencies選項。
----------------------------------------------------------------------------------------
AssetDatabase Unity Editor使用AssetDatabase維護項目中的全部資源文件,Unity使用這套API取代傳統的filesystem。這是一個Editor類,因此只有在名爲「Editor」的文件夾下的Script中才有用。
BuildPipeline.BuildStreamedSceneAssetBundle()或BuildPipeline.BuildPlayer(..., BuildOptions.BuildAdditionalStreamedScenes)生成的場景包,使用WWW下載後,只需調用WWW.assetBundle,而不需AssetBundle.LoadAll(),便可激活包中的場景,即調用WWW.assetBundle後,你就能夠經過Application.LoadLevel()來載入場景了。
http://blog.csdn.net/ox_thedarkness/article/details/9197453
1.Unity3D佔用內存太大的解決方法 - 星塵
討論AssetBundle-Resources-GameObject 的生命週期問題。對AssetBundle.Unload,Instantiate,Destory,UnloadUnusedAsset有詳細的辨析。
http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html
討論基於Unity3d 4.1.5,不定時更新。
美術資源應導出爲AssetBundle文件。這種AssetBundle有兩種存儲方式:能夠是未壓縮的,也可使用7z算法壓縮,默認壓縮。以我手頭的一個蒙皮動畫角色爲例,壓縮後文件大小由800K減小到260K。導出過程當中各個成分佔的文件比例會在Logs中打印出來,以供分析和優化。
AssetBundle有下面兩個主要的加載方法:
AssetBundle.CreateFromFile只能加載未壓縮的文件。根據文檔的說法,該方法是最快的加載方法,可是不知道這個"fast"是指「performace」仍是"easy"。若是該算法是流式加載,可能確實是最快的,由於其餘加載方法都有中間產物,例如CreateFromMemory或者WWW需會產生額外的byte[]。
AssetBundle.CreateFromMemory異步加載內存中二進制字節。這帶來的好處是,硬盤上的文件可使用自定義的方式組織、壓縮和打包。
加載過程當中會產生三級中間產物:
AssetBundle
Asset-Object:全部AssetBundle.Load*建立的Object,包括mainAsset
Cloned-Object:Instantiate一個Asset-Object以後產生的Object
其中,AssetBundle是資源的靜態二進制存檔形式。此時資源並無真正讀出,只有執行Load操做資源纔會被建立到Resouces系統中。Resources系統管理Asset-Object亦即實際的資源,包括貼圖、mesh、Asset-GameObject。其中的Asset-GameObject很是相似Cloned-GameObject,可是沒法掛載到場景中,沒法被Destroy銷燬,只能用Instantiate生成Cloned-Object。實際咱們看見的是Cloned-Object。
Unity3d並無追蹤每一個資源的來源。假如你反覆加載同一個資源文件,每次AssetBundle.CreateFromFile/Memory都會建立一個新的AssetBundle,包含新的貼圖、新的模型。爲了減小這類誤用,Unity在每一個資源包的二進制內容中添加了一個隨機包標誌(包標誌是導出時添加的,即便是同一個資源,每次導出都是不一樣的包)。Unity3d經過比較包標誌的方式,禁止同時存在兩個讀取了相同資源包。若一個資源包對應的AssetBundle沒有Unload,再次建立新的該資源的AssetBundle時會拋出錯誤:
The asset bundle '<unknown>' can't be loaded because another asset with the same files are already loaded
可是Unity只是簡單在AssetBundle建立時作了檢查,在Asset-Object級沒有記錄包標誌來源,也不會合並相同資源。
有一種不良作法:每次都從新讀取資源包以後當即釋放包,將Instantiate出來的角色放在場景上。這種作法很簡潔不會引發內存泄漏,可是對於mmo rpg而言,場景上常常會有不少相同角色。每次從新讀取的資源包都會產生獨立的Asset-Object,結果就是場景上的20只史萊姆會擁有20份骨骼、20份貼圖、20份材質、佔用20份顯存。
總的來講,項目框架須要手工管理AssetBundle,保證同一套資源不重複加載。
全部AssetBundle.Load*加載的UnityEngine.Object,咱們稱爲Asset-Object,與Instantiate創造出的 Cloned-Object相對應。
這兩個概念在[1]的第一張配圖中分別標記爲」Asset-*「和」*-複製「。對成員mainAsset的訪問其實是完整的加載函數調用,爲手工調用Load的簡化版。另外經測試,反覆Load同一個資源至少沒有額外資源泄露。
在Unity自帶的Profile系統中,Memory欄下 Textures/Meshes/Materials/AnimationClips/AudioClips指的就是Asset-Object。例如,從一個史萊姆Instantiate出不少史萊姆並不會增長Textures或者Meshes計數。
雖然都是UnityEngine.Object,可是Asset-Object和Cloned-Object本質是不一樣的。例如,若是對Asset-Object執行Destroy,系統會報錯:
Destroying assets is not permitted to avoid data loss.
Asset-Object是由Resources系統管理的,包括Asset中的Texture、AnimationClips等,爲內存開銷的主要來源。Resources系統使用弱引用管理Asset-Object,同時提供了Resources.UnloadUnusedAsset()以刪除沒有再也不被強引用的Asset-Object。注意他檢查的是全部強引用,並不限於場景中實際GameObject,因此若是你的代碼中記錄了的Asset表,還有某些代碼的意外引用都會阻止這些資源被Resources系統釋放。
有一種錯誤理解:咱們只須要AssetBundle.Unload(false),而後在刪除場景內容時Object.Destroy(),這樣是否就沒有泄漏了?答案是否認的,前者刪除了AssetBundle,後者刪除了Cloned-Object,可是Asset-Object尚未刪除。Asset-Object由Resources系統管理,須要手工調用Resources.UnloadUnusedAsset()或者其餘相似接口才能刪除。
正確的資源徹底釋放方法:AssetBundle.Unload(true)——釋放AssetBundle和Asset-Object,然後Object.Destroy()釋放Cloned-Object。
導出場景只能用BuildStreamedSceneAssetBundle,不能使用BuildAssetBundle。場景文件仍然能夠用CreateFromMemory讀取,只不過Clone的時候必須使用Application.LoadLevel。並且LoadLevel過程和結果貌似不可控,好比你從程序上並不能獲得「場景加載完畢」或者「場景的內容是什麼」這樣的信息。
裏面提到C#進行本地配置的問題,看不大懂先掛着,有時間再去研究