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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

unity asset store下载不了_Unity手游实战:从0开始SLG——资源管理系统-基础篇(三)AssetBundle原理...

發布時間:2024/7/19 windows 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity asset store下载不了_Unity手游实战:从0开始SLG——资源管理系统-基础篇(三)AssetBundle原理... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先用一句話介紹一下AssetBundle吧。

AssetBundle系統提供了一種壓縮文件的格式,可以把1到多個文件進行索引和序列化。

Unity項目在交付安裝之后,會通過AssetBundle對不包含代碼的資源進行更新。這就允許開發人員先提交一個小的應用程序包,將運行時內存壓力降到最低,并有選擇地加載針對不同終端用戶設備優化后的內容。

3.1 AssetBundle結構

總的來說,AssetBundle就像傳統的壓縮包一樣,由兩個部分組成:包頭和數據段。

包頭包含有關AssetBundle 的信息,比如標識符、壓縮類型和內容清單。清單是一個以Objects name為鍵的查找表。每個條目都提供一個字節索引,用來指示該Objects在AssetBundle數據段的位置。在大多數平臺上,這個查找表是用平衡搜索樹實現的。具體來說,Windows和OSX派生平臺(包括IOS)都采用了紅黑樹。因此,構建清單所需的時間會隨著AssetBundle中Assets的數量增加而線性增加。

數據段包含通過序列化AssetBundle中的Assets而生成的原始數據。如果指定LZMA為壓縮方案的話,則對所有序列化Assets后的完整字節數組進行壓縮。如果指定了LZ4,則單獨壓縮單獨Assets的字節。如果不使用壓縮,數據段將保持為原始字節流。

在Unity5.3之前,是無法對AssetBundle中單獨Objects進行壓縮的。因此,如果在5.3之前的Unity版本被要求從壓縮的AssetBundle中讀取一個或多個對象時,Unity必須解壓整個AssetBundle。通常,Unity會緩存AssetBundle的解壓縮副本,以提高在相同AssetBundle上的后續加載請求的加載性能。

3.2 加載AssetBundles

AssetBundles可以通過四個不同的API進行加載。但受限于兩個標準,這四個API的行為是不同的。2個標準如下:

1、AssetBundles的壓縮方式:LZMA、LZ4、還是未壓縮的。

2、AssetBundles的加載平臺。

而四個API分別是:

  • AssetBundle.LoadFromMemory(Async optional)
  • AssetBundle.LoadFromFile(Async optional)
  • UnityWebRequest's DownloadHandlerAssetBundle
  • WWW.LoadFromCacheOrDownload (on Unity 5.6 or older)

下面來詳細講一下4個API的區別。

3.2.1 AssetBundle.LoadFromMemory(Async)

Unity的建議是 不要使用這個API!

LoadFromMemory(Async) 是從托管代碼的字節數組里加載AssetBundle。也就是說你要提前用其他的方式將資源的二進制數組加入到內存中。然后該接口會將源數據從托管代碼字節數組復制到新分配的、連續的本機內存塊中。

但如果AssetBundle使用了LZMA壓縮類型,它將在復制時解壓AssetBundle。而未壓縮和LZ4壓縮類型的AssetBundle將逐字節的完整復制。

之所以不建議使用該API是因為,此API消耗的最大內存量將至少是AssetBundle的兩倍:本機內存中的一個副本,和LoadFromMemory(Async)從托管字節數組中復制的一個副本。

因此,從通過此API創建的AssetBundle加載的資產將在內存中冗余三次:一次在托管代碼字節數組中,一次在AssetBundle的棧內存副本中,第三次在GPU或系統內存中,用于Asset本身。

注意:在Unity5.3.3之前,這個API被稱為AssetBundle.CreateFromMemory。但功能沒有改變。

3.2.2 AssetBundle.LoadFromFile(Async)

LoadFromFile是一種高效的API,用于從本地存儲(如硬盤或SD卡)加載未壓縮或LZ4壓縮格式的AssetBundle。

在桌面獨立平臺、控制臺和移動平臺上,API將只加載AssetBundle的頭部,并將剩余的數據留在磁盤上。

AssetBundle的Objects 會按需加載,比如加載方法(例如AssetBundle.Load)被調用或其InstanceID被間接引用的時候。在這種情況下,不會消耗過多的內存。

但在Editor環境下中,API還是會把整個AssetBundle加載到內存中,就像讀取磁盤上的字節和使用AssetBundle.LoadFromMemoryAsync一樣。

如果在Editor中對項目進行了分析,此API可能會導致在AssetBundle加載期間出現內存尖峰。但這不應影響設備上的性能,在做優化之前,這些尖峰應該在設備上重新再測試一一遍.

要注意,這個API只針對未壓縮或LZ4壓縮格式,因為前面說過了,如果使用LZMA壓縮的話,它是針對整個生成后的數據包進行壓縮的,所以在未解壓之前是無法拿到AssetBundle的頭信息的。

注意:這里曾經有過一個歷史遺留問題,即在Unity5.3或更老版本的Android設備上,當試圖從Streaming Assets路徑加載AssetBundles時,此API將失敗。這個問題已在Unity5.4中已經解決。

在Unity5.3之前,這個API被稱為AssetBundle.CreateFromFile。其功能沒有改變。

3.2.3 AssetBundleDownloadHandler

DownloadHandlerAssetBundle的操作是通過UnityWebRequest的API來完成的。

UnityWebRequest API允許開發人員精確地指定Unity 應如何處理下載的數據,并允許開發人員消除不必要的內存使用。使用UnityWebRequest下載AssetBundle 的最簡單方法是調用UnityWebRequest.GetAssetBundle。

就實戰項目而言,最有意思的類是DownloadHandlerAssetBundle。它使用工作線程,將下載的數據流存儲到一個固定大小的緩沖區中,然后根據下載處理程序的配置方式將緩沖數據放到臨時存儲或AssetBundle緩存中。

所有這些操作都發生在非托管代碼中,消除了增加堆內存的風險。此外,該下載處理程序并不會保留所有下載字節的棧內存副本,從而進一步減少了下載AssetBundle的內存開銷。

LZMA壓縮的AssetBundles將在下載和緩存的時候更改為LZ4壓縮。這個可以通過設置Caching.CompressionEnable屬性來更改。

如果將緩存信息提供給UnityWebRequest對象的話,一旦有請求的AssetBundle已經存在于Unity的緩存中,那么AssetBundle將立即可用,并且此API的行為將會與AssetBundle.LoadFromFile相同操作。

在Unity5.6之前,UnityWebRequest系統使用了一個固定的工作線程池和一個內部作業系統來防止過多的并發下載,并且線程池的大小是不可配置的。在Unity5.6中,這些安全措施已經被刪除,以便適應更現代化的硬件,并允許更快地訪問HTTP響應代碼和報頭。

3.2.4 WWW.LoadFromCacheOrDownload

這是一個很古老的API了,從Unity2017.1開始,就只是簡單地包裝了UnityWebRequest。因此,使用Unity2017.1或更高版本的開發者應該直接使用UnityWebRequest來工作。Unity已經放棄了對改接口的維護,并可能在未來的某個版本中移除。

所以下面說的這些內容只適合于Unity5.6或更老的版本。

WWW.LoadFromCacheOrDownload允許從遠程服務器和本地存儲加載對象。也可以通過文件//URL從本地存儲加載文件。如果AssetBundle存在于Unitycache中,則此API的行為將與AssetBundle.LoadFromFile完全相同。

如果AssetBundle尚未緩存,則WWW.LoadFromCacheOrDownload會將從它的源文件讀取AssetBundle。如果AssetBundle被壓縮過,它會使用工作線程進行解壓縮并寫入緩存中。否則,它將通過工作線程直接寫入緩存。

在緩存AssetBundle之后,WWW.LoadFromCacheOrDownload將從緩存的、解壓縮的AssetBundle加載頭信息。然后,和AssetBundle.LoadFromFile加載AssetBundle行為相同。

此緩存會在WWW.LoadFromCacheOrDownload和UnityWebRequest之間共享。一個API下載的任何AssetBundle也可以通過另一個API獲得。

雖然數據將通過固定大小的緩沖區解壓縮并寫入緩存,但WWW對象會在本機內存中保留AssetBundle字節的完整副本。這個額外副本被保留的原因是因為要支持WWW.bytes字節屬性。

由于在WWW對象中緩存AssetBundle的字節的內存開銷,所以,實際項目開發中AssetBundles應該要保持較少的體積以便減少內存。

與UnityWebRequest不同的是,每次調用這個API都會產生一個新的工作線程。因此,在手機等內存有限的平臺上,最好限定一次只能下載一個AssetBundle,以避免內存激增。而在其他平臺也要小心創建過多的線程。

如果需要下載5個以上的AssetBundles,建議在腳本代碼中創建和管理下載隊列,以確保只有少數幾個AssetBundle同時下載。

3.2.5 建議

1、一般來說,只要有可能,就應該使用AssetBundle.LoadFromFile。這個API在速度、磁盤使用和運行時內存使用方面是最有效的。

2、對于必須下載或熱更新AssetBundles的項目,強烈建議對使用Unity5.3或更高版本的項目使用UnityWebRequest,對于使用Unity5.2或更老版本的項目使用WWW.LoadFromCacheOrDownload。

3、當使用UnityWebRequest或WWW.LoadFromCacheOrDownload時,要確保下載程序代碼在加載AssetBundle后正確地調用Dispose。另外,C#的using語句是確保WWW或UnityWebRequest被安全處理的最方便的方法。

4、對于需要獨特的、特定的緩存或下載需求的大項目,可以考慮使用自定義的下載器。編寫自定義下載程序是一項重要并且復雜的任務,任何自定義的下載程序都應該與AssetBundle.LoadFromFile保持兼容。

3.3 從AssetBundles中加載Assets

到這里,我們已經能夠獲得AssetBundles了,那么接下來就是要從AssetBundles里獲取Assets。

Unity提供了三個不同的API從AssetBundles加載UnityEngine.Objects,這些API都綁定到AssetBundle對象上,并且這些API具有同步和異步變體:

  • LoadAsset (LoadAssetAsync)
  • LoadAllAssets (LoadAllAssetsAsync)
  • LoadAssetWithSubAssets (LoadAssetWithSubAssetsAsync)

并且這些API的同步版本總是比異步版本快至少一個幀(其實是因為異步版本為了確保異步,都至少延遲了1幀),異步加載每幀會加載多個對象,直到他們的時間切片切出。

加載多個獨立的UnityEngine.Objects時應使用LoadAllAsset。并且只有在需要加載AssetBundle中的大多數或所有對象時,才應該使用它。與其他兩個API相比,LoadAllAsset比對LoadAsset的多個單獨調用略快一些。因此,如果要加載的Asset數量很大,但如果需要一次性加載不到三分之二的AssetBundle的話,則考慮將AssetBundle拆分為多個較小的包,再使用LoadAllAsset。

加載包含多個嵌入式對象的復合Asset時,應使用LoadAssetWithSubAsset,例如嵌入動畫的FBX模型或嵌入多個精靈的sprite圖集。也就是說,如果需要加載的對象都來自同一Asset,但與許多其他無關對象一起存儲在AssetBundle中,則使用此API。

任何其他情況,請使用LoadAsset或LoadAssetAsync。

3.3.1 低層級的加載細節

Object加載是在主線程上執行,但數據從工作線程上的存儲中讀取。任何不觸碰Unity系統中線程敏感部分(腳本、圖形)的工作都將在工作線程上轉換。例如,VBO將從網格創建,紋理將被解壓,等等。

從Unity5.3開始,Object加載就被并行化了。在工作線程上反序列化、處理和集成多個Object。當一個Object完成加載時,它的Awake回調將被調用,該對象的其余部分將在下一個幀中對UnityEngine可用。

同步AssetBundle.Load方法將暫停主線程,直到Object加載完成。但它們也會加載時間切片的Object,以便Object集成不會占用太多的毫秒幀時間。應用程序屬性設置毫秒數的屬性為Application.backgroundLoadingPriority。

ThreadPriority.High: 每幀最多50毫秒

ThreadPriority.Normal: 每幀最多10毫秒

ThreadPriority.BelowNormal: 每幀最多4毫秒

ThreadPriority.Low: 每幀最多2毫秒。

從Unity5.2開始,加載多個對象時候,會一直進行直到達到對象加載的幀時間限制為止。假設所有其他因素相等,asset 加載API的異步變體將總是比同步版本花費更長的時間,因為發出異步調用和對象之間有最小的一幀延遲。

3.3.2 AssetBundle 依賴項

根據運行時環境的不同,使用兩個不同的API自動跟蹤AssetBundles之間的依賴關系。在UnityEditor中,可以通過AssetDatabaseAPI查詢AssetBundle依賴項。AssetBundles分配和依賴項可以通過AssetImportAPI訪問和更改。在運行時,Unity提供了一個可選的API,通過基于ScriptableObject的AssetBundleManifest API加載在AssetBundle構建過程中生成的依賴信息。

當一個或多個AssetBundle 的UnityEngine.Objects引用了一個或者多個其他AssetBundle 的UnityEngine.Objects,那么這個AssetBundle就會依賴于另外的AssetBundle。AssetBundles充當由它包含的每個對象的FileGUID和LocalID標識的源數據。

因為一個對象是在其Instance ID第一次被間接引用時加載的,而且由于一個對象在加載其AssetBundle時被分配了一個有效的Instance ID,所以加載AssetBundles的順序并不重要。相反,在加載對象本身之前,重要的是加載包含對象依賴關系的所有AssetBundles。Unity不會嘗試在加載父AssetBundle時自動加載任何子AssetBundle。

示例:

假設material A引用texture B。material A被打包到AssetBundle1中,texture B被打包到AssetBundle2中:

在本用例中,AssetBundle2必須在material A從AssetBundle1中加載之前先加載。

這并不意味著AssetBundle 2必須在AssetBundle 1之前加載,或者texture B必須從AssetBundle 2中顯式加載。在將material A從AssetBundle 1加載之前加載AssetBundle 2就足夠了。

簡單來說就是AssetBundle之間的加載沒有先后,但是Asset的加載有。

有關AssetBundle依賴項的詳細信息,請參閱手冊頁。地址:https://docs.unity3d.com/Manual/AssetBundles-Dependencies.html?_ga=2.168691873.1408835506.1571651191-1030292064.1564583003

3.3.3. AssetBundle manifests

當使用BuildPiine.BuildAssetBundles API執行AssetBundle構建管線時,Unity會序列化一個包含每個AssetBundle依賴項信息的對象。此數據存儲在單獨的AssetBundle中,其中包含AssetBundleManifest類型的單個對象。

此Asset將存儲在與構建AssetBundles的父目錄同名的AssetBundle中。如果一個項目將其AssetBundles構建到位于(Projectroot)/Build/Client/的文件夾中,那么包含清單的AssetBundle將被保存為(Projectroot)/build/client/Client.manifest。

包含Manifest的AssetBundle可以像任何其他AssetBundle一樣加載、緩存和卸載。

AssetBundleManifest對象本身提供GetAllAssetBundles API來列出與清單同時構建的所有AssetBundles,以及查詢特定AssetBundle的依賴項的兩個方法:

  • AssetBundleManifest.GetAllDependencies返回AssetBundle的所有層次依賴項,其中包括AssetBundle的直接子級、其子級的依賴項等。
  • AssetBundleManifest.GetDirectDependations只返回AssetBundle的直接子級

請注意,這兩個API分配的都是字符串數組。因此,最好是在性能要求不敏感的時候使用。

3.3.4. 建議

在多數情況下,最好在玩家進入應用程序的性能關鍵區域(如主游戲關卡或世界)之前加載盡可能多的所需對象。這在移動平臺上尤為重要,因為在移動平臺上,訪問本地存儲的速度很慢,并且在運行時加載和卸載對象會觸發垃圾回收。

總結

以上是生活随笔為你收集整理的unity asset store下载不了_Unity手游实战:从0开始SLG——资源管理系统-基础篇(三)AssetBundle原理...的全部內容,希望文章能夠幫你解決所遇到的問題。

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