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

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

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

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

資源路徑

Application.dataPath

官方文檔

只讀,Editor 可讀寫

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

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

Application.persistentDataPath

官方文檔

可讀寫,用于持久化數(shù)據(jù)存儲,在 iOS 和 Android 平臺該路徑指向設(shè)備的公共路徑,該目錄不會隨 App 升級而刪除,但可被用戶直接刪除

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

iOS 會自動將 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ī)型該路徑會指向 SD 卡
  • Mac: ~/Library/Application Support/<company name>/<product name> ,舊版本還可能為 ~/Library/Caches~/Library/Application Support/unity.company name.product name,Unity 會查詢并使用以上路徑中最早的路徑

Application.streamingAssetsPath

官方文檔 官方手冊

只讀,Editor 可讀寫

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

StreamingAssets中資源可使用 I/O 讀取,但 WebGL 和 Android 平臺下該路徑為 URL,不支持直接獲取,因此需使用 UnityWebRequest獲取。若其他平臺使用 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

可讀寫,臨時(shí)數(shù)據(jù)和緩存路徑,應(yīng)用更新或覆蓋安裝時(shí)不會被清除,手機(jī)空間不足時(shí)才可能會被系統(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

讀寫權(quán)限說明

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

資源加載

推薦官方教程

AssetDataBase

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

Resources

接口文檔

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

Resources 最佳實(shí)踐

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

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

適合使用 Resources 的場景:

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

Resources 序列化

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

對于大部分平臺,查找樹為時(shí)間復(fù)雜度為 O(n log(n)) 的平衡查找樹,隨著 Resources 中對象的增加,索引加載時(shí)間增長速度將超過線形增長速度

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

接口 說明
FindObjectsOfTypeAll 獲取所有指定類型的對象
Load 加載 Resources 指定目錄下的 Asset
LoadAll 加載 Resources 指定目錄下的所有 Asset
LoadAsync 異步加載 Resources 指定目錄下的 Asset
UnloadAsset 將 asset 從內(nèi)存釋放,重新加載 Asset 不會使之前的引用重新鏈接
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

官方手冊 接口文檔

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

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

AssetBundle 構(gòu)建

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

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

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

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

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

AssetBundle 派發(fā)方式

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

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

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

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

Unity 內(nèi)置的 AssetBundle 緩存系統(tǒng)用于緩存 UnityWebRequestAssetBundle.GetAssetBundle下載的包,緩存僅以名稱作為唯一標(biāo)識。另外可通過重載方法可傳入版本號(開發(fā)者自己管理版本號),緩存系統(tǒng)會比對版本號,選擇匹配版本或下載新包

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

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 的行為隨壓縮算法和平臺而不同

  • 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

    該方法可高效地從硬盤加載未壓縮或 LZ4 壓縮的 Assetbundle,加載 LZMA 壓縮包時(shí)會先解壓再加載到內(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)建請求,再將請求傳入DownloadHandlerAssetBundle.GetContent(UnityWebRequest),下載完成后可像AssetBundle.LoadFromFile 一樣,直接使用 assetBundle 對象

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

    LZMA 壓縮包會在下載時(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 在速度、磁盤使用和運(yùn)行時(shí)內(nèi)存使用方面都最高效;需要下載則使用 UnityWebRequest

AssetBundle Asset 加載

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

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

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

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

其他情況均用LoadAsset (LoadAssetAsync)

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

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

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

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

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

AssetBundle 依賴

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

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

Unity 不會自動加載子 AssetBundle,具體可詳見手冊,例:

AssetBundle 1 中的 Material A 依賴于 AssetBundle 2 中的 Texture B,若要正常加載,與 AssetBundle 1 和 2 的加載順序無關(guān),但一定要保證加載 Material A 時(shí),AssetBundle 2 已加載

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

有兩種 API 查詢依賴

  • AssetBundleManifest.GetAllDependencies 獲取 AssetBundle 的所有依賴層級
  • AssetBundleManifest.GetDirectDependencies 獲取 AssetBundle 直接依賴

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

官方建議,大部分場合下,在進(jìn)入性能需求高的場景前,盡可能多地加載對象,尤其對于移動平臺這種,訪問本地存儲慢,加載卸載對象引起內(nèi)存流失會觸發(fā)垃圾回收的平臺

Asset 分包策略

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

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

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

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

對象類型分包

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

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

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

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

Addressable

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

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

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

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

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

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

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

    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)建的場景
  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 下都可見名為 Addressable 的勾選框,勾選即可將該 Asset,可更改其 Addressable 名稱,此時(shí)該 Asset 就被添加到默認(rèn)的 Addressables Group 中了

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

  3. 加載 Addressable Asset

    • Addressables.LoadAssetAsync<T>(string) 異步加載資源對象
    • Addressables.InstantiateAsync(string) 場景中創(chuàng)建對象
    • 或添加 AssetReference成員變量,在 Inspector 可選擇 AssetReference 引用的資源對象
    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)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。