Cualquier dado asset en un bundle podría depender en otros assets. Por ejemplo, un modelo puede incorporar materiales que en devuelta hacen uso de texturas y shaders. Es posible incluir todas las dependencias de un asset en conjunto con su bundle. Sin embargo, varios assets de diferentes bundles podrían depender de un conjunto en común de otros assets (eg, varios diferentes modelos de edificios podrían utilizar la misma textura del ladrillo). Si una copia separada de una dependencia compartida es incluida en cada bundle que tiene objetos utilizándola, entonces instancias redundantes de los assets podrían ser creadas cuando los bundles son cargados. Esto va a resultar en perdida de memoria.
Para evitar tal desperdicio, es posible separar dependencias compartidas a bundles separados y simplemente referenciarlos de cualquier bundle con assets que los necesite. Primero, la característica de referencia necesita ser activada con una llamada a BuildPipeline.PushAssetDependencies. Luego, el bundle que contiene la dependencia referenciada necesita ser construida. Luego, otro llamado a PushAssetDependencies debería ser hecho antes de construir los bundles que referencia los assets del primer bundle. Varios niveles adicionales de dependencias pueden ser introducidas utilizando más llamadas a PushAssetDependencies. Los niveles de referencia son almacenados en una pila, por lo que es posible ir devuelta al nivel utilizando la función BuildPipeline.PopAssetDependencies correspondiente. Los llamados push y pop necesitan ser balanceados incluyendo el push inicial que sucede antes de construir.
En tiempo de ejecución, usted necesita cargar un bundle que contiene dependencias antes de cualquier otro bundle que los referencie. Por ejemplo, usted debería necesitar cargar un bundle de texturas compartidas antes de cargar un bundle separado de materiales que referencia aquellas texturas.
Si usted anticipa la necesidad de reconstruir assets bundles que son parte de una cadena de dependencias entonces usted debería construirlos con la opción BuildAssetBundleOptions.DeterministicAssetBundle habilitada. Esto garantiza que los valores ID internos utilizados para identificar assets serán los mismos cada vez que el bundle es re-construido.
Cuando construya el asset bundle con este método, los objetos en este son asignados un código hash de 32 bit que es calculado utilizando el nombre del archivo del asset bundle, el GUID del asset y el id local del objeto en el asset. Por esta razón asegúrese de utilizar el mismo nombre del archivo cuando re-construya. También tenga en cuenta que tener muchos objetos podrían causar colisiones hash previniendo que Unity construya el asset bundle.
Cuando sea que los shaders sean directamente referenciados como parámetros en BuildPipeline.BuildAssetBundle, o indirectamente con la opción BuildAssetBundleOptions.CollectDependencies el código shader es incluido con el asset bundle. Esto podría causar un problema si usted utiliza BuildAssetBundle solamente para crear varios asset bundles, ya que shaders referenciados serán incluidos en cada bundle generado. Debería haber conflictos i.e. cuando usted mezcla diferentes versiones de un shader, por lo que usted tendrá que re-construir todos sus bundles después de modificar los shaders. El código shader también aumentará el tamaño de los bundles. Para evitar estos problemas usted puede utilizar BuildPipeline.PushAssetDependencies para separar shaders en un solo bundle, y esto le va a permitir actualizar el shader bundle solamente. Como un ejemplo de cómo lograr este flujo de trabajo, usted puede crear un prefab que incluya referencias a los shaders requeridos.
using UnityEngine;
public class ShadersList : MonoBehaviour {
public Shader[] list;
}
Cree un objeto vacío, asigne el script, agregue los shaders a la lista y cree el prefab, i.e. “ShadersList”. Luego usted puede crear un exportador que genera todos los bundles y actualiza el bundle de shaders:
using UnityEngine;
using UnityEditor;
public class Exporter : MonoBehaviour {
[MenuItem("Assets/Export all asset bundles")]
static void Export() {
BuildAssetBundleOptions options =
BuildAssetBundleOptions.CollectDependencies |
BuildAssetBundleOptions.CompleteAssets |
BuildAssetBundleOptions.DeterministicAssetBundle;
BuildPipeline.PushAssetDependencies();
BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/ShadersList.prefab"), null, "WebPlayer/ShadersList.unity3d", options);
BuildPipeline.PushAssetDependencies();
BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/Scene1.prefab"), null, "WebPlayer/Scene1.unity3d", options);
BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/Scene2.prefab"), null, "WebPlayer/Scene2.unity3d", options);
BuildPipeline.PopAssetDependencies();
BuildPipeline.PopAssetDependencies();
}
[MenuItem("Assets/Update shader bundle")]
static void ExportShaders() {
BuildAssetBundleOptions options =
BuildAssetBundleOptions.CollectDependencies |
BuildAssetBundleOptions.CompleteAssets |
BuildAssetBundleOptions.DeterministicAssetBundle;
BuildPipeline.PushAssetDependencies();
BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/ShadersList.prefab"), null, "WebPlayer/ShadersList.unity3d", options);
BuildPipeline.PopAssetDependencies();
}
}
Tenga en cuenta que usted debe cargar el shader bundle primero. Un problema de este método es que la opción BuildAssetBundleOptions.DeterministicAssetBundle puede producir conflictos debido a hashes que colisionan cuando la cantidad de objetos es muy grande. En este caso, la construcción va a fallar, y no será posible actualizar el shader bundle por sí mismo. En este caso, usted tendrá que quitar la opción y re-construir todos los asset bundles.