AssetBundles
AssetBundle是一個存檔文件,其中包含平臺在運行時加載的特定資產(模型,紋理,預制,音頻剪輯,甚至整個場景)。AssetBundles可以表示彼此之間的依賴關系;例如AssetBundle A中的一個材質可以引用AssetBundle B中的一個紋理。為了通過網絡進行有效的傳遞,可以根據用例要求,選擇內置算法(LZMA和LZ4)來對AssetBundles進行壓縮。
AssetBundles可用于可下載內容(DLC),減少初始安裝大小,加載為最終用戶平臺優化的資產,并降低運行時內存壓力。
一個AssetBundle文件中有什么?
好的問題,實際上“AssetBundle”可以指兩個不同但有關的事情。
第一個是磁盤上的實際文件。我們把這叫做AssetBundle存檔,或在本文檔只是短期檔案。存檔可以被認為是一個容器,就像一個文件夾,在其中保存其他文件。這些附加文件包括兩種類型:序列化文件和資源文件。序列化的文件將您的資產分成各自的對象,并寫入這個文件。資源文件只是存儲在某些資產(紋理和音頻)中的二進制數據塊,允許我們在另一個線程上有效地將其從磁盤加載到內存。
第二個是您通過代碼從特定存檔加載資源的實際的AssetBundle對象。此對象包含您添加到此存檔的資源的所有文件路徑的映射到屬于該資產的對象,該對象在需要時需要加載。(This object contains a map of all the file paths of the assets you added to this archive to the objects that belong to that asset that need to be loaded when you ask for it.)
AssetBundle工作流程
要開始使用AssetBundles,請按照下列步驟操作。有關每個工作流程的更詳細信息,請參見本部分文檔中的其他頁面。
將資產分配給AssetBundles
要將一個給定的資產分配給一個AssetBundle,請按照下列步驟操作:
- 從“項目視圖”中選中要分配給一個bundle的資產
- 檢查Inspector視圖中的對象
- 在Inspector視圖的底部,可以看到一個部分來分配AssetBundles和Variants
- 左側的下拉菜單分配AssetBundle,而右側的下拉菜單則指定Variants
- 點擊左側的下拉菜單,其中顯示“None”以顯示當前注冊的AssetBundle名稱
- 如果尚未創建,你將看到上面的圖像中的列表
- 點擊“New...”創建一個新的AssetBundle
- 鍵入所需的AssetBundle名稱。請注意,AssetBundle名稱支持一種類型的文件夾結構,具體取決于你鍵入的內容。要添加子文件夾,請使用“/”分隔文件夾名稱。例如:AssetBundle名稱“environment/forest”將在environment子文件夾下創建一個名為forest的bundle
- 一旦你選擇或創建了一個AssetBundle名稱,你可以重復此過程,為右側下拉菜單分配或創建一個不同的名稱,以分配或創建一個Variant名稱,如果你愿意的話。在構建AssetBundles時,Variant名稱不是必需的。
要了解有關AssetBundle分配和隨附策略的更多信息,請參閱Preparing Assets for AssetBundles的文檔。
構建AssetBundles
在項目中的Assets文件夾下創建一個名為Editor的文件夾,并在文件夾中放置以下內容的腳本:
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if(!Directory.Exists(assetBundleDirectory)
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.Standalone);
}
}
該腳本將在Assets菜單的底部創建一個名為“Build AssetBundles”的菜單項,該菜單項將執行與該標記關聯的功能中的代碼。當您單擊Build AssetBundles時,進度條將顯示一個構建對話框。這將使那些用AssetBundle名稱標記的所有資產打包進同一個文件,并將它們放在由assetBundleDirectory定義的路徑上的文件夾中。
有關此代碼正在執行的更多詳細信息,請參閱有關Building AssetBundles的文檔。
上傳AssetBundles到非本地存儲
這一步對于每個用戶都是獨一無二的,而不是一步一步可以告訴你如何做。如果您打算將AssetBundles上傳到第三方托管網站,請在此處進行。如果您正在嚴格執行本地開發,并打算將所有AssetBundles都放在磁盤上,請跳到下一步。
加載AssetBundles和Assets
對于有意從本地存儲加載的用戶,您將對AssetBundles.LoadFromFile API感興趣。看起來像這樣:
public class LoadFromFileExample extends 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);
}
}
LoadFromFile
獲取包文件的路徑。
如果您自己托管AssetBundles并且需要將其下載到游戲中,那么您將對UnityWebRequest API感興趣。這里有一個例子:
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);
}
GetAssetBundle(string, int)
獲取AssetBundle的位置的uri以及要下載的包的版本。在這個例子中,我們仍然指向一個本地文件,但是字符串uri可以指向你托管AssetBundles的任何URL。
UnityWebRequest具有處理AssetBundles的特定句柄(DownloadHandlerAssetBundle),DownloadHandlerAssetBundle從請求中獲取AssetBundle。
無論使用的方法如何,你現在都可以訪問AssetBundle對象。從該對象中加載資源,你將需要使用LoadAsset<T>(string)
方法,該方法中泛型類型T表示你所要加載的Asset的類型,方法參數為所要加載的Asset對象的名稱。這將返回您從AssetBundle加載的任何對象。您可以像Unity中的任何對象一樣使用這些返回的對象。例如,如果要在場景中創建一個GameObject,則只需要調用Instantiate(gameObjectFromAssetBundle)。
有關加載AssetBundles的API的更多信息,請參閱Using AssetBundles Natively文檔。
原文鏈接:
同系列文章
本文作者: Sheh偉偉
本文鏈接: http://davidsheh.github.io/2017/07/14/「翻譯」Unity中的AssetBundle詳解(一)/
版權聲明: 本博客所有文章除特別聲明外,均采用 CC BY-NC-SA 3.0 許可協議。轉載請注明出處!