AssetBundles are files which you can export from Unity to contain assets of your choice. These files use a proprietary compressed format and can be loaded on demand in your application. This allows you to stream content like models, textures, audio clips and even entire scenes separately from the scene in which they will be used. They have been designed to make it easy to download content to your application. html
在一些大型的網絡遊戲,或者加載比較多的一些場景時,若是要等待全部模型,貼圖等各類資源文件加載完畢才能執行遊戲,對用戶將會是一個很頭大的事情。因此就須要用到動態加載,即AssetBundles。好比玩家在進入遊戲時先加載一些周圍的場景文件,這樣不只能夠提升速度還能夠減小內存資源的消耗。 node
AssetBundles是能夠把unity3d中你所建立的文件或任何資源導出的一種文件格式,這些文件導出後使用的是一種特定的文件格式(.Unity3d),這些特定格式的文件能在須要的時候加載到場景中。而這些特定的文件格式能夠是模型,貼圖,聲音文件甚至是場景文件,它們是先前就被設計好的文件,因此很容易就能夠被下載到你所創建的遊戲或場景中來。 web
AssetBundles can contain any kind of asset type recognized by Unity, as determined by the filename extension. If you want to include files with custom binary data, then you must rename those files to have ".bytes" as the extension. Unity will import these files as TextAssets. 數組
AssetBundles 能夠是任意類型的文件只要是unity3d能識別的資源文件格式,識別主要是以文件擴展名爲準,好比.prefab等等。固然若是你想包含自定義的二進制文件,須要命名這些文件爲以".bytes"爲後綴,Unity將會把這些文件導成TextAssets。 緩存
For some sample code showing how to use asset bundles, see the AssetBundles Example Project 安全
若是想了解更多關於代碼如何實現,能夠參考 AssetBundles Example Project。 網絡
There are three class methods you can use to build AssetBundles: BuildPipeline.BuildAssetBundle, BuildPipeline.BuildStreamedSceneAssetBundleand BuildPipeline.BuildAssetBundleExplicitAssetNames.. app
有三個類方法能夠用來構建資源包:BuildPipeline.BuildAssetBundle, BuildPipeline.BuildStreamedSceneAssetBundle 和BuildPipeline.BuildAssetBundleExplicitAssetNames. 異步
當使用上面的三個函數作完準備工做,咱們如今就須要去下載這些資源而後加載它們。 async
The recommended way to download AssetBundles is to use WWW.LoadFromCacheOrDownload. Once the download is complete you can retrieve the AssetBundle with the assetBundle property. For example:
推薦使用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; }
using UnityEngine; // Note: This example does not check for errors. Please look at the example in the DownloadingAssetBundles section for more information
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; // Unload the AssetBundles compressed contents to conserve memory bundle.Unload(false); }
When you access the .assetBundle property the downloaded data is extracted and the AssetBundle object is created. At this point, you are ready to load the objects contained in the bundle. The second parameter passed to LoadFromCacheOrDownload specifies which version of the AssetBundle to download. LoadFromCacheOrDownload will download the AssetBundle if it doesn't exist in the cache or if it exists but is associated with a version that is lower than the one requested. Otherwise the AssetBundle will be loaded from cache.
以上代碼中的url是資源路徑的下載地址,首先使用LoadFromCacheOrDownload下載資源,括號中的url是路徑,1表明版本號,當等待下載完成後便可加載相關資源。
當資源包中的對象建立好以後,就能夠激活下載好的資源被解壓。到這裏,就須要用戶去加載包含在資源包器中的對象。LoadFromCacheOrDownload函數中的第二個參數是指定下載資源的版本號。若是在存儲器中的資源沒有被下載或者資源下載了可是比須要資源的版本號低,LoadFromCacheOrDownload函數將會下載資源到資源包中。不然資源包其將會直接從存儲器中加載。
Having created an AssetBundle object from the downloaded data, you can load the objects contained in it using three different methods:AssetBundle.Load, AssetBundle.LoadAsync and AssetBundle.LoadAll.
若是下載數據已經創建了資源包,你就可使用這三個不一樣的函數來加載物體了: AssetBundle.Load, AssetBundle.LoadAsync 和 AssetBundle.LoadAll.
To unload assets you need to use AssetBundle.Unload. This method takes a boolean parameter which tells Unity whether to unload all data (including the loaded asset objects) or only the compressed data from the downloaded bundle. If your application is using some objects from the AssetBundle and you want to free some memory you can pass false to unload the compressed data from memory. If you want to completely unload everything from the AssetBundle you should pass true which will destroy the Assets loaded from the AssetBundle.
使用AssetBundle.Unload這個函數能夠卸載加載好的資源,這個函數有一個布爾值的參數是用來告訴Unity是否要卸載全部的數據(包含加載的資源對象)或者只是已經下載過的被壓縮好的資源數據。若是要在資源包中從你的應用程序要使用一些對象或者你想釋放一些內存,能夠傳遞false這個值來卸載已經壓縮好了的文件從你的內存中(即.unity3d文件)。若是要徹底卸載全部的資源數據,須要傳遞true這個值,這將會銷燬全部的資源包器中加載的資源。
You can use AssetBundle.LoadAll to retrieve an array containing all objects from the AssetBundle. It is not possible to get a list of the identifiers directly. A common workaround is to keep a separate TextAsset with a known name to hold the names of the assets in the AssetBundle.
可使用AssetBundle.LoadAll 去取回資源包中包含的全部對象的數組。不可能直接就取回一個列表。一般的作法是保持一個單獨的TextAsset,這個TextAsset是控制資源包中資源的名稱。
Once you have loaded an object from your AssetBundle, you can instantiate it in your scene with the Instantiate function.
下載了資源,也加載好了,那麼就該在場景中使用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); }
Unity doesn't provide an automatic way to retrieve a list of AssetBundles that have been downloaded. You can keep track of this information from a script by storing references to the AssetBundle objects and their URLs, say.
Unity不提供自動的一個能夠取回全部被下載資源的列表。因此須要咱們在腳本中要創建這些資源對象的信息和它們的路徑以便咱們去查找。
The first step is to save your binary data file with the ".bytes" extension. Unity will treat this file as a TextAsset. As a TextAsset the file can be included when you build your AssetBundle. Once you have downloaded the AssetBundle in your application and loaded the TextAsset object, you can use the .bytes property of the TextAsset to retrieve your binary data.
第一步要儲存文件的擴展名以" .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; }
AssetBundles can contain scripts as TextAssets but as such they will not be actual executable code. If you want to include code in your AssetBundles that can be executed in your application it needs to be pre-compiled into an assembly and loaded using the Mono Reflection class (Note: Reflection is not available on iOS). You can create your assemblies in any normal C# IDE (e.g. Monodevelop, Visual Studio) or any text editor using the mono/.net compilers.
資源包能夠做爲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); }
Any given asset in a bundle may depend on other assets. For example, a model may incorporate materials which in turn make use of textures and shaders. It is possible to include all an asset's dependencies along with it in its bundle. However, several assets from different bundles may all depend on a common set of other assets (eg, several different models of buildings may use the same brick texture). If a separate copy of a shared dependency is included in each bundle that has objects using it, then redundant instances of the assets will be created when the bundles are loaded. This will result in wasted memory.
任何在資源包中給出的資源可能主要依賴於其它的資源。舉個例子,一個模型可能混合多種紋理和材質球中的材質,可能包括全部的某個資源相關的東西,然而,一些從不一樣資源包文件夾中的資源或許都要用到相同的一些其它資源(好比說一些不一樣的建築模型會用到相同的紋理貼圖)。若是在每一個資源文件夾中包含一個被共享的資源要被某個對象用到,當資源文件加載的時候那就不須要去實例化多餘的對象,換句話說就是隻要把共享的資源實例化一次就能夠了,這樣就能夠大大減小內存的佔用。
To avoid such wastage, it is possible to separate shared dependencies out into a separate bundle and simply reference them from any bundles with assets that need them. First, the referencing feature needs to be enabled with a call to BuildPipeline.PushAssetDependencies. Then, the bundle containing the referenced dependencies needs to be built. Next, another call to PushAssetDependencies should be made before building the bundles that reference the assets from the first bundle. Additional levels of dependency can be introduced using further calls to PushAssetDependencies. The levels of reference are stored on a stack, so it is possible to go back a level using the correspondingBuildPipeline.PopAssetDependencies function. The push and pop calls need to be balanced including the initial push that happens before building.
要避免資源的浪費,能夠單獨創建一個專門的文件夾用來放要被共享的資源或者全部須要被加載的對象,官方提供的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來告訴程序這個模型全部的相關資源已經所有加載完成。
At runtime, you need to load a bundle containing dependencies before any other bundle that references them. For example, you would need to load a bundle of shared textures before loading a separate bundle of materials that reference those textures.
在運行時,須要考慮到優先加載資源的順序。舉個例子,如今有一張紋理貼圖,這張貼圖可能被不少個模型須要用到,而這個貼圖又有不少不一樣的材質,那就得先加載紋理貼圖,而後材質,最後纔是模型。
具體的代碼實現過程可參考AssetBundles Example Project中的AutoExportRescources這個腳本。
AssetBundles allow you to share content between different games. The requirement is that any Assets which are referenced by GameObjects in your AssetBundle must either be included in the AssetBundle or exist in the application (loaded in the current scene). To make sure the referenced Assets are included in the AssetBundle when they are built you can pass the BuildAssetBundleOptions.CollectDependencies option.
資源包容許用戶去共享資源包中的內容到其它不一樣的遊戲。若是須要共享,前提須要你已經創建好這個資源包共享文件。可使用BuildAssetBundleOptions.CollectDependencies這個函數來檢測是否已經創建好資源包文件。
When you build AssetBundles the assets are identified internally by their filename without the extension. For example a Texture located in your Project folder at "Assets/Textures/myTexture.jpg" is identified and loaded using "myTexture" if you use the default method. You can have more control over this by supplying your own array of ids (strings) for each object when Building your AssetBundle withBuildPipeline.BuildAssetBundleExplicitAssetNames.
當在內部創建資源包時,它們的文件名不包含擴展名就會被識別。舉個例子,一個在你項目工程目錄下好比說"Assets/Textures/myTextures.jpg"的貼圖是用"myTexture"來識別。若是使用默認的方法,當你用BuildPipeline.BuildAssetBundleExplicitAssetNames這個函數創建你的資源包,那你能夠有不少你本身編號的數組上的控制。
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; }
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 |
You can use WWW.LoadFromCacheOrDownload which automatically takes care of saving your AssetBundles to disk. Be aware that on the Webplayer you are limited to 50MB in total (shared between all webplayers). You can buy a separate caching license for your game if you require more space.
使用WWW.LoadFromCacheOrDownload就能夠自動在你的硬盤上存儲資源包文件。可是說明一下Webplayer被限制50MB的存儲空間。若是須要更多空間則能夠單獨爲遊戲購買緩存許可證。
Unity allows you to create an AssetBundle object from a byte[] array with AssetBundle.CreateFromMemory. You can use this as a way to enhance the security by encrypting your assetbundles before transmission and decrypt them at runtime.
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 }