Version: 5.4
Optimizando búsquedas con AssetBundles
Reduciendo el Tamaño del Archivo de la Construcción

AssetBundles PF (Preguntas Frecuentes)

¿Cómo uso un AssetBundle?

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:

  • El url y los valores de la versión deben ser configurados en el Inspector antes de correr este script. El url es la ubicación del archivo AssetBundle, usualmente un servidor en el internet. El número de versión le permite al desarrollador asociar un número al AssetBundle cuando sea escrito en caché en disco. Cuando descargue un AssetBundle Unity va a revisar si el archivo ya existe en el caché. Si sí, compara la versión del asset almacenado con la versión pedida. Si es diferente entonces el AssetBundle será re-descargado. Si es el mismo, entonces va a cargar el AssetBundle de disco y va a evitar que se re-descargue el archivo. Por favor referirse a la función WWW.LoadFromCacheOrDownload en la referencia de scripting para más información acerca de estos parámetros.
  • Cuando la función Start de este script es llamada, va a comenzar a cargar el AssetBundle al llamar la función como una Coroutine. La función va a esperar (yield) en el objeto WWW a medida que descarga el AssetBundle. Al utilizar esto, la función va simplemente parar en ese punto hasta que el objeto WWW haya terminado de descargar, pero no va a bloquear la ejecución del resto del código, este espera (yields) hasta que haya terminado. Hasta una sola descarga de AssetBundle puede finalizar por frame cuando son descargados con WWW.LoadFromCacheOrDownload.
  • Una vez el objeto WWW ha descargado el archivo AssetBundle, la propiedad .assetBundle es utilizada para obtener un objeto AssetBundle. Este objeto es la interfaz para cargar objetos del archivo AssetBundle.
  • En este ejemplo una referencia a un prefab en el AssetBundle es obtenida del AssetBundle utilizando la propiedad .mainAsset (asset principal). Esta propiedad es configurada cuando se construye el AssetBundle pasando un objeto como el primer parámetro. El asset principal en el AssetBundle puede ser utilizado para almacenar un TextAsset con una lista de objetos dentro del AssetBundle y cualquier otra información acerca de ellos.

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.

¿Cómo uso AssetBundles en el editor?

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.

Cómo puedo almacenar en caché los AssetBundles?

Se puede utilizar WWW.LoadFromCacheOrDownload el cual automáticamente se ocupa de guardas sus AssetBundles en disco. Es posible comprar una licencia para almacenar en caché por separado para su juego si se 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 multi-plataforma?

Los AssetBundles son compatibles entre algunas plataformas. Utilice la siguiente tabla como una guía.

Compatibilidad de plataforma para AssetBundles
Standalone iOS Android
Editor Y Y* Y*
Standalone Y
iOS Y
Android Y

(*) AssetBundles built for mobile platforms might contain data stored in an optimized, platform-specific format which is incompatible with the platform the Editor is running on. Note that it is safe to assume that published games needs different asset bundles per platform. Specifically shaders are different between platforms.

E.g. GI data is stored in a format optimized for ARM architecture and thus is not loadable on x86 CPUs. Shaders are stored for OpenGLES 2 configuration and are not loadable by the Editor which uses the DX9/11 renderer (but works with OpenGLCore renderer). During development, you are recommended to use Simulation Mode mentioned in AssetBundles and the AssetBundle Manager tutorial to avoid Editor and mobile platforms incompatibility.

Cómo son los assets en AssetBundles identificados?

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.

Puedo yo re-utilizar mis AssetBundles en otro juego?

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.

Un AssetBundle construido ahora puede ser utilizable con versiones futuras de Unity?

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.

Cómo puedo listar los objetos en un AssetBundle?

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.

Cómo los AssetBundles pueden referenciar otros assets en otros AssetBundles

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.

Optimizando búsquedas con AssetBundles
Reduciendo el Tamaño del Archivo de la Construcción