簡(jiǎn)介
Unity可尋址資源系統(tǒng)
可尋址資源系統(tǒng)提供了一種簡(jiǎn)單的方法通過“地址”加載資源呻引。簡(jiǎn)化資源包的創(chuàng)建和部署的管理開銷勒奇。
可尋址資源系統(tǒng)允許你從任何地方通過異步加載的方式加載資源包产徊。無論你是通過"直接引用",或者傳統(tǒng)的Assetbundle形式员串,亦或是通過"Resource"文件夾管理,可尋址資源系統(tǒng)提供了一種簡(jiǎn)單的方法來使你的游戲更加靈活多變盔腔。
什么是一個(gè)資源(Asset)
Asset資源是你用來創(chuàng)建游戲或應(yīng)用程序的內(nèi)容喷屋。 資產(chǎn)的常見例子包括預(yù)制件Prefabs琳拨、紋理Textures、材質(zhì)Materials屯曹、音頻剪輯AudioClips和動(dòng)畫Animations狱庇。
什么是一個(gè)可尋址的資源
一個(gè)被做成可尋址的資源,可以從任何地方通過"唯一地址"取訪問它,無論它是打包駐留在本地的資源,還是發(fā)布到遠(yuǎn)程服務(wù)器上的資源,可尋址資源系統(tǒng)都可以定位并返回它,你可以通過地址加載單個(gè)可尋址資源,或者通過自定義的組標(biāo)簽加載多個(gè)可尋址資源
為什么要使用可尋址資源
傳統(tǒng)的游戲資源的結(jié)構(gòu),使得有效加載是一個(gè)非常具有挑戰(zhàn)性的事情.但是可尋址資源系統(tǒng)可以大幅縮短迭代周期,讓你節(jié)省大量的時(shí)間取用于設(shè)計(jì),編碼,和測(cè)試你的應(yīng)用
- 迭代時(shí)間: 按地址引用內(nèi)容是非常有效的,優(yōu)化內(nèi)容將不再需要更改代碼。
- 依賴項(xiàng)管理: 當(dāng)你請(qǐng)求一個(gè)內(nèi)容時(shí),系統(tǒng)會(huì)自動(dòng)返回所請(qǐng)求內(nèi)容的所有依賴項(xiàng),在將內(nèi)容返回給您之前先加載所有網(wǎng)格恶耽、著色器密任、動(dòng)畫等等。
- 內(nèi)存管理: 尋址系統(tǒng)能卸載資源也能加載資源,而且會(huì)自動(dòng)計(jì)算引用,并提供一個(gè)強(qiáng)大分析器來幫助您發(fā)現(xiàn)潛在的內(nèi)存問題偷俭。
- 內(nèi)容打包: 系統(tǒng)會(huì)自動(dòng)映射和理清的復(fù)雜的依賴關(guān)系,并進(jìn)行有效的打包浪讳,即使移動(dòng)或重命名資源后也是如此. 您可以很容易地為本地和遠(yuǎn)程部署準(zhǔn)備資源,以支持追加或減少應(yīng)用程序的下載內(nèi)容的大小。
概覽
可尋址資產(chǎn)系統(tǒng)由兩個(gè)包組成(在Package Managed中打開):
- Addressable Assets package (primary package)
- Scriptable Build Pipeline package (dependency)
當(dāng)您安裝Addressable Assets package涌萤,Scriptable Build Pipeline package將同時(shí)安裝淹遵。
常見概念
-
Address
: 運(yùn)行時(shí)檢索資源位置的標(biāo)識(shí)符 -
AddressableAssetData directory
: 存儲(chǔ)您的可尋址資源元數(shù)據(jù)在項(xiàng)目的資產(chǎn)目錄 -
Asset group
: 資源組,可用于構(gòu)建時(shí)處理一組可尋址資產(chǎn) -
Asset group schema
: 定義一組數(shù)據(jù)可以分配到一個(gè)組,在生成過程中使用 -
AssetReference
: 這個(gè)做法就像是一個(gè)直接引用的對(duì)象(類似傳統(tǒng)的拖拽到面板上綁定)负溪,但會(huì)延遲初始化透揣。該AssetReference對(duì)象存儲(chǔ)GUID作為尋址,可以按需加載笙以。 -
Asynchronous loading
: 異步加載,允許在整個(gè)應(yīng)用過程中中定位資源及其依賴的位置,而且是在不改變游戲代碼的前提下淌实。異步加載是尋址資產(chǎn)系統(tǒng)的基礎(chǔ). -
Build script
: 構(gòu)建腳本,運(yùn)行資產(chǎn)組處理器進(jìn)行資源打包,并對(duì)資源管理器的提供資源的地址和與可尋址標(biāo)識(shí)之間的映射關(guān)系。 -
Label
: 標(biāo)簽,為一個(gè)資源提供額外的可尋址表示符
開始使用
安裝可尋址資源系統(tǒng)的包
重要:可尋址資源系統(tǒng)要求Unity的版本為2018.3及以上
通過Window > Package Manager 打開找到Addressables即可安裝
將一個(gè)資源標(biāo)記為可尋址
Unity中有兩種方式可以將一個(gè)資源標(biāo)記為可尋址的
-
在Inspector監(jiān)視面板中
在Project window項(xiàng)目窗口中,選擇需要標(biāo)記的資源,然后在Inspector面板中,勾選上Address的復(fù)選框,并輸入一個(gè)名稱標(biāo)記該資源
-
在單獨(dú)的可尋址資源管理窗口中標(biāo)記
選擇Window > Asset Management > Addressables打開Addressables窗口拆祈。接下來恨闪,將所需的資產(chǎn)從Project window窗口拖拽到Addressables窗口中的資產(chǎn)組之一。
指定地址
默認(rèn)地址為該資源在你項(xiàng)目中的路徑(例如放坏,Assets/images/myImage.png),若要通過 Addressables window 改變?cè)撡Y源的地址咙咽,用鼠標(biāo)右鍵單擊該資源,并選擇重命名淤年。 當(dāng)你第一次開始使用可尋址的資源钧敞,系統(tǒng)會(huì)保存的一些編輯時(shí)和運(yùn)行時(shí)的數(shù)據(jù)資源在Assets/AddressableAssetsData文件中,該文件應(yīng)該被添加到您的版本控制的允許列表中麸粮。
打包構(gòu)建可尋址內(nèi)容
資源管理系統(tǒng)需要你在使用之前打包構(gòu)建所有的可尋址資源,該步驟不是自動(dòng)的,你可以通過編輯器來構(gòu)建或者通過的API來構(gòu)建
- 通過編輯器構(gòu)建:在Addressables window, 然后選擇 Build > Build Player Content
- 通過API來構(gòu)建:
AddressableAssetSettings.BuildPlayerContent()
使用可尋址資源
通過address加載或者實(shí)例化資源
您可以在運(yùn)行時(shí)加載或?qū)嵗粋€(gè)尋址資源,并加載資源的所有依賴項(xiàng)到內(nèi)存中(包括可用的綁定數(shù)據(jù))溉苛,允許你在需要的時(shí)候使用它,但這不會(huì)直接將其添加到場(chǎng)景中,若要將資源添加到您的場(chǎng)景你還需要instantiate實(shí)例化。但是你也可以直接通過Addressables的Instantiate接口立即加載并實(shí)例化添加到您的場(chǎng)景弄诲。
通過address訪問可尋址資源,需要先應(yīng)用命名空間UnityEngine.AddressableAssets
,然后調(diào)用如下方法:
//這將使用指定的地址加載資產(chǎn)愚战。
Addressables.LoadAssetAsync<GameObject>("AssetAddress");
或者
//這將直接實(shí)例化指定地址的資源并添加到場(chǎng)景中
Addressables.InstantiateAsync("AssetAddress");
Note: LoadAssetAsync
和InstantiateAsync
是異步操作方式. 你可以通過回調(diào)函數(shù)當(dāng)加載完成時(shí)后進(jìn)行后續(xù)的操作 (具體請(qǐng)查看文檔 Async operation handling)
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
using UnityEngine;
public class AddressablesExample : MonoBehaviour {
GameObject myGameObject;
void Start()
{
Addressables.LoadAssetAsync<GameObject>("AddressTest").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;
}
}
子資源和組件
子資源和組件對(duì)資源加載來說是一個(gè)特殊情況
組件 : 你不能通過Addressables直接加載一個(gè)組件,你必須先實(shí)例化一個(gè)GameObject,然后獲取這個(gè)GameObject的組件(通用做法是獲取GameObject后通過GetComponent來獲取),這里我們對(duì)Addressables進(jìn)行了擴(kuò)展以支持組件加載,具體方法參見our ComponentReference sample.
子資源 : 系統(tǒng)支持子資源的加載,但是需要特殊的語法,舉個(gè)潛在的例子,子資源包括,圖集中的大量圖片,或者FBX模型文件中的大量動(dòng)畫片段,如何直接加載這些圖篇,參考 our sprite loading sample
//加載所有的子資源:
Addressables.LoadAssetAsync<IList<Sprite>>("MySpriteSheetAddress");
//加載單個(gè)的子資源
Addressables.LoadAssetAsync<Sprite>("MySpriteSheetAddress[MySpriteName]");
資產(chǎn)中可用的名稱是在主Addressables組編輯器窗口中可見型诚。此外羹与,你可以使用一個(gè)AssetReference訪問資源的子對(duì)象,參考下方
使用AssetReference引用類
AssetReference類提供一種方法來訪問尋址的資源,而且無需知道他們的地址冠摄。要使用AssetReference類訪問一個(gè)可尋址的資源:
- 在你的Scene Hierarchy界面或者Project窗口中選擇一個(gè)資源
- 在Hierarchy中,為其添加組件(Add Component ),組件的類型為任何可序列化的組件都支持AssetReference變量引用(例如梗摇,游戲腳本拓哟、 ScriptableObject 或其他可序列化類)
- 在腳本中增加一個(gè)公開public的AssetReference變量
-
最后在Inspector窗口中,選擇一個(gè)可尋址的資源關(guān)聯(lián)起來,無論是將資源拖拽引用過來,或者是通過下拉菜單從預(yù)定義的可尋址資源中選擇一個(gè),都是可以的
加載或?qū)嵗粋€(gè)AssetRefAsseterence資源,可通過如下方法:
public class Z_Test : MonoBehaviour
{
public AssetReference assetReference;
// Start is called before the first frame update
void Start()
{
assetReference.LoadAssetAsync<GameObject>();
}
}
或者
public class Z_Test : MonoBehaviour
{
public AssetReference assetReference;
// Start is called before the first frame update
void Start()
{
assetReference.InstantiateAsync(這里有2個(gè)重載,自己填參數(shù));
}
}
和一般的資源尋址一樣,LoadAssetAsync
和InstantiateAsync
都是異步操作,你可以提供加載完成時(shí)的回調(diào)
子資源,如果AssetRefAsseterence中包含了子資源,(例如Sprite或FBX),你可以在該資源的Inspector面板中,AssetReference組件上看到多出了一個(gè)下拉框,下拉框中選擇你需要的是,引用資源本身,還是子類資源.第一個(gè)下拉框選擇的是資源本身,第二個(gè)下拉框,如果你選擇"<none>"的話, 那么資源引用還是指向資源該資源本身,此時(shí)可以獲取到所有的子類資源(例如assetReference.LoadAssetAsync<IList<Sprite>>()),但是如果第二個(gè)下拉框你選擇了某一個(gè)子資源,那么AssetRefAsseterence引用僅指向該子資源
構(gòu)建方面需要考慮的因素
在StreamingAssets中的本地?cái)?shù)據(jù)
可尋址資源系統(tǒng)需要一些文件取幫助識(shí)別一個(gè)資源在什么地方以及怎么取加載它,當(dāng)你構(gòu)建Addressables數(shù)據(jù)(即在Addressables窗口中Build Play Content)時(shí),這些文件會(huì)在StreamingAssets文件夾中生成,StreamingAssets是Unity中的一個(gè)特殊文件夾,它包括了所有的資源尋址信息.當(dāng)你構(gòu)建Addressables數(shù)據(jù)時(shí)候,系統(tǒng)級(jí)的文件會(huì)被生成在庫中,然后當(dāng)你構(gòu)建整個(gè)App時(shí),系統(tǒng)會(huì)拷貝這些所需要的文件到StreamingAssets文件夾中,構(gòu)建,然后再從庫中刪除它們,通過這種方式,你可以為多個(gè)平臺(tái)構(gòu)建每個(gè)平臺(tái)各自關(guān)聯(lián)需要的數(shù)據(jù).
除了特定的Addressables數(shù)據(jù),任何為本地使用構(gòu)建數(shù)據(jù)的組也將使用于特定平臺(tái)的位置,為了驗(yàn)證這項(xiàng)工作,去設(shè)置profile配置文件變量中的構(gòu)建路徑和加載路徑分別是[UnityEngine.AddressableAssets.Addressables.BuildPath]
和
{UnityEngine.AddressableAssets.Addressables.RuntimePath}
你可以在AddressableAssetSettings
文件的Inspector面板中指定這些設(shè)置(默認(rèn)情況下,這個(gè)對(duì)象是位于項(xiàng)目的資產(chǎn)/AddressableAssetsData目錄)
預(yù)先下載
通過調(diào)用Addressables.DownloadDependenciesAsync()
方法可以加載指定的address或label的依賴資源,通常情況下,這是一個(gè)assetbundle
通過AsyncOperationHandle
的句柄和可以獲取PercentComplete
屬性來幫助監(jiān)視和顯示當(dāng)前的下載進(jìn)度,你可以讓應(yīng)用等待直到所有內(nèi)容加載完畢
如果你想征求用戶同意后再下載,那么需要先獲取到下載資源的大小告訴用戶,通過
Addressables.GetDownloadSize()
返回需要下載內(nèi)容的大小
注意:這需要考慮到之前下載的bundles是否仍然有緩存
雖然提前為應(yīng)用程序下載資源是有利的伶授,但在某些情況下断序,您可能會(huì)選擇不這樣做。 例如:
- 如果你的應(yīng)用程序有大量的在線內(nèi)容谎砾,你通常希望用戶只與其中的一部分進(jìn)行交互逢倍。
- 你有一個(gè)應(yīng)用程序必須連網(wǎng)下載,如果你的應(yīng)用程序的所有內(nèi)容都是小的bundle,你可以根據(jù)需要選擇下載,即按需下載
您可以使用預(yù)加載功能來顯示下載已經(jīng)啟動(dòng)捧颅,然后繼續(xù)景图,而不是使用完成百分比值等待內(nèi)容加載。 此實(shí)現(xiàn)將需要一個(gè)'加載或等待的屏幕'(即UI或交互效果)來處理資源仍在加載時(shí)的等待情況
為多平臺(tái)構(gòu)建
可尋址資源系統(tǒng)在你構(gòu)建可尋址資源內(nèi)容時(shí),其資源是依賴于平臺(tái)的,因而你必須為你每個(gè)需要支持的平臺(tái)進(jìn)行重新構(gòu)建
默認(rèn)情況下碉哑,建立Addressables應(yīng)用數(shù)據(jù)時(shí)挚币,您指定平臺(tái)的數(shù)據(jù)存儲(chǔ)在Addressables的特定平臺(tái)的目錄構(gòu)建路徑中.
運(yùn)行時(shí)路徑負(fù)責(zé)處理這些平臺(tái)文件夾指向適用的應(yīng)用程序數(shù)據(jù)。
注意:當(dāng)你在編輯器模式下使用Addressables BuildScriptPackedPlayMode
,Addressables 將嘗試加載數(shù)據(jù)到你當(dāng)前選中的編輯器平臺(tái)(win或ios或mac等等).因此,如果你當(dāng)前構(gòu)建的目標(biāo)數(shù)據(jù)不是您當(dāng)前編輯器平臺(tái),那么兼容性可能會(huì)出現(xiàn)問題.要了解更多詳細(xì)信息,參考 Play mode scripts.
可尋址資源的開發(fā)周期
可尋址資源系統(tǒng)最重要的優(yōu)點(diǎn)之一就是將 準(zhǔn)備內(nèi)容 構(gòu)建內(nèi)容 和加載內(nèi)容 的關(guān)聯(lián)進(jìn)行解耦,事實(shí)上,在之前它們是緊密聯(lián)系在一起的
傳統(tǒng)的資源管理器
如果你之前是使用 Resources
文件夾來存放資源的,那么它揮別內(nèi)置到應(yīng)用程序中,你必須通過Resources.Load的方式來加載內(nèi)容,需要提供路徑的資源.如果資源存放在別處,你會(huì)使用直接應(yīng)用
或者AssetBundle
來加載,如果你使用AssetBundle
,你需要再次進(jìn)行路徑,打包以及組織加載策略,如果AssetBundle
在遠(yuǎn)程服務(wù)器上,或者對(duì)其他的bundle具有依賴性,那么你必須通過寫代碼來管理下載,加載和卸載所有的Bundles
可尋址資源管理器
給資源一個(gè)'address'名稱作為尋址方式,你就可以使用該地址來加載他,不管它在你的項(xiàng)目中是如何構(gòu)建的,即使你更改這個(gè)資源的路徑名或者文件名都不會(huì)出現(xiàn)問題,你還可以從Resources
文件夾中移動(dòng)該資源或者從構(gòu)建路徑,或者一些其他的生成位置(包括遠(yuǎn)程的),而不用去改變你的加載代碼
資源組模式(Asset group schemas)
模式定義了一組數(shù)據(jù),你可以增加模式到資源組中,附加到組的模式可以定義如何構(gòu)建改組中的內(nèi)容.舉個(gè)例子,當(dāng)你構(gòu)建打包模式時(shí),將附加有BundledAssetGroupSchema
模式的組用作資產(chǎn)的源,您可以將模式集組合到用于定義新組的模板中
你也可以通過AddressableAssetsSettings
添加資源組模式
構(gòu)建腳本
構(gòu)建腳本是一個(gè)繼承了[IDataBuilder
] 接口的[ScriptableObject
]可編輯腳本資源.
用戶可以自己創(chuàng)建構(gòu)建腳本然后在AddressableAssetSettings
的Inspector面板中添加它們.
通過Addressables窗口,即(Window > AssetManagement > Addressables)中選擇Play Mode Script,然后選擇下拉選項(xiàng),當(dāng)前扣典,已實(shí)現(xiàn)三個(gè)腳本來支持完整的應(yīng)用程序構(gòu)建妆毕,并提供三個(gè)用于在編輯器中進(jìn)行迭代的播放模式腳本。
播放模式腳本
Addressable Assets Package默認(rèn)自帶了三個(gè)構(gòu)建腳本贮尖,這些腳本創(chuàng)建播放模式數(shù)據(jù)以幫助您加速應(yīng)用程序開發(fā)笛粘。
Fast mode
快速模式(BuildScriptFastMode)使您可以在游戲流程中快速運(yùn)行游戲。快速模式直接通過資產(chǎn)數(shù)據(jù)庫加載資產(chǎn)薪前,無需分析或創(chuàng)建AssetBundle即可進(jìn)行快速迭代润努。Virtual mode
虛擬模式(BuildScriptVirtualMode)可以分析內(nèi)容的布局和依賴性,而無需創(chuàng)建AssetBundle示括。資源通過ResourceManager
從資源數(shù)據(jù)庫加載铺浇,就好像它們是通過Bundles加載一樣。查看游戲過程中Bundles何時(shí)加載或卸載,通過Addressable Profiler window(Window > Asset Management > Addressable Profiler)
虛擬模式可幫助您模擬負(fù)載策略并調(diào)整內(nèi)容組以找到生產(chǎn)版本的適當(dāng)平衡垛膝。Packed Play mode
打包播放模式(BuildScriptPackedPlayMode)使用已構(gòu)建的Bundles鳍侣。此模式與已部署的應(yīng)用程序構(gòu)建最匹配,但是需要你進(jìn)行一步單獨(dú)的數(shù)據(jù)構(gòu)建過程.如果你不修改資源,則此模式是最快的,因?yàn)樗谶M(jìn)入"Play"模式時(shí)是不會(huì)處理任何數(shù)據(jù)的,你必須通過Addressables window (Window > Asset Management > Addressables) 然后選擇Build > Build Player Content,或者可以使用如下代碼進(jìn)行代碼打包:
AddressableAssetSettings.BuildPlayerContent()
選擇編譯腳本
要改變播放模式腳本,請(qǐng)通過Addressables window (Window > Asset Management > Addressables) ,選擇Play Mode Script的下拉框來選擇,在開發(fā)和部署期間,每種模式都有特定的使用時(shí)間和地點(diǎn)吼拥。下表說明了開發(fā)周期的各個(gè)階段倚聚,在這些階段中,特定的模式很有用凿可。
分析和調(diào)試
默認(rèn)情況下,可尋址資源只有warnings日志和error錯(cuò)誤日志,你可以開啟更加詳細(xì)的detailed logging,通過Edit > Project Settings > Player,然后到Other Settings > Configuration,增加預(yù)定義宏ADDRESSABLES_LOG_ALL
你可以通過不勾選AddressableAssetSettings
面板中的Log Runtime Exceptions來禁用異常捕捉,你可以通過繼承ResourceManager.ExceptionHandler
屬性實(shí)現(xiàn)自己的異常捕捉機(jī)制,但是這必須在Addressables運(yùn)行時(shí)初始化成功后
初始化
您可以將對(duì)象附加到“可尋址資源”設(shè)置秉沼,然后在運(yùn)行時(shí)進(jìn)行初始化過程。
CacheInitializationSettings
對(duì)象控制Unity在運(yùn)行時(shí)的緩存API,創(chuàng)建自己的初始化對(duì)象,創(chuàng)建一個(gè)可編程對(duì)象ScriptableObject 繼承 IObjectInitializationDataProvider
接口,這是系統(tǒng)的編輯器組件矿酵,負(fù)責(zé)創(chuàng)建ObjectInitializationData
在運(yùn)行時(shí)序列化數(shù)據(jù)
內(nèi)容更新工作流
Unity建議將游戲內(nèi)容分為兩類:
- Static靜態(tài)內(nèi)容,你可以不用考慮更新
- Dynamic動(dòng)態(tài)內(nèi)容,你期望更新的內(nèi)容
在這種結(jié)構(gòu)中唬复,靜態(tài)內(nèi)容隨應(yīng)用程序一起提供(或在安裝后立即下載),并且駐留在很少的Bundles。動(dòng)態(tài)內(nèi)容駐留在線上服務(wù)器全肮,最好放在較小的包中敞咧,以最大程度地減少每次更新所需的數(shù)據(jù)量」枷伲可尋址資源系統(tǒng)的目標(biāo)之一是使這種結(jié)構(gòu)易于使用和修改休建,而無需更改腳本。
但是评疗,"可尋址資源系統(tǒng)"也允許適當(dāng)?shù)母淖兒驼{(diào)整"Static"內(nèi)容,當(dāng)你不想要發(fā)布整個(gè)新的應(yīng)用構(gòu)建時(shí)测砂。
它是怎樣工作的
Addressables 使用內(nèi)容目錄將地址映射到每個(gè)資產(chǎn),以及指定從什么地方加載它,為了提供修改映射的支持,你的原始應(yīng)用必須知道該目錄的在線副本,需要打開這個(gè),在AddressableAssetSettings
的inspector的面板中打開Build Remote Catalog選項(xiàng),這可以確保從指定的路徑拷貝和加載該目錄副本,應(yīng)用發(fā)布后,此加載路徑就無法更改。內(nèi)容更新過程將創(chuàng)建目錄的新版本(具有相同的文件名),以覆蓋先前指定的加載路徑上的文件百匆。
構(gòu)建應(yīng)用程序會(huì)生成一個(gè)唯一的應(yīng)用程序內(nèi)容版本字符串砌些,該字符串標(biāo)識(shí)每個(gè)應(yīng)用程序應(yīng)加載的內(nèi)容目錄。給定的服務(wù)器可以包含應(yīng)用程序多個(gè)版本的目錄加匈,而不會(huì)發(fā)生沖突存璃。我們將所需的數(shù)據(jù)存儲(chǔ)在addressables_content_state.bin文件中。包括版本字符串雕拼,以及標(biāo)記為StaticContent的組中包含的任何資產(chǎn)的哈希信息纵东。默認(rèn)情況下,此文件與AddressableAssetSettings.asset文件位于同一文件夾中啥寇。
addressables_content_state.bin文件包含Addressables系統(tǒng)中每個(gè)StaticContent資源組的哈希和依賴項(xiàng)信息偎球。構(gòu)建到StreamingAssets文件夾的所有組都應(yīng)標(biāo)記為StaticContent洒扎,盡管大型遠(yuǎn)程組也可以從該名稱中受益。在下一步(準(zhǔn)備進(jìn)行內(nèi)容更新)期間衰絮,此哈希信息確定任何StaticContent組是否包含已更改的資源逊笆,以及是否需要將這些資產(chǎn)移至其他位置。
準(zhǔn)備更新內(nèi)容
如果您在任何 StaticContent 組中修改了資源岂傲,則需要運(yùn)行 Prepare For Content Update 命令难裆。 這將把任何已修改的資產(chǎn)從靜態(tài)組中移出,并將它們移動(dòng)到新組中镊掖。 產(chǎn)生新的資源組合:
- 打開Addressables window (Window > Asset Management > Addressables)
- 在Addressables window窗口中,選擇Build菜單,然后選擇Prepare For Content Update
- 在Build Data File對(duì)話框打開時(shí),選擇addressables_content_state.bin文件 (默認(rèn)情況下,位置在Assets/AddressableAssetsData)
此數(shù)據(jù)用于確定自上次構(gòu)建應(yīng)用程序以來已修改了哪些資產(chǎn)或依賴項(xiàng)乃戈。系統(tǒng)將這些資產(chǎn)移至新的組,以準(zhǔn)備內(nèi)容更新構(gòu)建亩进。
注意:如果所有更改都限于非靜態(tài)組症虑,則此命令將不執(zhí)行任何操作。
重要信息:在運(yùn)行準(zhǔn)備操作之前归薛,Unity建議分支您的版本控制系統(tǒng)谍憔。準(zhǔn)備操作以適合于更新內(nèi)容的方式重新排列資產(chǎn)組。分支機(jī)構(gòu)確保下次發(fā)送新播放器時(shí)主籍,您可以返回到首選的內(nèi)容安排习贫。
用于內(nèi)容更新的構(gòu)建
- 打開Addressables window (Window > Asset Management > Addressables)
- 在Addressables window窗口中,選擇Build菜單,然后選擇Build For Content Update
- 在Build Data File對(duì)話框打開時(shí),選擇Build文件夾下已經(jīng)存在需要被當(dāng)前替換的應(yīng)用構(gòu)建文件,構(gòu)建文件夾中必須包含 addressables_content_state.bin 文件
構(gòu)建生成內(nèi)容目錄時(shí),會(huì)有一個(gè)hash文件和assetbundles
生成的內(nèi)容目錄與所選應(yīng)用程序構(gòu)建中的目錄名稱相同,將覆蓋舊的目錄和哈希文件千元。應(yīng)用程序加載哈希文件以確定是否有新的目錄可用苫昌。系統(tǒng)從應(yīng)用程序附帶的或已經(jīng)下載的現(xiàn)有捆綁包中加載未修改的資源
系統(tǒng)通過使用addressables_content_state.bin文件中的內(nèi)容版本信息和位置信息去創(chuàng)建AssetBundles,不包含更新的Assetbundle則與之前的同名,不發(fā)生變化,如果Assetbundle包含更新的內(nèi)容,則生成包含更新內(nèi)容的新Assetbundle,使用一個(gè)新的文件,以便它可以與原來的文件共存,新文件名的Assetbundle必須復(fù)制到承載內(nèi)容的位置(新的內(nèi)容追加到老文件的承載位置)
系統(tǒng)還為靜態(tài)內(nèi)容構(gòu)建資源包幸海,但是你不需要將它們上傳到內(nèi)容托管位置祟身,因?yàn)闆]有 Addressables 資源引用它們。
內(nèi)容更新例子
在這個(gè)例子中物独,一個(gè)已發(fā)布的應(yīng)用程序知道以下組:
由于這個(gè)版本是實(shí)時(shí)的袜硫,有些玩家在他們的設(shè)備上有 Local static,并且有可能在本地緩存這兩個(gè)遠(yuǎn)程捆綁包中的一個(gè)或者兩個(gè)挡篓。
如果你修改了每個(gè)組中的一個(gè)資產(chǎn)(AssetA婉陷,AssetL 和 AssetX) ,然后運(yùn)行Prepare For Content Update瞻凤,在本地 Addressable 設(shè)置中的結(jié)果現(xiàn)在是:
請(qǐng)注意憨攒,prepare 操作實(shí)際上編輯了靜態(tài)組世杀,這可能看起來有悖直覺阀参。 但是,關(guān)鍵是系統(tǒng)構(gòu)建了上面的布局瞻坝,但是丟棄了任何靜態(tài)組的構(gòu)建結(jié)果蛛壳。 因此杏瞻,從玩家的角度來看,你最終會(huì)得到以下結(jié)果:
Local_Static
已經(jīng)在播放器設(shè)備上衙荐,不能更改捞挥。 這個(gè)舊版本的 AssetA 不再被引用。 相反忧吟,它被作為死數(shù)據(jù)粘在播放器設(shè)備上砌函。
Remote_Static
沒有改變。 如果它還沒有緩存在播放器的設(shè)備上溜族,它會(huì)在請(qǐng)求 AssetM 或 AssetN 時(shí)下載讹俊。 像 AssetA 一樣,這個(gè)舊版本的 AssetL 不再被引用煌抒。
Remotenonstatic
包現(xiàn)在已經(jīng)舊了仍劈。 你可以從服務(wù)器上刪除它,但是無論如何寡壮,從現(xiàn)在開始它都不會(huì)被下載贩疙。 如果被緩存,它最終會(huì)離開緩存况既。 像 AssetA 和 AssetL 一樣这溅,這個(gè)舊版本的 AssetX 不再被引用。
舊的 Remote nonstatic
包被替換為新版本棒仍,其特征是它的散列文件芍躏。 Assetx 的修改版本使用這個(gè)新包進(jìn)行更新。
content_update_group
由接下來的過程中修改過的引用資產(chǎn)組成降狠。
請(qǐng)注意对竣,上面的例子有以下含義:
- 任何已更改的本地資產(chǎn)將永遠(yuǎn)不會(huì)在用戶的設(shè)備上使用。
- 如果用戶已經(jīng)緩存了一個(gè)
nonstatic
非靜態(tài)包榜配,那么他們將需要重新下載該包否纬,包括未更改的資產(chǎn)(例如,在這個(gè)實(shí)例中蛋褥,AssetY
和AssetZ
)临燃。 理想情況下,用戶沒有緩存包烙心,在這種情況下膜廊,他們只需要下載新的Remote nonstatic
包。 - 如果用戶已經(jīng)緩存了
Remote Static
遠(yuǎn)程靜態(tài)包淫茵,那么他們只需要下載更新的資產(chǎn)(在這個(gè)實(shí)例中爪瓜,是content update group
中的AssetL
)。 在這種情況下匙瘪,這是理想的铆铆。 如果用戶沒有緩存該捆綁包蝶缀,他們必須通過content update group
下載新AssetL
,以及通過未觸及的Remote static
捆綁包下載現(xiàn)已失效的AssetL
薄货。 無論初始緩存狀態(tài)如何翁都,在某個(gè)時(shí)刻,用戶的設(shè)備上都會(huì)有不存在的AssetL
谅猾,盡管它從未被訪問過柄慰,但它會(huì)無限期地緩存下去
資源的主機(jī)服務(wù)
概覽
資源主機(jī)服務(wù)是通過Unity Editor環(huán)境為可尋址資源配置資源打包到本地或者遠(yuǎn)程服務(wù)器的綜合服務(wù),當(dāng)測(cè)試打包的內(nèi)容時(shí),資源的主機(jī)服務(wù)的設(shè)計(jì)目的是為了提高迭代速度,也可以用來向本地和遠(yuǎn)程網(wǎng)絡(luò)連接的客戶端提供內(nèi)容税娜。
打包模式測(cè)試和迭代
從編輯播放模式測(cè)試轉(zhuǎn)移到平臺(tái)應(yīng)用程序構(gòu)建測(cè)試給開發(fā)過程帶來了復(fù)雜性和時(shí)間成本,主機(jī)服務(wù)提供可擴(kuò)展的編輯器內(nèi)嵌的內(nèi)容傳遞服務(wù)先煎,這些服務(wù)直接映射到 Addressables 組配置,使用自定義 Addressables 配置文件,您可以快速配置應(yīng)用程序巧涧,從 Unity 編輯器本身加載所有內(nèi)容薯蝎。這包括部署和構(gòu)建到移動(dòng)設(shè)備或任何其他平臺(tái),這些移動(dòng)設(shè)備或平臺(tái)具有對(duì)開發(fā)系統(tǒng)的網(wǎng)絡(luò)訪問權(quán)限谤绳。
Turn-Key(打開,配置) 內(nèi)容服務(wù)
您可以將 Asset Hosting Services 部署到服務(wù)器環(huán)境中占锯,方法是以批處理模式(headless)運(yùn)行,為面向內(nèi)部網(wǎng)和因特網(wǎng)的 Unity 應(yīng)用程序客戶機(jī)托管內(nèi)容缩筛。
配置
本文詳細(xì)介紹了項(xiàng)目資產(chǎn)托管服務(wù)的初始設(shè)置消略。 雖然安裝指南側(cè)重于編輯器工作流,但是您可以通過設(shè)置 AddressableAssetSettings
類的 HostingServicesManager
屬性使用 API 來配置托管服務(wù)瞎抛。
配置新的主機(jī)服務(wù)
使用 Hosting window 添加艺演、配置和啟用新的 Hosting 服務(wù)。 在編輯器中桐臊,選擇 Window > Asset Management > Hosting Services胎撤,或者單擊 Addressables window菜單中的 Hosting 按鈕以訪問 Hosting window。
要添加新的托管服務(wù)断凶,請(qǐng)單擊Add Service按鈕伤提。
在出現(xiàn)的Add Service對(duì)話框中,可以選擇預(yù)定義的服務(wù)類型或定義自定義服務(wù)類型认烁。 若要使用預(yù)定義的服務(wù)類型肿男,請(qǐng)從Service Type下拉選項(xiàng)中選擇。 使用Descriptive Name字段為服務(wù)輸入名稱却嗡。
注意: 有關(guān)實(shí)現(xiàn)自定義托管服務(wù)類型的更多信息舶沛,請(qǐng)參見關(guān)于自定義服務(wù)的部分。
新添加的服務(wù)出現(xiàn)在Hosting window 的 Hosting Services 部分窗价,默認(rèn)為禁用狀態(tài)如庭。 要啟動(dòng)服務(wù),請(qǐng)單擊Enable Service按鈕舌镶。
Http 主機(jī)服務(wù)啟動(dòng)時(shí)會(huì)自動(dòng)分配一個(gè)端口號(hào)柱彻。 端口號(hào)在 Unity 會(huì)話之間保存和重用豪娜。 要選擇不同的端口餐胀,可以在 Port 字段中分配特定的端口號(hào)技掏,或者使用 Reset 按鈕隨機(jī)分配不同的端口扼褪。
注意: 如果重置端口號(hào),則必須執(zhí)行完整的應(yīng)用程序構(gòu)建,以生成并嵌入正確的 URL坚芜。
現(xiàn)在已經(jīng)啟用了 HTTP 主機(jī)服務(wù),可以為每個(gè)資產(chǎn)組的 BuildPath
中指定的目錄提供內(nèi)容睹耐。
Profile文件配置
在開發(fā)過程中使用 Hosting Services 時(shí)糊探,Unity 建議創(chuàng)建一個(gè)Profile配置文件,將所有資產(chǎn)組配置為使用專門為此目的創(chuàng)建的目錄或從 Hosting Service 加載內(nèi)容扣汪。
在Addressables window窗口中選擇(Window > Asset Management > Addressables),選擇Profiles > Inspect Profile Settings,您還可以通過 addresssableassetsettings
訪問這些設(shè)置断楷。
接下來,創(chuàng)建一個(gè)新的Profile文件,如下面的例子,將profile的命名為"Editor Hosted"
修改加載路徑字段,改為從主機(jī)服務(wù)加載崭别。 Httphostingservice
是一個(gè)指定服務(wù)器本地 IP 地址和端口的URL冬筒。 在 Hosting 窗口中,您可以使用名為 PrivateIpAddress 和 HostingServicePort 的配置文件變量來構(gòu)造 URL (例如茅主,http: / / [ PrivateIpAddress ] : [ HostingServicePort ])舞痰。
此外,您應(yīng)該修改所有生成路徑變量诀姚,以指向 Project 的 Assets 文件夾外的一個(gè)公共目錄响牛。
驗(yàn)證每個(gè)組的配置是否正確。 確保它們各自的配置文件profile的 BuildPath
和 LoadPath
路徑都被正確設(shè)置 赫段,這些配置文件profile 信息是針對(duì)對(duì)應(yīng)的主機(jī)服務(wù)所作出的修改呀打。 在這個(gè)示例中,您可以看到如何展開 LoadPath
中的配置文件變量糯笙,以構(gòu)建正確的基礎(chǔ) URL聚磺,從而從 Hosted Services 加載。
最后炬丸,從 Addressables window 選擇新的配置文件瘫寝,新建一個(gè)構(gòu)建,并部署到目標(biāo)設(shè)備稠炬。 Unity 編輯器現(xiàn)在通過 HttpHostingService
服務(wù)處理來自應(yīng)用程序的所有加載請(qǐng)求焕阿。 現(xiàn)在不需要重新部署就可以對(duì)內(nèi)容進(jìn)行添加和更改。 重新構(gòu)建可尋址內(nèi)容首启,并重新啟動(dòng)已部署的應(yīng)用程序以刷新內(nèi)容暮屡。
批處理模式
您還可以使用批處理模式從Unity編輯器啟動(dòng)主機(jī)服務(wù)。 要做到這一點(diǎn)毅桃,從命令行啟動(dòng) Unity褒纲,使用以下選項(xiàng):
-batchMode -executeMethod UnityEditor.AddressableAssets.HostingServicesManager.BatchMode
這將從默認(rèn)的addresssableassetsettings
對(duì)象加載 Hosting Services
配置准夷,并啟動(dòng)所有已配置的服務(wù)。
要使用可選的 addresssableassetsettings
配置莺掠,請(qǐng)創(chuàng)建自己的靜態(tài)方法入口點(diǎn)衫嵌,通過
UnityEditor.AddressableAssets.HostingServicesManager.BatchMode(AddressableAssetSettings settings)
重載。
自定義服務(wù)
主機(jī)服務(wù)設(shè)計(jì)為可擴(kuò)展的彻秆,允許您實(shí)現(xiàn)自己的自定義邏輯楔绞,以便從 可尋址資源系統(tǒng) 加載請(qǐng)求服務(wù)內(nèi)容。 例如:
- 支持使用非 http 協(xié)議下載內(nèi)容的自定義 IResourceProvider唇兑。
- 管理一個(gè)外部?jī)?nèi)容服務(wù)進(jìn)程酒朵,提供 CDN 匹配的解決方案(例如 Apache HTTP Server 文檔)。
實(shí)現(xiàn)自定義服務(wù)
Hostingservicesmanager
可以管理任何實(shí)現(xiàn) IHostingService
接口的類(有關(guān)方法參數(shù)和返回值的詳細(xì)信息扎附,請(qǐng)參閱 API documentation.
創(chuàng)建一個(gè)新的自定義服務(wù)
- 按照上面配置新的主機(jī)服務(wù)部分中概述的步驟來訪問添加服務(wù)對(duì)話框蔫耽。
- 選擇 Custom,然后將適用的腳本拖放到字段中留夜,或者從對(duì)象選擇器中選擇它匙铡。 該對(duì)話框驗(yàn)證所選腳本是否實(shí)現(xiàn) IHostingService 接口。
- 完成添加服務(wù)香伴,點(diǎn)擊添加按鈕慰枕。
下一步,您的自定義服務(wù)將出現(xiàn)在服務(wù)類型下拉選項(xiàng)中即纲。
內(nèi)存管理
鏡像加載和卸載
當(dāng)使用 Addressable Assets 時(shí)具帮,確保正確內(nèi)存管理的主要方法是鏡像正確地加載和卸載。 這取決于您的資產(chǎn)類型和加載方法低斋。 在任何情況下蜂厅,釋放方法都可以接受已加載的資產(chǎn)或是由加載返回的操作句柄。 例如膊畴,在場(chǎng)景創(chuàng)建期間(如下所述) 掘猿,加載將返回一個(gè) AsyncOperationHandle<Sceneinstance>
,您可以通過這個(gè)返回的句柄釋放這個(gè) AsyncOperationHandle sceneinstance
唇跨,或者通過handle.Result
來釋放 稠通。 結(jié)果(在本例中為 SceneInstance
)。
資源加載
通過Addressables.LoadAssetAsync
或者 Addressables.LoadAssetsAsync
來加載資源.
這會(huì)將資源加載到內(nèi)存中买猖,而不會(huì)將其實(shí)例化改橘。 每次執(zhí)行加載調(diào)用時(shí),它都會(huì)為每個(gè)加載的資源的引用計(jì)數(shù)ref-count加1,如果對(duì)同個(gè)資產(chǎn)調(diào)用 LoadAssetAsync
三次玉控,則會(huì)得到 AsyncOperationHandle
結(jié)構(gòu)的三個(gè)引用實(shí)例但是它們都指向相同的底層,該操作對(duì)相應(yīng)資源的的參考計(jì)數(shù)為3飞主。如果加載成功,那么生成的AsyncOperationHandle
結(jié)構(gòu)將包含.Result
屬性.你也您可以使用 Unity 的內(nèi)置實(shí)例化方法來實(shí)例化加載資源,但是該方法不會(huì)增加資源的引用數(shù)ref-count。
若要卸載資源碌识,請(qǐng)使用 Addressables.Release
方法碾篡,該方法將 ref-count 遞減。 當(dāng)給定資源的 ref-count 為零時(shí)筏餐,就可以卸載該資源开泽,并減少任何依賴項(xiàng)的ref-count引用。
注意: 資產(chǎn)可能會(huì)也可能不會(huì)立即卸載胖烛,這取決于現(xiàn)有的依賴項(xiàng)眼姐。 有關(guān)更多信息诅迷,請(qǐng)閱讀關(guān)于何時(shí)清除內(nèi)存的部分佩番。 when memory is cleared
場(chǎng)景加載
要加載一個(gè)場(chǎng)景,請(qǐng)使用Addressables.LoadSceneAsync
. 您可以使用此方法在Single
單模式下加載場(chǎng)景罢杉,該模式將關(guān)閉所有打開的場(chǎng)景趟畏,或者在Additive
追加模式下加載場(chǎng)景(更多信息,請(qǐng)參閱場(chǎng)景模式加載文檔 Scene mode loading)滩租。
若要卸載一個(gè)場(chǎng)景赋秀,請(qǐng)使用Addressables.UnloadSceneAsync
。 或者在Single
模式下打開一個(gè)新的場(chǎng)景,那么會(huì)自動(dòng)卸載其他場(chǎng)景.你可以使用 Addressables 的接口或者 SceneManager.LoadScene
和 SceneManager.LoadSceneAsync
, 打開一個(gè)新場(chǎng)景并會(huì)自動(dòng)關(guān)閉當(dāng)前場(chǎng)景律想,引用計(jì)數(shù)ref-count也會(huì)適當(dāng)?shù)剡f減猎莲。
游戲?qū)ο蟮膶?shí)例化
要加載和實(shí)例化一個(gè)游戲?qū)ο筚Y產(chǎn),使用 Addressables.InstantiateAsync
實(shí)例化技即。 這實(shí)例化位于指定location
參數(shù)的預(yù)置, Addressables系統(tǒng)將加載預(yù)置及其依賴項(xiàng)著洼,并遞增所有相關(guān)資源的引用計(jì)數(shù)ref-count。
在同一地址上三次調(diào)用 InstantiateAsync
將導(dǎo)致所有依賴資產(chǎn)的 ref-count 為3而叼。 但是身笤,與三次調(diào)用 LoadAssetAsync
不同的是,每次InstantiateAsync
異步調(diào)用都返回一個(gè) AsyncOperationHandle
,它指向一個(gè)唯一的操作葵陵。 這是因?yàn)槊總€(gè)實(shí)例化 InstantiateAsync
的結(jié)果都是唯一的實(shí)例液荸。 Instanateasync
和其他加載調(diào)用之間的另一個(gè)區(qū)別是可選的 trackHandle
參數(shù)(追蹤handle)。 當(dāng)設(shè)置為 false
時(shí)脱篙,在釋放實(shí)例時(shí)娇钱,必須保留 AsyncOperationHandle
。 這樣更有效率绊困,但是需要更多的開發(fā)工作文搂。
要銷毀毀一個(gè)實(shí)例化的游戲?qū)ο螅?qǐng)使用 Addressables.ReleaseInstance
考抄,或關(guān)閉包含實(shí)例化對(duì)象的場(chǎng)景细疚。 你可以使用 Addressables 的接口或者 SceneManager.LoadScene
和 SceneManager.LoadSceneAsync
, 打開一個(gè)新場(chǎng)景并會(huì)自動(dòng)關(guān)閉當(dāng)前場(chǎng)景。 如上所述,如果將 trackHandle
設(shè)置為false
疯兼,則只能調(diào)用 Addressables.ReleaseInstance
然遏,而不是實(shí)際的游戲?qū)ο驡ameObject。
注意: 如果您調(diào)用 Addressables.ReleaseInstance
吧彪。 在一個(gè)沒有使用 Addressables API 創(chuàng)建,或者創(chuàng)建時(shí)將 trackHandle
設(shè)置未false
了,系統(tǒng)會(huì)返回 false待侵,以指示該方法無法釋放指定的實(shí)例。 在這種情況下姨裸,實(shí)例不會(huì)被銷毀
Addressables.InstantiateAsync
有一些相關(guān)的開銷,所以如果你需要每幀實(shí)例化相同的對(duì)象幾百次,考慮通過 Addressables
API 加載,然后通過其他方法實(shí)例化,你可以調(diào)用 Addressables. LoadAssetAsync
,然后對(duì)返回結(jié)果調(diào)用 GameObject.Instantiate()
,這允許靈活地以同步方式調(diào)用 Instanate
,缺點(diǎn)是 Addressables 系統(tǒng)不知道您創(chuàng)建了多少實(shí)例秧倾,如果管理不當(dāng),可能會(huì)導(dǎo)致內(nèi)存問題.例如傀缩,引用紋理的預(yù)置將不再具有可供引用的有效加載紋理那先,從而導(dǎo)致內(nèi)存泄漏問題(或更糟)。 這些類型的問題可能很難跟蹤赡艰,因?yàn)槟赡懿粫?huì)立即觸發(fā)內(nèi)存卸載(請(qǐng)參閱下面關(guān)于清除內(nèi)存的小節(jié)clearing memory
數(shù)據(jù)加載
你不需要使用AsyncOperationHandle.Result
來釋放物體,但仍然需要它們本身才能被釋放(這段我也不清楚它在說什么)
舉個(gè)例子可以是Addressables.LoadResourceLocationsAsync
和Addressables.GetDownloadSizeAsync
你可以訪問這些數(shù)據(jù),直到它們被釋放.請(qǐng)使用Addressables.Release
操作來釋放
后臺(tái)交互
不返回 AsyncOperationHandle
中任何內(nèi)容的操作售淡。 結(jié)果字段具有一個(gè)可選參數(shù),用于在完成時(shí)自動(dòng)釋放操作句柄,如果在操作完成后不再需要這些操作句柄之一慷垮,請(qǐng)將 autoReleaseHandle
參數(shù)設(shè)置為 true
揖闸,以確保清除操作句柄,如果需要在操作句柄完成后檢查操作句柄的狀態(tài),則希望 autoReleaseHandle
為 false料身。 這些接口的例子是 Addressables.DownloadDependenciesAsync
和 Addressables.UnloadScene
Addressable Profiler配置文件
使用 Addressable Profiler 窗口監(jiān)視所有 Addressables 系統(tǒng)操作的引用計(jì)數(shù)汤纸。 訪問“編輯器”中的窗口,
Window > Asset Management > Addressable Profiler
重要:為了查看探查器中的數(shù)據(jù),必須在 Addresssableassetsettings
對(duì)象的檢視面板中啟用 Send Profiler Events
設(shè)置芹血。
分析器提供了以下信息:
- 白色垂直線表示發(fā)生加載請(qǐng)求的幀贮泞。
- 藍(lán)色背景表示當(dāng)前加載的資源。
- 圖中綠色部分表示資產(chǎn)的當(dāng)前引用計(jì)數(shù)祟牲。
內(nèi)存何時(shí)清空
不再被引用的資源(在探查器的藍(lán)色部分的末尾顯示)并不一定意味著已經(jīng)卸載了該資源隙畜。 一個(gè)常見的適用場(chǎng)景涉及一個(gè)資源包中的多個(gè)資產(chǎn)。 例如:
- 在一個(gè)資產(chǎn)組合'stuff'中有三個(gè)資產(chǎn)(樹tree说贝、坦克tank,和牛cow)议惰。
- 當(dāng)加載樹tree時(shí),分析器將顯示一個(gè)樹tree引用計(jì)數(shù)乡恕,一個(gè)stuff引用計(jì)數(shù)言询。
- 稍后,當(dāng) tank 加載時(shí)傲宜,分析器將同時(shí)顯示一個(gè) tree 和 tank 的參考計(jì)數(shù)运杭,以及兩個(gè) stuff 的參考計(jì)數(shù)
- 如果釋放 tree,它的 ref-count 變?yōu)榱愫洌⑶宜{(lán)條消失辆憔。
在這個(gè)示例中,此時(shí)實(shí)際上并沒有卸載樹資源。 您可以加載資源包或其部分內(nèi)容虱咧,但不能部分卸載資產(chǎn)包.
在stuff本身完全卸載之前熊榛,其中的任何資源都不會(huì)卸載。 但是有一個(gè)例外Resources.UnloadUnusedAssets
,
在上述場(chǎng)景中執(zhí)行此方法將導(dǎo)致 tree 卸載腕巡。 因?yàn)?Addressables 系統(tǒng)無法知道這些事件,profiler圖形監(jiān)視器僅反映 Addressables ref-counts (不完全反映內(nèi)存所擁有的內(nèi)容)玄坦。 注意,如果您選擇使用Resources.UnloadUnusedAssets
來手動(dòng)釋放資源绘沉,這是一個(gè)非常慢的操作,并且應(yīng)該只在不會(huì)顯示任何故障的屏幕上調(diào)用(即最好是在加載時(shí)調(diào)用,不然可能存在游戲過程中的掉幀卡幀)煎楣。
異步處理句柄
一些Addressables API方法會(huì)返回一個(gè)AsyncOperationHandle
句柄,句柄最主要的目的是允許訪問當(dāng)前異步的的狀態(tài)和曹祖哦的結(jié)果,句柄信息知道你調(diào)用Addressables.Release
或者Addressables.ReleaseInstance
都是有效的.獲取更多的相關(guān)信息,參見memory management.
當(dāng)操作完成之后,AsyncOperationHandle.Status
屬性將會(huì)返回AsyncOperationStatus.Succeeded
或者AsyncOperationStatus.Failed
,如果操作是成功的,那么將會(huì)得到一個(gè)AsyncOperationHandle.Result
結(jié)果屬性
你可以定期檢查操作狀態(tài),或者注冊(cè)一個(gè)完成時(shí)的回調(diào)事件AsyncOperationHandle.Complete
,當(dāng)你不再需要提供返回AsyncOperationHandle
,你應(yīng)該使用Addressables.Release
方法來釋放
有類型(確定類型)的句柄 對(duì)比 無類型句柄
大多數(shù) Addressables API 方法返回一個(gè)一般的 AsyncOperationHandle<T>泛型結(jié)構(gòu),允許 AsyncOperationHandle.Completed
事件的類型安全,以及確切的AsyncOperationHandle.Result
對(duì)象的類型,還有一個(gè)非通用的 AsyncOperationHandle
結(jié)構(gòu),你可以根據(jù)需要在兩個(gè)句柄之間進(jìn)行轉(zhuǎn)換
請(qǐng)注意,如果嘗試將非泛型句柄強(qiáng)制轉(zhuǎn)換為不正確類型的泛型句柄车伞,則會(huì)發(fā)生運(yùn)行時(shí)異常择懂。 例如
AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
// Convert the AsyncOperationHandle<Texture2D> to an AsyncOperationHandle:
AsyncOperationHandle nonGenericHandle = textureHandle;
// Convert the AsyncOperationHandle to an AsyncOperationHandle<Texture2D>:
AsyncOperationHandle<Texture2D> textureHandle2 = nonGenericHandle.Convert<Texture2D>();
// This will throw and exception because Texture2D is required:
AsyncOperationHandle<Texture> textureHandle3 = nonGenericHandle.Convert<Texture>();
AsyncOperationHandle 使用案例
void Start() {
//注冊(cè)完成時(shí)的回調(diào)函數(shù)
AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAsset<Texture2D>("mytexture");
textureHandle.Completed += TextureHandle_Completed;
}
private void TextureHandle_Completed(AsyncOperationHandle<Texture2D> handle) {
if (handle.Status == AsyncOperationStatus.Succeeded) {
Texture2D result = handle.Result;
// The texture is ready for use.
}
}
Asyncoperationhandle 繼承自 IEnumerator,因此可以在協(xié)同程序中生成它
public IEnumerator Start() {
AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
yield return handle;
if (handle.Status == AsyncOperationStatus.Succeeded) {
Texture2D texture = handle.Result;
// The texture is ready for use.
// ...
// Release the asset after its use:
Addressables.Release(handle);
}
}
Addressables 還支持異步操作await
,通過AsyncOperationHandle.Task
屬性:
public async Start() {
AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
await handle.Task;
// The task is complete. Be sure to check the Status is successful before storing the Result.
}
注意:
用 SceneManager.LoadSceneAsync加載場(chǎng)景并將allowSceneActivation
屬性設(shè)置為false
時(shí),或使用 Addressables.LoadSceneAsync
并將activateOnLoad 設(shè)置為false時(shí).可能會(huì)導(dǎo)致后續(xù)的異步操作被阻塞無法完成,詳情請(qǐng)參見allowSceneActivation
自定義操作
IResourceProvider
API 允許您通過以數(shù)據(jù)驅(qū)動(dòng)的方式定義位置和依賴關(guān)系來擴(kuò)展加載過程帖世。 在某些情況下休蟹,您可能希望創(chuàng)建自定義操作沸枯。Iresourceprovider
API 是構(gòu)建這些自定義操作的基礎(chǔ)
創(chuàng)建一個(gè)自定義操作
通過從 AsyncOperationBase
類派生并重寫所需的虛方法來創(chuàng)建自定義操作日矫。 可以將派生的操作傳遞給 ResourceManager.StartOperation
啟動(dòng),并接收 一個(gè)AsyncOperationHandle
的返回結(jié)構(gòu)。 以這種方式啟動(dòng)的操作在 ResourceManager
中注冊(cè)绑榴,并顯示在 Addressables Profiler 中
哪轿。
執(zhí)行操作
Resourcemanager
調(diào)用 AsyncOperationBase
。 在依賴性操作完成后翔怎,再執(zhí)行自定義操作方法窃诉。
完成句柄
自定義操作完成后,調(diào)用 AsyncOperationBase.Complete
赤套。您可以在 Execute 方法中調(diào)用這個(gè)函數(shù)飘痛,也可以將其推遲到調(diào)用外部。 Asyncoperationbase. Complete
通知 ResourceManager
操作已經(jīng)完成容握,并將調(diào)用關(guān)聯(lián)的 AsyncOperationHandle.Completed
事件已完成活動(dòng)宣脉。
終止操作
當(dāng)你在釋放AsyncOperationHandle
時(shí),Resourcemanager
會(huì)為你的自定義操作調(diào)用 AsyncOperationBase.Destroy
方法,你應(yīng)該在此釋放與自定義操作關(guān)聯(lián)的任何內(nèi)存或資源。
Addressables分析器
Addressables分析器一個(gè)收集你的項(xiàng)目的地址布局信息的工具剔氏。 在某些情況下塑猖,分析人員可能會(huì)采取適當(dāng)?shù)男袆?dòng)來清理項(xiàng)目的狀態(tài)。 在其他情況下谈跛,分析僅僅是一個(gè)信息工具羊苟,它可以讓你對(duì)你的 Addressables 布局做出更明智的決定。
使用分析器
在編輯器中感憾,打開 Addressables Window **(Window Asset Management Addressables) **蜡励,然后單擊菜單中的 Analyze 按鈕以打開 Addressables Window 。
分析窗口顯示一個(gè)分析規(guī)則列表,以及以下操作:
- Analyze Selected Rules 分析選擇規(guī)則
- Fix Selected Rules 修復(fù)選擇規(guī)則
- Clear Selected Rules 清理選擇規(guī)則
分析操作
分析操作是規(guī)則信息的收集步驟凉倚。運(yùn)行此操作可以收集有關(guān)生成彭则、依賴映射等的數(shù)據(jù), 每個(gè)規(guī)則負(fù)責(zé)收集所需的數(shù)據(jù),并將其作為 AnalyzeResult
對(duì)象返回占遥。
在分析步驟期間俯抖,不應(yīng)采取任何措施修改任何數(shù)據(jù)或項(xiàng)目狀態(tài)。 根據(jù)在此步驟中收集的數(shù)據(jù)瓦胎,修復(fù)操作可能是適當(dāng)?shù)牟僮鬟^程芬萍。 但是,有些規(guī)則只包含分析步驟搔啊,因?yàn)闆]有明確的合適的操作基于收集到的基礎(chǔ)信息柬祠。
例子
Check Scene to Addressable Duplicate Dependencies
Check Resources to Addressable Duplicate Dependencies
純信息性規(guī)則且不包含修復(fù)操作的規(guī)則被歸類為不可修復(fù)規(guī)則。 那些確實(shí)具有修復(fù)操作的規(guī)則被歸類為可修復(fù)規(guī)則负芋。
清除步驟
此操作將刪除分析收集的任何數(shù)據(jù)漫蛔,并相應(yīng)地更新TreeView
修復(fù)操作
對(duì)于可修復(fù)規(guī)則,您可以選擇運(yùn)行修復(fù)操作旧蛾。 這將使用在分析步驟中收集的數(shù)據(jù)來執(zhí)行任何必要的修改并解決問題
例子:
Check Duplicate Group Dependencies
可以采取合理的適當(dāng)行動(dòng)來解決分析中發(fā)現(xiàn)的問題
提供分析規(guī)則
可修復(fù)的規(guī)則
檢查重復(fù)的組依賴項(xiàng)
該規(guī)則通過使用 BundledAssetGroupSchemas
掃描所有組并投影資產(chǎn)組布局來檢查可能重復(fù)的資產(chǎn)莽龟。 這實(shí)際上需要觸發(fā)一個(gè)完整的構(gòu)建,因此這種檢查非常耗時(shí),而且需要大量的性能。
問題: 重復(fù)的資源產(chǎn)生于共享依賴關(guān)系的不同組中的資源猪杭,例如共享不同 Addressable 組中存在的資產(chǎn)的兩個(gè)預(yù)制Prefab。 這些材料(以及它的任何附屬物)將被拉入包含預(yù)制Prefabs的兩個(gè)組搂赋。 為了防止這種情況,材料必須被標(biāo)記為可尋址的益缠,無論是在一個(gè)Prefab脑奠,或在自己的空間,從而把材料和它的依賴關(guān)系在一個(gè)單獨(dú)的可尋址組
解決方案: 如果此檢查發(fā)現(xiàn)任何問題幅慌,在此規(guī)則上運(yùn)行修復(fù)操作將創(chuàng)建一個(gè)新的 Addressable 組宋欺,用于移動(dòng)所有依賴的資產(chǎn)。
異常: 如果您有一個(gè)包含多個(gè)對(duì)象的資源欠痴,那么不同的組可能只提取該資源的一部分迄靠,而不是實(shí)際的重復(fù)。 一個(gè)多網(wǎng)格的 FBX 就是這樣的例子喇辽。 如果一個(gè)網(wǎng)格在“ GroupA”中掌挚,另一個(gè)網(wǎng)格在“ GroupB”中,那么這個(gè)規(guī)則將認(rèn)為 FBX 是共享的菩咨,如果您運(yùn)行修復(fù)操作吠式,則將它提取到它自己的組中陡厘。 在這種情況下,運(yùn)行修復(fù)操作實(shí)際上是有害的特占,因?yàn)閮山M都沒有完整的 FBX 資源糙置。
還要注意,重復(fù)的資源可能并不總是一個(gè)問題是目。 如果同一組用戶永遠(yuǎn)不會(huì)請(qǐng)求資源(例如谤饭,區(qū)域特定的資源) ,那么可能希望重復(fù)依賴懊纳,或者至少是無關(guān)緊要的揉抵。 每個(gè)項(xiàng)目都是唯一的,因此修復(fù)重復(fù)的資資源依賴關(guān)系應(yīng)該根據(jù)具體情況進(jìn)行評(píng)估嗤疯。
不可修復(fù)的規(guī)則
檢查資源以尋址重復(fù)依賴項(xiàng)
此規(guī)則檢測(cè)是否有任何資源或資源依賴項(xiàng)在構(gòu)建的Addressable
數(shù)據(jù)和駐留在Resources
文件夾中的資源之間重復(fù)冤今。
問題: 這些重復(fù)意味著數(shù)據(jù)將同時(shí)包含在應(yīng)用程序構(gòu)建和 Addressables 構(gòu)建中。
解決方案: 這個(gè)規(guī)則是不可修復(fù)的茂缚,因?yàn)闆]有合適的操作可以自動(dòng)解決戏罢。 它純粹提供信息,提醒您存在重復(fù)和冗余,如果有的話,你必須自行決定如何進(jìn)行和采取什么行動(dòng)脚囊。 可能的手動(dòng)修復(fù)的一個(gè)示例是將有問題的資產(chǎn)移出 Resources 文件夾龟糕,并使其可尋址。
構(gòu)建捆綁布局
此規(guī)則將顯示如何在 Addressable 構(gòu)建中顯式標(biāo)記為 Addressable 的資源凑术。 對(duì)于這些顯式資源翩蘸,我們還顯示了構(gòu)建隱式引用了哪些資源,因此將引入哪些資源淮逊。
此規(guī)則收集的數(shù)據(jù)不表示任何特定問題。 它是純粹的信息扶踊。
檢查精靈地圖集泄鹏,以尋址重復(fù)依賴
給定一個(gè)可尋址的精靈地圖集,這個(gè)規(guī)則將檢測(cè)是否有任何精靈在地圖集被標(biāo)記為可尋址的任何其他地方秧耗。
問題: 這些重復(fù)意味著精靈數(shù)據(jù)將在可尋址構(gòu)建的多個(gè)區(qū)域中重復(fù)备籽。
解決方案:它是純粹的信息,提醒你冗余分井。 如果有的話车猬,你必須決定如何進(jìn)行和采取什么行動(dòng)。 一個(gè)可能的手動(dòng)修復(fù)的例子是從 Addressables 中移除重復(fù)的精靈尺锚,讓你的資產(chǎn)從你的 Addressable 精靈地圖集中引用一個(gè)精靈珠闰,而不是直接引用精靈。
拓展分析
每個(gè)唯一的項(xiàng)目可能需要額外的分析規(guī)則以外的預(yù)先包裝瘫辩。
可尋址資產(chǎn)系統(tǒng)允許您創(chuàng)建自己的自定義規(guī)則類
AnalyzeRule objects
創(chuàng)建 AnalyzeRule
類的一個(gè)新的子類伏嗜,并重寫以下屬性:
-
canFix
告訴分析該規(guī)則是否被認(rèn)為是可修復(fù)的坛悉。 -
ruleName
是您將在Analyze window分析窗口中看到的此規(guī)則的顯示名稱。
你還需要重寫以下方法: List<AnalyzeResult> RefreshAnalysis(AddressableAssetSettings settings)
void FixIssues(AddressableAssetSettings settings)
-
void ClearAnalysis().
Note: 如果您的規(guī)則被指定為不可修復(fù)承绸,那么您不必重寫FixIssues
方法裸影。
引用分析
這是你的分析操作。 在此方法中军熏,執(zhí)行所需的任何計(jì)算轩猩,并緩存潛在修復(fù)所需的所有數(shù)據(jù)。 返回值是一個(gè) List<Analyzeresult>
列表荡澎。 在收集數(shù)據(jù)之后界轩,為分析中的每個(gè)條目創(chuàng)建一個(gè)新的 AnalyzeResult
,其中第一個(gè)參數(shù)的數(shù)據(jù)為字符串衔瓮,第二個(gè)參數(shù)的數(shù)據(jù)為 MessageType
(可以選擇將消息類型指定為警告或錯(cuò)誤)浊猾。
返回您創(chuàng)建的對(duì)象列表。 如果需要在 TreeView
中為特定的 AnalyzeResult
對(duì)象創(chuàng)建子元素热鞍,則可以使用 kDelimiter
描述父項(xiàng)和任何子項(xiàng)葫慎。 包括父項(xiàng)和子項(xiàng)之間的分隔符。
修復(fù)問題
這是您的修復(fù)操作薇宠。 如果需要對(duì)分析步驟采取適當(dāng)?shù)男袆?dòng)偷办,請(qǐng)?jiān)谶@里執(zhí)行
清除分析
這是你的清除分析行為。 在分析步驟中緩存的任何數(shù)據(jù)都可以在此函數(shù)中清理或刪除澄港。 Treeview
將會(huì)更新以反映數(shù)據(jù)的缺乏椒涯。
追加自定義規(guī)則到GUI
自定義規(guī)則必須使用 1AnalyzeWindow.RegisterNewRule<RuleType>()1 向 GUI 類注冊(cè)自己。 為了在Analyze window.中顯示回梧。 例如:
class MyRule : AnalyzeRule {}
[InitializeOnLoad]
class RegisterMyRule
{
static RegisterMyRule()
{
AnalyzeWindow.RegisterNewRule<MyRule>();
}
}
(舊項(xiàng)目)更新移植到可尋址資源系統(tǒng)
本文詳細(xì)介紹了如何修改現(xiàn)有項(xiàng)目以利用可尋址資產(chǎn)废岂。 有三種傳統(tǒng)的資產(chǎn)參考方法:
- Direct References 直接引用類型 : 將資源直接添加到應(yīng)用程序自動(dòng)加載的組件或場(chǎng)景中
- Resource Folders Resource 文件夾 : 將資源放在Resource文件夾中通過它們的名字加載
- Asset Bundles 資源打包成資源包 : 打包成AssetBundle然后通過文件路徑加載它們及其依賴項(xiàng)
Direct References直接引用法的移植:
要從這種方法遷移,請(qǐng)遵循以下步驟:
- 用AssetReference 替換對(duì)對(duì)象的直接引用
public GameObject directRefMember;
//替換為
public AssetReference AssetRefMember;
- 將資源拖到適當(dāng)?shù)慕M件的 Inspector 上狱意,就像直接引用一樣湖苞。
- 如果希望基于對(duì)象而不是字符串名稱加載資產(chǎn),請(qǐng)直接從您在設(shè)置中創(chuàng)建的
AssetReference
對(duì)象中實(shí)例化該資產(chǎn).
AssetRefMember.LoadAssetAsync<GameObject>();
AssetRefMember.InstantiateAsync(pos, rot);
注意: 可尋址資產(chǎn)系統(tǒng)異步加載資產(chǎn)详囤。 在更新對(duì)資產(chǎn)引用的直接引用時(shí)财骨,還必須更新代碼以異步操作。
Resource folders法的移植:
當(dāng)您將 Resources文件夾中的資產(chǎn)標(biāo)記為Addressable時(shí)藏姐,系統(tǒng)會(huì)自動(dòng)將該資產(chǎn)從Resources文件夾移動(dòng)到 Project 中名為 Resources_moved 的新文件夾中隆箩。 已移動(dòng)資產(chǎn)的默認(rèn)地址是舊路徑,省略了文件夾名稱羔杨。 加載代碼的變化為:
Resources.LoadAsync<GameObject>("desert/tank.prefab");
//替換為
Addressables.LoadAssetAsync<GameObject>("desert/tank.prefab");.
Asset Bundles法的移植:
當(dāng)您打開 Addressables window時(shí)捌臊,Unity 提供將所有資源包轉(zhuǎn)換為 Addressable 資產(chǎn)組。
這是遷移代碼最簡(jiǎn)單的方法问畅。 如果選擇手動(dòng)轉(zhuǎn)換資源娃属,請(qǐng)單擊忽略按鈕六荒。
然后,使用前面描述的直接引用或資源文件夾方法矾端。
資產(chǎn)地址的默認(rèn)路徑是其文件路徑掏击。 如果使用路徑作為資源的地址,則裝載資源的方式與從捆綁包裝載資產(chǎn)的方式相同秩铆。 可尋址資源系統(tǒng)處理包及其所有依賴項(xiàng)的加載砚亭。