u3d 資源包

AssetBundles是可以把unity3d中你所創建的文件或任何資源導出的一種文件格式,這些文件導出後使用的是一種特定的文件格式(.Unity3d 後綴名可自定義),這些特定格式的文件能在需要的時候加載到場景中。而這些特定的文件格式可以是模型,貼圖,聲音文件甚至是場景文件,它們是先前就被設計好的文件,所以很容易就可以被下載到你所建立的遊戲或場景中來。

AssetBundles 可以是任意類型的文件只要是unity3d能識別的資源文件格式,識別主要是以文件擴展名爲準,比如.prefab等等。當然如果你想包含自定義的二進制文件,需要命名這些文件爲以".bytes"爲後綴,Unity將會把這些文件導成TextAssets。

創建資源包

有三個類方法可以用來構建資源包:BuildPipeline.BuildAssetBundleBuildPipeline.BuildStreamedSceneAssetBundle 和BuildPipeline.BuildAssetBundleExplicitAssetNames.

  • BuildPipeline.BuildAssetBundle allows you to build AssetBundles of any type of asset. 
    可以構建任意類型資源的資源包。【創建一個壓縮好的包含Assets下的所有資源文件.unity3d。可以包含是項目目錄下的任意資源,而把所有的資源壓縮成一個.unity3d的文件,這個文件包括所有的預置物體(prefabs),紋理貼圖(textures),模型,動畫。使用AssetBundle.mainAsset這個函數可以很方便的讓你指定一個定義好的物體。被壓縮的資源儲存在pathName. Options,會自動的允許用戶包含相關的或者需要用到的】
  • BuildPipeline.BuildStreamedSceneAssetBundle is used when you want to include only scenes to be streamed and loaded as the data becomes available. 
    用來當你希望只包括流場景,使數據加載變爲可用。【建立一個或多個場景,這些場景所需要的所有資源將被壓縮入資源包,即asset bundle裏面。資源包中的場景文件可以在任何平臺上建立,而且這些文件往往是以一個單一的unity3d文件格式被用來創建。使用WWW類可以下載場景文件。當場景文件被下載好可以使用WWW.LoadFromCacheOrDownload來加載下載好的場景文件。】
  • BuildPipeline.BuildAssetBundleExplicitAssetNames is the same as BuildPipeline.BuildAssetBundle but has an extra parameter to specify a custom string identifier (name) for each object. 
    和BuildPipeline.BuildAssetBundle類似,但是有額外的參數來指定每個物體的自定義的字符串(名字)。【建立一個自定義名字的資源包方法: 創建一個包含所有資源的一個壓縮好的unity3d文件。AssetBundle可以包括任何項目目錄下的資源文件。在assetNames參數中提供一個與資源數目相同大小的字符串數組。在資源數組中存儲的信息與資源文件名相同,可以傳遞AssetBundle.Load去加載一個指定的資源。使用BuildAssetBundle時,只需使用資源的路徑名。壓縮好的資源包文件將會被儲存在pathName. Options,允許用戶自動包含與之相關的或者總是包含完整的資源去代替確切的參照物體。】

public class ExportAssetBundles
{
    [MenuItem("Assets/Build AssetBundle From Selection - Track dependencies")]
    static void ExportResource()
    {
        // Bring up save panel
        string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");
        if (path.Length != 0)
        {
            // Build the resource file from the active selection.
            Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets);
            Selection.objects = selection;
        }
    }
    [MenuItem("Assets/Build AssetBundle From Selection - No dependency tracking")]
    static void ExportResourceNoTrack()
    {
        // Bring up save panel
        string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");
        if (path.Length != 0)
        {
            // Build the resource file from the active selection.
            BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path);
        }
    }
}

Downloading AssetBundles 下載資源包

推薦使用WWW.LoadFromCacheOrDownload方法用來下載資源。當下載完成你就可以重新得到該資源的相關屬性,例如:

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
	// 從指定路徑下載
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);

    // Wait for download to complete
	// 等待下載完成
    yield return www;

    // Load and retrieve the AssetBundle
	// 加載並取回資源包
    AssetBundle bundle = www.assetBundle;
}

以上代碼中的url是資源路徑的下載地址,首先使用LoadFromCacheOrDownload下載資源,括號中的url是路徑,1代表版本號,當等待下載完成後即可加載相關資源。

當資源包中的對象創建好之後,就可以激活下載好的資源被解壓。到這裏,就需要用戶去加載包含在資源包器中的對象。LoadFromCacheOrDownload函數中的第二個參數是指定下載資源的版本號。如果在存儲器中的資源沒有被下載或者資源下載了但是比需要資源的版本號低,LoadFromCacheOrDownload函數將會下載資源到資源包中。否則資源包其將會直接從存儲器中加載。

Loading and unloading objects from an AssetBundle 從資源包加載和卸載對象

如果下載數據已經建立了資源包,你就可以使用這三個不同的函數來加載物體了: AssetBundle.LoadAssetBundle.LoadAsync 和 AssetBundle.LoadAll.

  • AssetBundle.Load will load an object using its name identifier as a parameter. The name is the one visible in the Project view. You can optionally pass an object type as an argument to the Load method to make sure the object loaded is of a specific type. 
    AssetBundle.Load會加載物體,使用該物體的名字作爲識別的參數。名字可以在Unity3d中Project view看到。你可以自由選擇去傳遞對象變量的類型來確認該加載對象是否是被指定的類型。
  • AssetBundle.LoadAsync works the same as the Load method described above but it will not block the main thread while the asset is loaded. This is useful when loading large assets or many assets at once to avoid pauses in your application. 
    AssetBundle.LoadAsync 與AssetBundle.Load 函數相類似,但是當資源加載時它不會阻礙主線程。如果同時要加載比較大的資源或者很多資源時,這個函數會比較有用,它可以避免程序的暫停,因爲它會同步加載。
  • AssetBundle.LoadAll will load all the objects contained in your AssetBundle. As with AssetBundle.Load, you can optionally filter objects by their type. 
    AssetBundle.LoadAll 顧名思義這個函數是用來加載所有在你資源包中的對象。作爲AssetBundle.Load這個函數,你可以隨意用該對象的類型去過濾。

使用AssetBundle.Unload這個函數可以卸載加載好的資源,這個函數有一個布爾值的參數是用來告訴Unity是否要卸載所有的數據(包含加載的資源對象)或者只是已經下載過的被壓縮好的資源數據。如果要在資源包中從你的應用程序要使用一些對象或者你想釋放一些內存,可以傳遞false這個值來卸載已經壓縮好了的文件從你的內存中(即.unity3d文件)。如果要完全卸載所有的資源數據,需要傳遞true這個值,這將會銷燬所有的資源包器中加載的資源。

Listing objects in an AssetBundle 從資源包列表物體

可以使用AssetBundle.LoadAll 去取回資源包中包含的所有對象的數組。不可能直接就取回一個列表。通常的做法是保持一個單獨的TextAsset,這個TextAsset是控制資源包中資源的名稱。

Instantiating objects from AssetBundles 從資源包實例化物體

下載了資源,也加載好了,那麼就該在場景中使用Instantiate函數去實例化它了。

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
	// 開始從指定路徑下載
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);

    // Wait for download to complete
	// 等待下載完成
    yield return www;

    // Load and retrieve the AssetBundle
	// 加載並取回資源包
    AssetBundle bundle = www.assetBundle;

    // Load the TextAsset object
	// 加載文本資源對象
    GameObject go = bundle.Load("myGameObject", typeof(GameObject)) as GameObject;

    // Instantiate the GameObject
	// 實例化該對象
    Instantiate(go);
}

Keeping track of downloaded AssetBundles 保持跟蹤下載的資源包

Unity不提供自動的一個可以取回所有被下載資源的列表。所以需要我們在腳本中要建立這些資源對象的信息和它們的路徑以便我們去查找。

Storing and loading binary data in an AssetBundle 在資源包儲存和加載二進制數據

第一步要儲存文件的擴展名以" .bytes"爲結尾的二進制數據。Unity會把它們看成TextAsset來使用。當你建立資源包就會包含一個TestAsset的文件。當在資源包應用程序中下載好這個二進制數據後也需要加載它們,可以使用TextAsset的.bytes的屬性去取回你的二進制數據。

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);

    // Wait for download to complete
    yield return www;

    // Load and retrieve the AssetBundle
    AssetBundle bundle = www.assetBundle;

    // Load the TextAsset object
    TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;

    // Retrieve the binary data as an array of bytes
    byte[] bytes = txt.bytes;
}

Including scripts in AssetBundles 在資源包中包含腳本

資源包可以作爲TextAssets包含腳本但是不會實際執行代碼。如果想要在資源包包含用來執行應用程序的代碼,需要預先編譯,然後使用Mono Reflection class來加載(注意:Reflection在iOS平臺不可用)。可以在任何版本的C#IDE編輯器(如:Monodevelop, Visual Studio)或者使用mono/.net 文檔編輯器。

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);

    // Wait for download to complete
    yield return www;

    // Load and retrieve the AssetBundle
    AssetBundle bundle = www.assetBundle;

    // Load the TextAsset object
    TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;

    // Load the assembly and get a type (class) from it
    var assembly = System.Reflection.Assembly.Load(txt.bytes);
    var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");

    // Instantiate a GameObject and add a component with the loaded class
    GameObject go = new GameObject();
    go.AddComponent(type);
}

Managing asset dependencies 管理相關資源

任何在資源包中給出的資源可能主要依賴於其它的資源。舉個例子,一個模型可能混合多種紋理和材質球中的材質,可能包括所有的某個資源相關的東西,然而,一些從不同資源包文件夾中的資源或許都要用到相同的一些其它資源(比如說一些不同的建築模型會用到相同的紋理貼圖)。如果在每個資源文件夾中包含一個被共享的資源要被某個對象用到,當資源文件加載的時候那就不需要去實例化多餘的對象,換句話說就是隻要把共享的資源實例化一次就可以了,這樣就可以大大減少內存的佔用。

要避免資源的浪費,可以單獨建立一個專門的文件夾用來放要被共享的資源或者所有需要被加載的對象,官方提供的AssetBundles Example Project中的AssetBundles這個文件夾就是一個不錯的選擇,要查看該文件夾需要進入unity3D->在Project中右擊會看到一個下拉菜單有Auto Build Rescources Files的選項,點擊它,然後進入AsssetBundles資源目錄下你會發現多了一個名爲AssetBundles的文件夾,所有的資源已經被轉化成.unity3d的格式存儲在這裏了。要把這些資源存儲在指定的AssetBundles這個文件夾下,需要用到BuildPipeline.PushAssetDependencies和BuildPipeline.PopAssetDependencies這兩個函數。首先需要BuildPipeline.PushAssetDependencies來激活將要使用到的資源文件夾(比如AssetBundles Example Project中的AssetBundles這個文件夾)。然後就需要建立你想在這個文件夾中存放什麼資源了,比如說一個紋理貼圖。接着再次呼叫BuildPipeline.PushAssetDependencies來激活下一個將要使用到的和先前存放資源相關的其它資源。比如說有一個角色的模型,這個角色模型有它自己的紋理貼圖,那就需要先激活它的貼圖然後激活模型本身。如此反覆直到把所有與需要加載資源的其它相關資源都使用BuildPipeline.PushAssetDependencies加載完畢,最後再使用BuildPipeline.PopAssetDependencies來告訴程序這個模型所有的相關資源已經全部加載完成。

在運行時,需要考慮到優先加載資源的順序。舉個例子,現在有一張紋理貼圖,這張貼圖可能被很多個模型需要用到,而這個貼圖又有很多不同的材質,那就得先加載紋理貼圖,然後材質,最後纔是模型。

具體的代碼實現過程可參考AssetBundles Example Project中的AutoExportRescources這個腳本。

Can I reuse my AssetBundles in another game? 
可以在其他的遊戲場景重新使用我的資源包嗎?

資源包允許用戶去共享資源包中的內容到其它不同的遊戲。如果需要共享,前提需要你已經建立好這個資源包共享文件。可以使用BuildAssetBundleOptions.CollectDependencies這個函數來檢測是否已經建立好資源包文件。

How are assets in AssetBundles identified?
資源包中的資源如何被識別?

當在內部建立資源包時,它們的文件名不包含擴展名就會被識別。舉個例子,一個在你項目工程目錄下比如說"Assets/Textures/myTextures.jpg"的貼圖是用"myTexture"來識別。如果使用默認的方法,當你用BuildPipeline.BuildAssetBundleExplicitAssetNames這個函數建立你的資源包,那你可以有很多你自己編號的數組上的控制。

Loading objects from an AssetBundles asynchronously
從資源包異步加載對象

You can use the AssetBundle.LoadAsync method to load objects Asynchronously and reduce the likelihood of having hiccups in your application.

可以使用AssetBundle.LoadAsync方法來異步加載對象,這樣一來可以減少在應用程序中被打斷的可能性。

using UnityEngine;

IEnumerator Start () {
	// Start a download of the given URL
	WWW www = WWW.LoadFromCacheOrDownload (url, 1);

	// Wait for download to complete
	yield return www;

	// Load and retrieve the AssetBundle
	AssetBundle bundle = www.assetBundle;

	// Load the object asynchronously
	AssetBundleRequest request = bundle.LoadAsync ("myObject", typeof(GameObject));

	// Wait for completion
	yield return request;

	// Get the reference to the loaded object
	GameObject obj = request.asset as GameObject;
}

Are AssetBundles cross-platform?
資源包可以跨平臺嗎?

AssetBundles are compatible between some platforms. Use the following table as a guideline.

在有一些平臺中是可以兼容的,可以參考下面的這個表格。

Platform compatibility for AssetBundles 資源包在平臺的兼容性
  Standalone Webplayer iOS Android
Editor Y Y Y Y
Standalone Y Y    
Webplayer Y Y    
iOS     Y  
Android       Y

How do I cache AssetBundles? 如何緩存資源包?

使用WWW.LoadFromCacheOrDownload就可以自動在你的硬盤上存儲資源包文件。但是說明一下Webplayer被限制50MB的存儲空間。如果需要更多空間則可以單獨爲遊戲購買緩存許可證。

Protecting content 保護內容

Unity允許用戶使用AssetBundle.CreateFromMemory從一個 byte[]數組中建立一個AssetBundle的對象。在運行時傳輸和解密之前,可以用這種加密方法來提高安全性和保護用戶建立的資源包中內容。

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = new WWW (url);

    // Wait for download to complete
    yield return www;

    // Get the byte data
    byte[] encryptedData = www.bytes;

    // Load the TextAsset object
    byte[] decryptedData = YourDecryptionMethod(encryptedData);

    // Create an AssetBundle from the bytes array
    AssetBundle bundle = AssetBundle.CreateFromMemory(decryptedData);

    // You can now use your AssetBundle
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章