Hay dos pasos principales involucrados cuando trabaje con AssetBundles. El primer paso es descargar el AssetBundle desde un servidor o una ubicación en disco. Esto se realiza a través de la clase WWW. El segundo paso es cargar los Assets desde el AssetBundle, en ser utilizados en la aplicación. Aquí hay un ejemplo de un script en C# de esto:
using UnityEngine;
using System.Collections;
public class BundleLoader : MonoBehaviour{
public string url;
public int version;
public IEnumerator LoadBundle(){
while (!Caching.ready)
yield return null;
using(WWW www = WWW.LoadFromCacheOrDownload(url, version)) {
yield return www;
AssetBundle assetBundle = www.assetBundle;
GameObject gameObject = assetBundle.mainAsset as GameObject;
Instantiate(gameObject);
assetBundle.Unload(false);
}
}
void Start(){
StartCoroutine(LoadBundle());
}
}
Este script es agregado al GameObject como Componente. El AssetBundle es cargado en la siguiente manera:
Por favor tenga en cuenta que por simplicidad el ejemplo previo no está haciendo ninguna revisión de seguridad. Por favor ver el código aquí para un ejemplo más complejo.
Como crear aplicaciones es un proceso iterativo, usted seguramente va a modificar sus Assets muchas veces, lo cual requeriría que se re-construyan los AssetBundles después de cada cambio para ser capaz de probarlos. Aunque sea posible cargar AssetBundles en el Editor, este no es flujo de trabajo recomendado. Más bien, mientras pruebe en el Editor, usted debería utilizar la función de ayuda Resources.LoadAssetAtPath para evitar que tenga que utilizar y re-construir AssetBundles. La función le permite a usted cargar el Asset como si fuera cargado desde un AssetBundle, mientras omite el proceso de construcción y sus Assets siempre están actualizados.
Lo siguiente es un ejemplo de un script de ayuda, que usted puede utilizar para cargar sus Assets dependiendo si usted está corriendo en el Editor o no. Coloque este código en un script C# llamado AssetBundleLoader.cs:
using UnityEngine;
using System.Collections;
public class AssetBundleLoader {
public Object Obj; // The object retrieved from the AssetBundle
public IEnumerator LoadBundle<T> (string url, int version, string assetName, string assetPath) where T : Object {
Obj = null;
#if UNITY_EDITOR
Obj = Resources.LoadAssetAtPath(assetPath, typeof(T));
if (Obj == null)
Debug.LogError ("Asset not found at path: " + assetPath);
yield break;
#else
WWW download;
if ( Caching.enabled ) {
while (!Caching.ready)
yield return null;
download = WWW.LoadFromCacheOrDownload( url, version );
}
else {
download = new WWW (url);
}
yield return download;
if ( download.error != null ) {
Debug.LogError( download.error );
download.Dispose();
yield break;
}
AssetBundle assetBundle = download.assetBundle;
download.Dispose();
download = null;
if (assetName == "" || assetName == null)
Obj = assetBundle.mainAsset;
else
Obj = assetBundle.Load(assetName, typeof(T));
assetBundle.Unload(false);
#endif
}
}
Ahora nosotros podemos utilizar el script AssetBundleLoader para cargar un Asset desde un AssetBundle si estamos corriendo la aplicación construida o cargar el Asset directamente desde la carpeta del Proyecto si está corriendo en el Editor:
using UnityEngine;
using System.Collections;
public class ExampleLoadingBundle : MonoBehaviour {
public string url = "http://www.mygame.com/myBundle.unity3d"; // URL where the AssetBundle is
public int version = 1; // The version of the AssetBundle
public string assetName = "MyPrefab"; // Name of the Asset to be loaded from the AssetBundle
public string assetPath; // Path to the Asset in the Project folder
private Object ObjInstance; // Instance of the object
void Start(){
StartCoroutine(Download());
}
IEnumerator Download () {
AssetBundleLoader assetBundleLoader = new AssetBundleLoader ();
yield return StartCoroutine(assetBundleLoader.LoadBundle <GameObject> (url, version, assetName, assetPath));
if (assetBundleLoader.Obj != null)
ObjInstance = Instantiate (assetBundleLoader.Obj);
}
void OnGUI(){
GUILayout.Label (ObjInstance ? ObjInstance.name + " instantiated" : "");
}
}
El script previo debería ser guardado a un archivo llamado ExampleLoadingBundle.cs dentro de la carpeta de Assets. Después de configurar las variables públicas a sus valores correctos y correrlas, se va a utilizar la clase AssetBundleLoader para cargar un Asset. Luego es instanciado y esto será mostrado al utilizar el GUI.
Usted puede utilizar WWW.LoadFromCacheOrDownload el cual automáticamente se ocupa de guardas sus AssetBundles en disco. Por favor tenga en cuenta que en el Webplayer usted está limitado a 50MB en total (compartido entre todos los webplayers). Usted puede comprar una licencia para almacenar en caché por separado para su juego si usted requiere más espacio.
Si sus AssetBundles están almacenados en la carpeta StreamingAssets como AssetBundles descomprimidos, usted puede utilizar AssetBundle.CreateFromFile para referenciar el AssetBundle en disco. Si los AssetBundles en la carpeta StreamingAssets están comprimidos, usted va a necesitar utilizar WWW.LoadFromCacheOrDownload para crear una copia descomprimida del AssetBundle en caché.
Los AssetBundles son compatibles entre algunas plataformas. Utilice la siguiente tabla como una guía.
Compatibilidad de plataforma para AssetBundles | |||||
Standalone | Webplayer (Reproductor Web) | iOS | Android | ||
Editor | Y | Y | Y* | Y* | |
Standalone | Y | Y | |||
Webplayer (Reproductor Web) | Y | Y | |||
iOS | Y | ||||
Android | Y |
Por ejemplo, un bundle creado mientras el que el objetivo de construcción Webplayer estaba activo sería compatible con el editor y con las construcciones strandalone. Sin embargo, no sería compatible con apps construidas para las plataformas iOS o Android.
(*) Los AssetBundles construidos para plataformas móviles podrían contener datos almacenados en un formato de plataforma específico y optimizado que es incompatible con la plataforma en dónde el editor está corriendo. Tenga en cuenta que es seguro asumir que los juegos publicados necesitan diferentes asset bundles por plataforma. Específicamente los shaders son diferentes entre plataformas.
E.G los datos de GI son almacenados en un formato optimizado por la arquitectura ARM y por lo tanto no se pueden cargar en CPUs x86. Los shaders son almacenados para una configuración OpenGLES 2 y no se pueden cargar por el Editor que utiliza el renderizador DX9/11 (pero funciona con el renderizador OpenGLCore). Durante el desarrollo, a usted se le recomienda utilizar el Simulation Mode (modo de simulación) mencionado en el tutorial AssetBundles y el AssetBundle Manager para evitar la incompatibilidad del Editor y plataformas móviles.
Cuando usted construya AssetBundles los assets son identificados internamente por su nombre de archivo sin la extensión. Por ejemplo, una Textura ubicada en la carpeta Project en “Assets/Textures/myTexture.jpg” es identificada y cargada utilizando “myTexture” si usted utiliza el método por defecto. Usted puede tener más control sobre esto al proporcionar su propio arreglo de ids (strings) para cada objecto cuando construya su AssetBundle con BuildPipeline.BuildAssetBundleExplicitAssetNames.
Los AssetBundles le permiten a usted compartir contenido entre diferentes juegos. El requerimiento is que cualquier assets que sea referenciado por GameObjects en su AssetBundle debe ser incluido en el AssetBundle. Para asegurarse que los assets referenciados sean incluidos en el AssetBundle cuando son construidos usted puede pasar la opción BuildAssetBundleOptions.CollectDependencies.
Los AssetBundles pueden contener una estructura llamada un type tree que permite información acerca de los tipos de assets para entender correctamente entre diferentes versiones de Unity. En plataformas de escritorio, el type tree es incluido por defecto pero puede desactivarse al pasar BuildAssetBundleOptions.DisableWriteTypeTree a la función BuildAssetBundle. Los Webplayers intrinsecamente dependen en el type tree por lo que siempre son incluido (ie, la opción DisableWriteTypeTree no tiene efecto). Type trees nunca son incluidos para los assetbundles móviles o de consola y por lo tanto usted necesitará re-construir estos bundles cuando el formato de serialización cambie. Esto puede suceder en nuevas versiones de Unity. (Excepto para lanzamientos de arreglos a bugs) También sucede si usted agrega o quita campos serializados en monobehaviour que son incluidos en el assetbundle. Cuando cargue un AssetBundle, Unity va a intentar darle un mensaje de error si el AssetBundle debe ser re-construido.
Usted puede utilizar AssetBundle.LoadAllAssets para recuperar un arreglo que contenga todos los objetos del AssetBundle. No es posible obtener una lista de los identificados directamente. Una solución alternativa común es mantener un TextAsset (asset de texto) separado para mantener los nombres de los assets en el AssetBundle.
Suponga que el Bundle A contiene un Prefab que tiene un material y una textura. Bundle B tiene una escena que tiene una instancia del mismo prefab. Bundle B necesita acceder al material. Al menos de que el material sea incluido en un asset bundle específico, será incluido en ambos bundle A y B.