Unity學(xué)習(xí)—資源管理概覽

本文介紹了 Unity 常用四種默認(rèn)路徑,以及 AssetDataBase、Resources灾锯、AssetBundle 和目前最新的 Addressable 四種資源管理方式

文中所有 API 均以版本 2019.3 為準(zhǔn)

本文原地址:Unity學(xué)習(xí)—資源管理概覽

資源路徑

Application.dataPath

官方文檔

只讀猾愿,Editor 可讀寫(xiě)

游戲數(shù)據(jù)相對(duì)路徑,即游戲安裝路徑若债,PC 上路徑會(huì)使用 '/' 分割文件夾

  • Unity Editor: <項(xiàng)目根路徑>/Assets
  • Mac player: <App 包路徑>/Contents
  • iOS player: <App 包路徑>/<AppName.app>/Data
  • Win/Linux player: <可執(zhí)行數(shù)據(jù)文件夾路徑>
  • WebGL: player data 文件的 絕對(duì) url 地址 (不包含具體文件名)
  • Android: 一般為 APK 路徑, 若使用 split binary build, 則為 OBB 路徑
  • Windows Store Apps: player data 文件夾的絕對(duì)地址

Application.persistentDataPath

官方文檔

可讀寫(xiě)拆融,用于持久化數(shù)據(jù)存儲(chǔ)蠢琳,在 iOS 和 Android 平臺(tái)該路徑指向設(shè)備的公共路徑,該目錄不會(huì)隨 App 升級(jí)而刪除镜豹,但可被用戶(hù)直接刪除

persistentDataPath的路徑由Bundle Identifier生成的 GUID 組成傲须,只要Bundle Identifier不變,路徑不變

iOS 會(huì)自動(dòng)將 persistentDataPath 路徑下的文件備份到 iCloud

  • Windows Store Apps: %userprofile%\AppData\Local\Packages\<productname>\LocalState
  • iOS: /var/mobile/Containers/Data/Application/<guid>/Documents
  • Android: /storage/emulated/0/Android/data/<packagename>/files 該路徑由 android.content.Context.getExternalFilesDir 獲得趟脂,部分機(jī)型該路徑會(huì)指向 SD 卡
  • Mac: ~/Library/Application Support/<company name>/<product name> 泰讽,舊版本還可能為 ~/Library/Caches~/Library/Application Support/unity.company name.product name,Unity 會(huì)查詢(xún)并使用以上路徑中最早的路徑

Application.streamingAssetsPath

官方文檔 官方手冊(cè)

只讀,Editor 可讀寫(xiě)

流數(shù)據(jù)存儲(chǔ)的相對(duì)路徑已卸,該目錄下 Asset 在 Unity 編譯時(shí)不會(huì)被 Unity 打包佛玄,使其在運(yùn)行時(shí)可直接通過(guò)路徑獲取,可將資源放入 Assets 目錄下任何名為 StreamingAssets文件夾

StreamingAssets中資源可使用 I/O 讀取累澡,但 WebGL 和 Android 平臺(tái)下該路徑為 URL梦抢,不支持直接獲取,因此需使用 UnityWebRequest獲取愧哟。若其他平臺(tái)使用 UnityWebRequest 獲取奥吩,則需在路徑前加上"file://" ,如 "file://" + Application.streamingAssetsPath + "/file.mp4"

  • Unity Editor, Windows, Linux players, PS4, Xbox One, Switch : Application.dataPath + "/StreamingAssets"
  • Mac: Application.dataPath + "/Resources/Data/StreamingAssets"
  • iOS: Application.dataPath + "/Raw"
  • Android: "jar:file://" + Application.dataPath + "!/assets" (壓縮后的 APK/JAR 文件)

Application.temporaryCachePath

可讀寫(xiě)翅雏,臨時(shí)數(shù)據(jù)和緩存路徑圈驼,應(yīng)用更新或覆蓋安裝時(shí)不會(huì)被清除,手機(jī)空間不足時(shí)才可能會(huì)被系統(tǒng)清除

路徑示例

路徑 Editor Windows Mac OS iOS Android
Application.dataPath 項(xiàng)目路徑/Assets 安裝路徑/ProductName_Data /Applications/AppName.app/Contents /var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/AppName.app/Data /data/app/package.name.apk
Application.persistentDataPath C:/Users/username/AppData/LocalLow/CompanyName/ProductName <br />或<br />/Users/username/Library/Application Support/CompanyName/ProductName C:\Users\username\AppData\LocalLow\CompanyName\ProductName /Users/username/Library/Application Support/CompanyName/AppName /var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents /data/data/package.name/files
Application.streamingAssetsPath 項(xiàng)目路徑/Assets/StreamingAssets 安裝路徑/ProductName_Data/StreamingAssets /Applications/AppName.app/Contents/Resources/Data/StreamingAssets /var/containers/Bundle/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/AppName.app/Data/Raw jar:file:///data/app/package.name.apk/!/assets
Application.temporaryCachePath C:/Users/username/AppData/Local/Temp/CompanyName/ProductName<br />或<br />/var/folders/xx/xxxxxxxxxxxxxx/X/CompanyName/ProductName C:\Users\username\AppData\Local\Temp\CompanyName\ProductName /var/folders/xx/xxxxxxxxxxxxxx/X/CompanyName/ProductName /var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches /data/data/package.name/cache

讀寫(xiě)權(quán)限說(shuō)明

https://blog.csdn.net/BillCYJ/article/details/99712313

資源加載

推薦官方教程

AssetDataBase

AssetDataBase 可在 Editor 環(huán)境下對(duì)項(xiàng)目 Asset 進(jìn)行增刪改查等操作(可實(shí)現(xiàn)與 Unity 編輯器頂部工具欄 Assets 選項(xiàng)下基本相同的功能)望几,使用方法可參考官方手冊(cè) 接口文檔

Resources

接口文檔

可在項(xiàng)目 Assets 目錄下任意位置創(chuàng)建Resources文件夾绩脆,打包時(shí) Unity 會(huì)整合所有位于Resources文件夾的 Asset 及其依賴(lài),并生成一個(gè)只讀的 resources.assets 資產(chǎn)文件橄抹,對(duì)于 Resources 目錄中在游戲中被直接引用的資產(chǎn)靴迫,則會(huì)被另外打包到 sharedassets0.assets

Resources 最佳實(shí)踐

官方的建議是不使用 Resources,有以下幾點(diǎn)原因:

  1. Resources 文件夾會(huì)導(dǎo)致內(nèi)存管理困難
  2. 不適當(dāng)使用 Resources 文件夾會(huì)加長(zhǎng)應(yīng)用啟動(dòng)和編譯時(shí)間楼誓,Resources 文件夾越多玉锌,Asset 管理越困難
  3. Resources 系統(tǒng)降低項(xiàng)目針對(duì)指定平臺(tái)使用自定義內(nèi)容的能力,并且無(wú)法實(shí)現(xiàn)增量更新(AssetBundle 是 Unity 針對(duì)不同設(shè)備提供特定內(nèi)容的主要工具)

適合使用 Resources 的場(chǎng)景:

  1. 因其簡(jiǎn)單快速的特性疟羹,適合用于快速原型和實(shí)驗(yàn)開(kāi)發(fā)主守,但當(dāng)正式開(kāi)發(fā)時(shí)應(yīng)當(dāng)減少使用
  2. 適合以下條件都滿(mǎn)足的狀況
    1. 該內(nèi)容不會(huì)占用大量存儲(chǔ)資源
    2. 該內(nèi)容在整個(gè)生命周期都需要
    3. 該內(nèi)容幾乎不需要修改
    4. 該內(nèi)容在不同平臺(tái)設(shè)備都一致

Resources 序列化

項(xiàng)目編譯時(shí)會(huì)將所有 Resources 目錄下 Asset 和 Object 合并到一個(gè)序列化的 resources.assets文件,該文件中還包含了類(lèi)似于 AssetBundle 的元數(shù)據(jù)(metadata)和索引信息榄融,該信息包含了由對(duì)象名稱(chēng)轉(zhuǎn)化得到的 GUID 和 Local ID 的查找樹(shù)和對(duì)象位于序列化文件中的字節(jié)偏移量

對(duì)于大部分平臺(tái)参淫,查找樹(shù)為時(shí)間復(fù)雜度為 O(n log(n)) 的平衡查找樹(shù),隨著 Resources 中對(duì)象的增加愧杯,索引加載時(shí)間增長(zhǎng)速度將超過(guò)線(xiàn)形增長(zhǎng)速度

Resources 系統(tǒng)在 Splash 展示時(shí)初始化涎才,該過(guò)程不可跳過(guò),經(jīng)觀察在低端設(shè)備上力九,10000 個(gè) Asset 文件就會(huì)導(dǎo)致該過(guò)程長(zhǎng)達(dá)數(shù)秒耍铜,哪怕很多對(duì)象在第一個(gè)場(chǎng)景沒(méi)用到也會(huì)被加載

接口 說(shuō)明
FindObjectsOfTypeAll 獲取所有指定類(lèi)型的對(duì)象
Load 加載 Resources 指定目錄下的 Asset
LoadAll 加載 Resources 指定目錄下的所有 Asset
LoadAsync 異步加載 Resources 指定目錄下的 Asset
UnloadAsset 將 asset 從內(nèi)存釋放,重新加載 Asset 不會(huì)使之前的引用重新鏈接
UnloadUnusedAssets 釋放未使用的 Asset(包括僅在腳本堆棧使用跌前,未在GameObject 使用)
void Start()
{
    //Load a text file (Assets/Resources/Text/textFile01.txt)
    var textFile = Resources.Load<TextAsset>("Text/textFile01");

    //Load text from a JSON file (Assets/Resources/Text/jsonFile01.json)
    var jsonTextFile = Resources.Load<TextAsset>("Text/jsonFile01");
    //Then use JsonUtility.FromJson<T>() to deserialize jsonTextFile into an object

    //Load a Texture (Assets/Resources/Textures/texture01.png)
    var texture = Resources.Load<Texture2D>("Textures/texture01");

    //Load a Sprite (Assets/Resources/Sprites/sprite01.png)
    var sprite = Resources.Load<Sprite>("Sprites/sprite01");

    //Load an AudioClip (Assets/Resources/Audio/audioClip01.mp3)
    var audioClip = Resources.Load<AudioClip>("Audio/audioClip01");
}

AssetBundle

官方手冊(cè) 接口文檔

AssetBundle 是外部資產(chǎn)的集合棕兼,可獨(dú)立于 Unity 構(gòu)建過(guò)程外,是 Unity 更新非代碼內(nèi)容的主要工具抵乓,經(jīng)常置于服務(wù)器上供用戶(hù)終端動(dòng)態(tài)獲瘸檀ⅰ蹭沛;AssetBundle 使開(kāi)發(fā)者可以提交更小的應(yīng)用包臂寝,最小化運(yùn)行時(shí)內(nèi)存壓力章鲤,使終端可以選擇性加載優(yōu)化內(nèi)容

該部分僅簡(jiǎn)單介紹 AssetBundle,更多信息可見(jiàn) Unity學(xué)習(xí)—AssetBundle

AssetBundle 構(gòu)建

  1. 首先分配資產(chǎn)對(duì)象所在 AssetBundle咆贬,在 Project 窗口選中需要打包的 Asset败徊,在 Inspect 窗口底部可見(jiàn)如下圖內(nèi)容,底部 AssetBundle 后有兩個(gè)輸入選擇框掏缎,第一個(gè)為該資源所在 AssetBundle 名稱(chēng)皱蹦,第二個(gè)為 AssetBundle 變體名稱(chēng)

    除此之外,Unity 還提供了 AssetImporter.assetBundleNameAssetImporter.assetBundleVariant等接口將資源分配到 AssetBundle

    image
  2. 然后即可構(gòu)建 AssetBundle 了眷蜈,使用BuildPipeline.BuildAssetBundles()即可構(gòu)建 AssetBundle沪哺,其中可配置參數(shù)輸出路徑、構(gòu)建選項(xiàng)酌儒、目標(biāo)平臺(tái)

  3. 或者可以使用 Unity 官方提供的工具管理 AssetBundle AssetBundles-Browser 官方手冊(cè)

[MenuItem("Build Asset Bundles/Normal")]
static void BuildABsNone()
{
    BuildPipeline.BuildAssetBundles("Assets/MyAssetBuilds", BuildAssetBundleOptions.None, BuildTarget.StandaloneOSX);
}

AssetBundle 構(gòu)建選項(xiàng)

BuildAssetBundleOptions
  • None
  • UncompressedAssetBundle:不壓縮
  • DisableWriteTypeTree:不包含類(lèi)型信息
  • DeterministicAssetBundle:使用哈希值作為 Asset Id
  • ForceRebuildAssetBundle:強(qiáng)制重建
  • IgnoreTypeTreeChanges:增量構(gòu)建檢查時(shí)忽略類(lèi)型樹(shù)改動(dòng)
  • AppendHashToAssetBundleName:AssetBundle 名稱(chēng)后加哈希值
  • ChunkBasedCompression:使用 LZ4 壓縮
  • StrictMode:構(gòu)建過(guò)程中任務(wù)錯(cuò)誤即構(gòu)建失敗
  • DryRunBuild:試運(yùn)行
  • DisableLoadAssetByFileName:禁用名稱(chēng)查找資源辜妓,可降低運(yùn)行時(shí)內(nèi)存提高加載效率
  • DisableLoadAssetByFileNameWithExtension:禁用帶后綴名的名稱(chēng)查找資源,可降低運(yùn)行時(shí)內(nèi)存提高加載效率

AssetBundle 派發(fā)方式

根據(jù)實(shí)際情況選擇 AssetBundle 時(shí)隨項(xiàng)目打包忌怎,或后續(xù)通過(guò)網(wǎng)絡(luò)下載籍滴,一般移動(dòng)平臺(tái)由于初始安裝大小和下載限制,會(huì)選擇安裝后下載榴啸,而主機(jī)和電腦則隨項(xiàng)目打包

隨項(xiàng)目打包有兩個(gè)主要原因:

  1. 減少項(xiàng)目構(gòu)建時(shí)長(zhǎng)孽惰,簡(jiǎn)化迭代開(kāi)發(fā),針對(duì)無(wú)需單獨(dú)更新的 AssetBundle 可放在 StreamingAssets 目錄下
  2. 發(fā)布可更新的初始修正內(nèi)容鸥印,用于節(jié)省用戶(hù)初始安裝后的時(shí)間和為后續(xù)修復(fù)做準(zhǔn)備勋功。但 StreamingAssets 不適用于該情況,若不考慮自定義下載和緩存系統(tǒng)库说,則可以使用 Unity 的緩存系統(tǒng)狂鞋,從 StreamingAssets 下載初始緩存

一般推薦使用 UnityWebRequest下載 AssetBundle,若下載包為 LZMA 壓縮璃弄,則緩存的為未壓縮或使用 LZ4 重壓縮的內(nèi)容要销,若緩存已滿(mǎn),則 Unity 會(huì)刪除最近最少使用的 AssetBundle

Unity 內(nèi)置的 AssetBundle 緩存系統(tǒng)用于緩存 UnityWebRequestAssetBundle.GetAssetBundle下載的包夏块,緩存僅以名稱(chēng)作為唯一標(biāo)識(shí)疏咐。另外可通過(guò)重載方法可傳入版本號(hào)(開(kāi)發(fā)者自己管理版本號(hào)),緩存系統(tǒng)會(huì)比對(duì)版本號(hào)脐供,選擇匹配版本或下載新包

緩存系統(tǒng)可通過(guò) Caching.expirationDelayCaching.maximumAvailableDiskSpace 修改最小未使用過(guò)期時(shí)間和最大緩存空間浑塞,當(dāng)緩存文件在過(guò)期時(shí)間內(nèi)沒(méi)被打開(kāi)過(guò)即被刪除,或緩存空間不足政己,則優(yōu)先刪除最近最少打開(kāi)的緩存

IEnumerator GetText()
{
    using (UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle("http://www.my-server.com/mybundle"))
    {
        yield return uwr.SendWebRequest();

        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log(uwr.error);
        }
        else
        {
            // Get downloaded asset bundle
            AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
        }
    }
}

AssetBundle 加載

有四種不同的 API 用于加載 AssetBundle酌壕,但每個(gè) API 的行為隨壓縮算法和平臺(tái)而不同

  • AssetBundle.LoadFromMemoryAsync

    IEnumerator LoadFromMemoryAsync(string path)
    {
        AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
        yield return createRequest;
        AssetBundle bundle = createRequest.assetBundle;
        var prefab = bundle.LoadAsset<GameObject>("MyObject");
        Instantiate(prefab);
    }
    
  • AssetBundle.LoadFromFile

    該方法可高效地從硬盤(pán)加載未壓縮或 LZ4 壓縮的 Assetbundle,加載 LZMA 壓縮包時(shí)會(huì)先解壓再加載到內(nèi)存

    public class LoadFromFileExample : MonoBehaviour {
        function Start() {
            var myLoadedAssetBundle 
                = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
            
            if (myLoadedAssetBundle == null) {
                Debug.Log("Failed to load AssetBundle!");
                return;
            }
            var prefab = myLoadedAssetBundle.LoadAsset.<GameObject>("MyObject");
            Instantiate(prefab);
        }
    }
    
  • WWW.LoadfromCacheOrDownload(5.6 及以前版本)

    舊方法,已拋棄

  • UnityWebRequestAssetBundle (5.3 及以后版本)

    先使用UnityWebRequest.GetAssetBundle創(chuàng)建請(qǐng)求卵牍,再將請(qǐng)求傳入DownloadHandlerAssetBundle.GetContent(UnityWebRequest)果港,下載完成后可像AssetBundle.LoadFromFile 一樣,直接使用 assetBundle 對(duì)象

    該方法使開(kāi)發(fā)者更靈活處理下載數(shù)據(jù)糊昙,選擇臨時(shí)存儲(chǔ)或長(zhǎng)期緩存辛掠,避免不必要的內(nèi)存使用。同時(shí)释牺,由于是原生代碼萝衩,沒(méi)有托管堆棧擴(kuò)展風(fēng)險(xiǎn),DownloadHandler 也不會(huì)保留下載數(shù)據(jù)没咙,進(jìn)一步減少了內(nèi)存開(kāi)銷(xiāo)

    LZMA 壓縮包會(huì)在下載時(shí)解壓猩谊,并以 LZ4 重新壓縮緩存,可調(diào)用 Caching.CompressionEnabled 修改

    IEnumerator InstantiateObject()
    {
        string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName; 
        UnityEngine.Networking.UnityWebRequest request 
            = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
        yield return request.Send();
        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
        GameObject cube = bundle.LoadAsset<GameObject>("Cube");
        GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");
        Instantiate(cube);
        Instantiate(sprite);
    }
    

官方推薦盡量使用 AssetBundle.LoadFromFile祭刚,該 API 在速度牌捷、磁盤(pán)使用和運(yùn)行時(shí)內(nèi)存使用方面都最高效;需要下載則使用 UnityWebRequest

AssetBundle Asset 加載

同步異步加載 Asset 一共有六種 API 可使用袁梗,同步方法一定比對(duì)應(yīng)的異步方法快至少一幀

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

LoadAllAssets適合加載包中大部分或所有獨(dú)立 Unity 對(duì)象時(shí)使用宜鸯,相較于多次重復(fù)調(diào)用另外兩種 API,LoadAllAssets速度要稍快一點(diǎn)遮怜。因此當(dāng) Asset 數(shù)量巨大且一次性需要加載的 Asset 少于 2/3 的時(shí)候淋袖,建議將 AssetBundle 拆分成多個(gè)小包體,再使用LoadAllAssets加載

LoadAssetWithSubAssets適合需要加載的對(duì)象內(nèi)嵌了其他對(duì)象的情況锯梁,若加載對(duì)象均來(lái)自于一個(gè) Asset 且包中有許多其他無(wú)關(guān)對(duì)象即碗,則使用該 API

其他情況均用LoadAsset (LoadAssetAsync)

Unity 對(duì)象加載時(shí)在主線(xiàn)程執(zhí)行,對(duì)象數(shù)據(jù)是在工作線(xiàn)程 worker thread陌凳,任何線(xiàn)程不敏感的操作都在工作線(xiàn)程執(zhí)行

異步加載時(shí)會(huì)根據(jù)時(shí)間片限制每幀加載多個(gè)對(duì)象剥懒,自 Unity 5.3 后,對(duì)象加載就并行化了合敦。多個(gè)對(duì)象在工作線(xiàn)程被反序列化初橘、處理和集成,當(dāng)對(duì)象加載完成充岛,則觸發(fā) Awake 回調(diào)

同步加載方法 AssetBundle.Load會(huì)暫停主線(xiàn)程知道加載完成保檐,它們還將加載過(guò)程進(jìn)行時(shí)間切片,以使對(duì)象集成所占用的幀時(shí)間不超過(guò)特定的毫秒數(shù)崔梗,該值可通過(guò)Application.backgroundLoadingPriority設(shè)定

  • ThreadPriority.High: 最大 50 毫秒每幀
  • ThreadPriority.Normal: 最大 10 毫秒每幀
  • ThreadPriority.BelowNormal: 最大 4 毫秒每幀
  • ThreadPriority.Low: 最大 2 毫秒每幀

在其他因素相同的情況下夜只,異步加載方法的調(diào)用到加載對(duì)象可用之間最小有一幀延遲,導(dǎo)致異步加載方法比同步方法執(zhí)行所需時(shí)間更長(zhǎng)

AssetBundle 依賴(lài)

根據(jù)運(yùn)行環(huán)境可以使用兩個(gè)不同的 API 自動(dòng)追蹤 AssetBundle 之間的依賴(lài)蒜魄。Editor 環(huán)境下扔亥,可使用AssetDatabase查詢(xún)依賴(lài)场躯,使用AssetImporter訪(fǎng)問(wèn)和修改 AssetBundle 的分配和依賴(lài);運(yùn)行時(shí)旅挤,可以通過(guò)基于 ScriptableObject 的 AssetBundleManifest API 加載在 AssetBundle 構(gòu)建期間生成的依賴(lài)項(xiàng)信息

當(dāng)一個(gè)對(duì)象所在的 AssetBundle 被加載時(shí)踢关,該對(duì)象就被分配了一個(gè)唯一的有效實(shí)例 ID,因此 AssetBundle 的加載順序并不重要谦铃,重要的是在加載該對(duì)象本身之前耘成,要優(yōu)先把所有包含其依賴(lài)對(duì)象的 AssetBundle 加載好。

Unity 不會(huì)自動(dòng)加載子 AssetBundle驹闰,具體可詳見(jiàn)手冊(cè),例:

AssetBundle 1 中的 Material A 依賴(lài)于 AssetBundle 2 中的 Texture B撒会,若要正常加載嘹朗,與 AssetBundle 1 和 2 的加載順序無(wú)關(guān),但一定要保證加載 Material A 時(shí)诵肛,AssetBundle 2 已加載

在構(gòu)建 AssetBundle 時(shí)屹培,Unity 創(chuàng)建一個(gè)包含每一個(gè) AssetBundle 依賴(lài)信息的類(lèi)型為 AssetBundleManifest 的序列化對(duì)象,該文件存在一個(gè)與其他 AssetBundle 在同一打包路徑下的單獨(dú)的 AssetBundle 中怔檩,且與父層文件夾名相同

有兩種 API 查詢(xún)依賴(lài)

  • AssetBundleManifest.GetAllDependencies 獲取 AssetBundle 的所有依賴(lài)層級(jí)
  • AssetBundleManifest.GetDirectDependencies 獲取 AssetBundle 直接依賴(lài)

因該 API 會(huì)生成字符串?dāng)?shù)組褪秀,所以應(yīng)盡量少用,且避免性能高峰時(shí)使用

官方建議薛训,大部分場(chǎng)合下媒吗,在進(jìn)入性能需求高的場(chǎng)景前,盡可能多地加載對(duì)象乙埃,尤其對(duì)于移動(dòng)平臺(tái)這種闸英,訪(fǎng)問(wèn)本地存儲(chǔ)慢,加載卸載對(duì)象引起內(nèi)存流失會(huì)觸發(fā)垃圾回收的平臺(tái)

Asset 分包策略

  • 邏輯實(shí)體分包
  • 對(duì)象類(lèi)型分包
  • 并發(fā)內(nèi)容分包
邏輯實(shí)體分包

依據(jù)資源在項(xiàng)目功能塊的使用位置介袜,如 UI甫何、角色、環(huán)境和其他在生命周期中常出現(xiàn)的內(nèi)容等分包

  • 將所有 UI 的紋理和布局?jǐn)?shù)據(jù)分包
  • 將角色的模型和動(dòng)畫(huà)數(shù)據(jù)分包
  • 將多場(chǎng)景共用的紋理和模型分包

該分包方式適用于制作 DLC遇伞,可以只下載單個(gè)實(shí)體而無(wú)需下載無(wú)變化的資源辙喂,其關(guān)鍵點(diǎn)在于需要開(kāi)發(fā)者清楚了解每個(gè)打包的資源所要用到的時(shí)機(jī)和位置

對(duì)象類(lèi)型分包

該方式適用于針對(duì)多平臺(tái)分包,例如音頻文件的壓縮設(shè)置在 Windows 和 Mac OS 平臺(tái)一樣鸠珠,另外由于紋理壓縮格式和設(shè)置等改變頻率遠(yuǎn)低于腳本和預(yù)設(shè)體巍耗,使用該分配方式可以使 AssetBundle 兼容更多的 Unity 版本

并發(fā)內(nèi)容分包

并發(fā)內(nèi)容分包可理解為以關(guān)卡為分組依據(jù),將一個(gè)關(guān)卡內(nèi)獨(dú)有的角色跳芳、紋理芍锦、音樂(lè)等需要在同一時(shí)機(jī)加載的內(nèi)容分為一包

Tips
  • 將常更新與不常更新內(nèi)容分開(kāi)
  • 將需要同時(shí)加載的對(duì)象分為一組,如一個(gè)模型飞盆,其所需的材質(zhì)和動(dòng)畫(huà)分為一組
  • 若多個(gè) AssetBundle 中的多個(gè)對(duì)象引用了其他 AssetBundle 中的單個(gè) Asset娄琉,則將依賴(lài)項(xiàng)分離到單獨(dú)的包中以減少重復(fù)
  • 確保兩組完全不可能同時(shí)加載的對(duì)象不在用一包中次乓,如低清和高清材質(zhì)包
  • 若一個(gè)包中只有低于一半的對(duì)象被頻繁加載,可將其拆分
  • 將一些同時(shí)加載的小包(資源少于5到10個(gè))合并
  • 若一個(gè)包中的對(duì)象僅是版本不同孽水,則可以使用 AssetBundle 變體

Addressable

Addressable 系統(tǒng)為 Unity 新推出的資源管理系統(tǒng)票腰,整合了 Unity 直接引用,Resources 和 AssetBundle 全部三種資源加載方式女气。通過(guò)可尋址資產(chǎn)的方式杏慰,便捷地實(shí)現(xiàn)了內(nèi)容包的創(chuàng)建和部署。Addressable 系統(tǒng)使用異步加載的方式實(shí)現(xiàn)從任何位置加載任何依賴(lài)項(xiàng)炼鞠,使得任何引用方式都更加便捷動(dòng)態(tài)化

注意:需Unity 2018.3 及其以后版本

Addressable 優(yōu)勢(shì)
  • 縮減迭代周期缘滥,無(wú)需修改代碼優(yōu)化內(nèi)容
  • 自動(dòng)依賴(lài)管理,將請(qǐng)求內(nèi)容的依賴(lài)項(xiàng)一同加載
  • 自動(dòng)內(nèi)存管理谒主,對(duì)管理資源自動(dòng)引用計(jì)數(shù)
  • 內(nèi)容打包朝扼,負(fù)責(zé)構(gòu)建和解析引用鏈,在將資源移動(dòng)或重命名的情況下霎肯,依然可實(shí)現(xiàn)本地和遠(yuǎn)端部署
  • 配置文件擎颖,可配置多個(gè)配置文件,實(shí)現(xiàn)快速切換
Addressable 概念

Addressable 由兩個(gè)包組成观游,Addressable Assets package(主要功能) 和 Scriptable Build Pipeline package(依賴(lài)項(xiàng))

  • Address:資源的地址標(biāo)記搂捧,用于運(yùn)行時(shí)查詢(xún)
  • AddressableAssetData:在項(xiàng)目 Assets 目錄下用于存儲(chǔ) Addressable 資源的文件目錄
  • Asset group:構(gòu)建時(shí)處理的 Addressable 資產(chǎn)組
  • Asset group schema:數(shù)據(jù)構(gòu)建時(shí)的配置
  • AssetReference:可根據(jù)需求延遲初始化的直接引用對(duì)象
  • Asynchronous loading:開(kāi)發(fā)過(guò)程中無(wú)需更改代碼也可修改資產(chǎn)位置和依賴(lài)項(xiàng)
  • Build script:打包資產(chǎn),將 Address 和 Resources 映射
  • Label:為運(yùn)行時(shí)加載相似項(xiàng)目提供額外的 Addressable Asset 標(biāo)志
Addressable 使用
Addressable 安裝
  1. 打開(kāi)頂部工具欄 Window -> Package Manager懂缕,找到 Addressables允跑,點(diǎn)擊安裝即可

    打開(kāi)Pacakage Manager
    安裝 Addressable
  2. 安裝完成后 Addressable 的主要功能都可在頂部工具欄 Window -> Asset Management -> Addressables 中找到

    • Groups:Addressable 分組工具
    • Settings:Addressable 總體設(shè)置
    • Profiles:預(yù)設(shè)構(gòu)建配置管理
    • EventViewer:監(jiān)測(cè)引用計(jì)數(shù)工具
    • Analyze:用于分析打包情況,檢測(cè)重復(fù)等可自定義規(guī)則的分析工具
    • Hosting:模擬服務(wù)器
    打開(kāi) Addressables Group
  3. 打開(kāi)Group提佣,創(chuàng)建新的配置吮蛹,項(xiàng)目 Assets 目錄下會(huì)自動(dòng)創(chuàng)建一個(gè) AddressableAssetData 目錄,無(wú)需直接改動(dòng)該目錄

    image
image
Addressable Group 配置
  1. 在 Addressables Groups 窗口拌屏,右鍵或左上角 create 按鈕即可創(chuàng)建 Group
  2. 選中 Group潮针,在 Inspector 中修改設(shè)置,Group 有三種配置項(xiàng)
    • Content Packing & Loading:打包的構(gòu)建和加載路徑倚喂,以及其他打包相關(guān)設(shè)置
    • Content Update Restriction:包更新限制
    • Resources and Built In Scenes:是否包含 Resources 或構(gòu)建的場(chǎng)景
  3. 添加 Asset 后每篷,構(gòu)建 Addressable Group
    • Addressables Groups 窗口,Build > New Build > Default Build Script
    • 或者使用 API AddressableAssetSettings.BuildPlayerContent()
Addressables Asset 配置和加載
  1. 添加 Addressable Asset

    • 將資源直接拖入 Addressables Groups 窗口下分組內(nèi)即可

    • 或者在 Project 中選擇任何 Asset 端圈,在 Inspector 下都可見(jiàn)名為 Addressable 的勾選框焦读,勾選即可將該 Asset,可更改其 Addressable 名稱(chēng)舱权,此時(shí)該 Asset 就被添加到默認(rèn)的 Addressables Group 中了

      image
  2. (可選) 更改資源名矗晃,為資源添加 Label

  3. 加載 Addressable Asset

    • Addressables.LoadAssetAsync<T>(string) 異步加載資源對(duì)象
    • Addressables.InstantiateAsync(string) 場(chǎng)景中創(chuàng)建對(duì)象
    • 或添加 AssetReference成員變量,在 Inspector 可選擇 AssetReference 引用的資源對(duì)象
    public class AddressablesExample : MonoBehaviour {
        GameObject myGameObject;
            ...
            Addressables.LoadAssetAsync<GameObject>("AssetAddress").Completed += OnLoadDone;
        }
    
        private void OnLoadDone(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<GameObject> obj)
        {
            // In a production environment, you should add exception handling to catch scenarios such as a null result.
            myGameObject = obj.Result;
        }
    }
    

參考

Unity讀取內(nèi)部宴倍、外部資源詳解

Unity資源管理

The Addressable Asset System 正式版應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末张症,一起剝皮案震驚了整個(gè)濱河市仓技,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俗他,老刑警劉巖脖捻,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異兆衅,居然都是意外死亡地沮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)羡亩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)摩疑,“玉大人,你說(shuō)我怎么就攤上這事夕春∥椿模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵及志,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我寨腔,道長(zhǎng)速侈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任迫卢,我火速辦了婚禮倚搬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乾蛤。我一直安慰自己每界,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布家卖。 她就那樣靜靜地躺著眨层,像睡著了一般。 火紅的嫁衣襯著肌膚如雪上荡。 梳的紋絲不亂的頭發(fā)上趴樱,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音酪捡,去河邊找鬼叁征。 笑死,一個(gè)胖子當(dāng)著我的面吹牛逛薇,可吹牛的內(nèi)容都是我干的捺疼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼永罚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼啤呼!你這毒婦竟也來(lái)了卧秘?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤媳友,失蹤者是張志新(化名)和其女友劉穎斯议,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體醇锚,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哼御,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了焊唬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恋昼。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赶促,靈堂內(nèi)的尸體忽然破棺而出液肌,到底是詐尸還是另有隱情,我是刑警寧澤鸥滨,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布嗦哆,位于F島的核電站,受9級(jí)特大地震影響婿滓,放射性物質(zhì)發(fā)生泄漏老速。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一凸主、第九天 我趴在偏房一處隱蔽的房頂上張望橘券。 院中可真熱鬧,春花似錦卿吐、人聲如沸旁舰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)箭窜。三九已至,卻和暖如春谨湘,著一層夾襖步出監(jiān)牢的瞬間绽快,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工紧阔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坊罢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓擅耽,卻偏偏與公主長(zhǎng)得像活孩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乖仇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345