Version: 2021.1
Patching con AssetBundles
Unity Asset Bundle Browser tool

Solución de problemas

Esta sección describe varios problemas que comúnmente aparecen en proyectos que usan AssetBundles.

Duplicación de Assets

El sistema AssetBundle de Unity 5 descubrirá todas las dependencias de un Objeto cuando el Objeto esté integrado en un AssetBundle. Esto se hace usando la Asset Database. Esta información de dependencia se usa para determinar el conjunto de objetos que se incluirán en un AssetBundle.

Los objetos que están asignados explícitamente a un AssetBundle solo estarán integrados en ese AssetBundle. Un objeto se “asigna explícitamente” cuando AssetImporter de ese objeto tiene su propiedad assetBundleName establecida en un string no vacío.

Cualquier Objeto que no esté explícitamente asignado en un AssetBundle se incluirá en todos los AssetBundles que contengan 1 o más Objetos que hagan referencia al Objeto no etiquetado.

Si dos Objetos diferentes están asignados a dos AssetBundles diferentes, pero ambos tienen referencias a un Objeto de dependencia común, entonces ese Objeto de dependencia se copiará en ambos AssetBundles. La dependencia duplicada también se instanciará, lo que significa que las dos copias del objeto de dependencia se considerarán objetos diferentes con identificadores diferentes. Esto aumentará el tamaño total de los AssetBundles de la aplicación. Esto también causará que se carguen dos copias diferentes del Objeto en la memoria si la aplicación carga ambos de sus padres.

Hay varias formas de abordar este problema:

  1. Asegúrese de que los Objetos integrados en diferentes AssetBundles no compartan dependencias. Todos los objetos que comparten dependencias se pueden colocar en el mismo AssetBundle sin duplicar sus dependencias.

    • Este método generalmente no es viable para proyectos con muchas dependencias compartidas. Puede producir AssetBundles monolíticos que se deben reconstruir y volver a descargar con demasiada frecuencia para que sean convenientes o eficientes.
  2. Segmente AssetBundles para que no se carguen al mismo tiempo dos AssetBundles que comparten una dependencia.

    • Este método puede funcionar para ciertos tipos de proyectos, como juegos basados en niveles. Sin embargo, aún aumenta innecesariamente el tamaño de los AssetBundles del proyecto y aumenta los tiempos de compilación y carga.
  3. Asegúrese de que todos los activos de dependencia estén integrados en sus propios AssetBundles. Esto elimina por completo el riesgo de assets duplicados, pero también introduce complejidad. La aplicación debe realizar un seguimiento de las dependencias entre los AssetBundles y asegurarse de que se carguen los AssetBundles correctos antes de llamar a cualquier API de AssetBundle.LoadAsset.

En Unity 5, las dependencias de Objeto se rastrean a través de la API AssetDatabase, ubicada en el espacio de nombres de UnityEditor. Como el espacio de nombres lo implica, esta API solo está disponible en el Editor de Unity y no en tiempo de ejecución. AssetDatabase.GetDependencies se puede usar para localizar todas las dependencias inmediatas de un Objeto o Asset específico. Tenga en cuenta que estas dependencias pueden tener sus propias dependencias. Además, la API de AssetImporter se puede utilizar para consultar el AssetBundle al que está asignado un Objeto específico.

Al combinar las API AssetDatabase y AssetImporter, es posible escribir un script Editor que asegure que todas las dependencias directas o indirectas de AssetBundle estén asignadas a AssetBundles, o que no haya dos AssetBundles que compartan dependencias que no hayan sido asignadas a AssetBundle. Debido al costo de memoria de la duplicación de activos, se recomienda que todos los proyectos tengan ese script.

Duplicación del Sprite Atlas

Las siguientes secciones describen una peculiaridad del código de cálculo de dependencia de Assets de Unity 5 cuando se utiliza junto con atlas de sprites generados automáticamente.

Cualquier atlas de sprite generado automáticamente se asignará al AssetBundle que contiene los objetos de Sprite a partir de los cuales se generó el atlas de sprite. Si los Objetos de sprite están asignados a múltiples AssetBundles, entonces el atlas de sprite no se asignará a un AssetBundle y se duplicará. Si los objetos de Sprite no están asignados a un AssetBundle, entonces el atlas de sprite tampoco se asignará a un AssetBundle.

Para asegurarse de que los atlas de sprites no estén duplicados, verifique que todos los sprites etiquetados en el mismo atlas de sprite estén asignados al mismo AssetBundle.

Unity 5.2.2p3 y posterior

Los atlas de sprites generados automáticamente nunca se asignarán a un AssetBundle. Debido a esto, se incluirán en cualquier AssetBundles que contenga sus sprites constituyentes y también cualquier AssetBundles que haga referencia a sus sprites constituyentes.

Debido a este problema, se recomienda enfáticamente que todos los proyectos de Unity 5 que usen el empaquetador de sprites de Unity se actualicen a Unity 5.2.2p4, 5.3 o a una versión más reciente de Unity.

Para los proyectos que no pueden actualizar, existen dos soluciones para este problema:

  1. Fácil: evite usar el empacador de sprites incorporado de Unity. Los atlas Sprite generados por herramientas externas serán activos normales y se pueden asignar correctamente a un AssetBundle.

  2. Difícil: asigne todos los objetos que usen sprites atlased automáticamente al mismo AssetBundle como los sprites.

    • Esto asegurará que el atlas de sprite generado no se vea como la dependencia indirecta de ningún otro AssetBundles y no se duplicará.

    • Esta solución preserva el flujo de trabajo de usar el empaquetador de sprites de Unity, pero degrada la capacidad de los desarrolladores de separar los Assets en diferentes AssetBundles, y obliga a volver a descargar un atlas sprite completo cuando cualquier cambio de datos en cualquier componente que hace referencia al atlas, incluso si atlas en sí mismo no ha cambiado.

Texturas Android

Debido a la gran fragmentación de dispositivos en el ecosistema de Android, a menudo es necesario comprimir texturas en varios formatos diferentes. Si bien todos los dispositivos Android son compatibles con ETC1, ETC1 no admite texturas con canales alfa. Si una aplicación no requiere soporte OpenGL ES 2, la forma más limpia de resolver el problema es usar ETC2, que es compatible con todos los dispositivos Android OpenGL ES 3.

La mayoría de las aplicaciones deben enviarse a dispositivos más antiguos donde el soporte ETC2 no está disponible. Una forma de resolver este problema es con las Variantes AssetBundle de Unity 5. (Consulte la guía de optimización de Android de Unity para obtener detalles sobre otras opciones).

Para usar las Variantes AssetBundle, todas las texturas que no se pueden comprimir limpiamente con ETC1 se deben aislar en AssetBundles de solo texturas. A continuación, cree suficientes variantes de estos AssetBundles para admitir las secciones del ecosistema de Android que no sean ETC2, utilizando formatos de compresión de texturas específicos del proveedor como DXT5, PVRTC y ATITC. Para cada variante de AssetBundle, cambie las configuraciones de TextureImporter de texturas incluidas en el formato de compresión apropiado para la variante.

En tiempo de ejecución, se puede detectar la compatibilidad con los diferentes formatos de compresión de texturas utilizando la API SystemInfo.SupportsTextureFormat. Esta información se debe usar para seleccionar y cargar la variante AssetBundle que contiene texturas comprimidas en un formato compatible.

Se puede encontrar más información sobre los formatos de compresión de texturas de Android aquí.

Uso excesivo de la manipulación de archivos iOS

El problema descrito en la siguiente sección se corrigió en Unity 5.3.2p2. Las versiones actuales de Unity no se ven afectadas por este problema.

En versiones anteriores a Unity 5.3.2p2, Unity mantendría un identificador de archivo abierto para un AssetBundle durante todo el tiempo que se carga el AssetBundle. Esto no es un problema en la mayoría de las plataformas. Sin embargo, iOS limita el número de identificadores de archivos que un proceso puede tener abierto simultáneamente a 255. Si al cargar un AssetBundle se excede este límite, la llamada de carga fallará con un error de “Demasiadas Manchas abiertas de archivo”.

Este era un problema común para los proyectos que trataban de dividir su contenido entre cientos o miles de AssetBundles.

Para proyectos que no pueden actualizar a una versión parcheada de Unity, las soluciones temporales son:

  • Reducir el número de AssetBundles en uso mediante la fusión de AssetBundles relacionados
  • Uso de AssetBundle.Unload(false) para cerrar el identificador de archivo de AssetBundle y administrar manualmente los ciclos de vida de los Objetos cargados


Patching con AssetBundles
Unity Asset Bundle Browser tool