Este es el primero de una serie de artículos que desglosan consejos de optimización para sus proyectos de Unity. Úselos como guía para ejecutar a velocidades de fotogramas más altas con menos recursos. Una vez que haya probado estas mejores prácticas, asegúrese de consultar las otras páginas de la serie:
- Optimización del rendimiento para gráficos de alta gama.
- Administrar el uso de GPU para juegos de PC y consola
- Programación avanzada y arquitectura de código.
- Rendimiento físico mejorado para un juego fluido
Asset Pipeline puede afectar drásticamente la productividad de su equipo y el rendimiento de su juego. Al trabajar con un artista técnico experimentado, su equipo estará equipado para definir y hacer cumplir los formatos y especificaciones de los activos para procesos fluidos.
No confíe en la configuración predeterminada. Utilice la pestaña Anular específica de la plataforma para optimizar activos como texturas y geometría de malla. Una configuración incorrecta puede generar tamaños de compilación más grandes, tiempos de compilación más prolongados y un rendimiento de la GPU y un uso de memoria deficientes. Considere utilizar la función Presets para personalizar aún más la configuración de referencia para su proyecto.
Consulte esta guía para conocer las mejores prácticas para trabajar con recursos artísticos. Para obtener una guía específica para dispositivos móviles, consulte el curso Unity Learn sobre optimización de arte 3D para aplicaciones móviles.
En la Configuracióndel reproductor , deshabilite la API de gráficos automáticos y elimine las API de gráficos adicionales que no planea admitir para cada una de sus plataformas específicas. Esto puede evitar la generación de variantes de sombreado excesivas. Deshabilite la configuración de Arquitecturas de destino para CPU más antiguas si su aplicación no las admite.
Obtenga más información sobre la API de gráficos.
Cambiar el backend de secuencias de comandos de Mono a IL2CPP (lenguaje intermedio a C++) puede proporcionar un mejor rendimiento general en tiempo de ejecución. Sin embargo, también puede aumentar los tiempos de construcción. Algunos desarrolladores prefieren usar Mono localmente para una iteración más rápida y luego cambiar a IL2CPP para compilar máquinas y/o lanzar candidatos. Consulte la documentación sobre Optimización de los tiempos de compilación de IL2CPP para obtener más información sobre cómo reducir los tiempos de compilación.
*NOTA*: Al usar esta opción, Unity convierte ILcode de scripts y ensamblados a C++ antes de crear un archivo binario nativo (.exe, .apk, .xap) para su plataforma de destino.
Consulte la Introducción a los aspectos internos de IL2CPP o consulte la página del manual de opciones del compilador para saber cómo las diversas opciones del compilador afectan el rendimiento del tiempo de ejecución.
Los proyectos móviles deben equilibrar la velocidad de fotogramas con la duración de la batería y la limitación térmica. Piense en los fotogramas por segundo (fps).
En lugar de superar los límites de su dispositivo a 60 fps, considere ejecutar a 30 fps como un compromiso. Tenga en cuenta que Unity ya tiene por defecto 30 fps para dispositivos móviles.
También puede ajustar la velocidad de fotogramas dinámicamente durante el tiempo de ejecución con Application.targetFrameRate. Por ejemplo, puedes bajar de 30 fps para escenas lentas o relativamente estáticas (como menús) y reservar configuraciones de fps más altas para el juego.
Las plataformas móviles no renderizarán medios fotogramas. Incluso si deshabilita Vsync en el Editor (Configuración del proyecto > Calidad), todavía está habilitado a nivel de hardware. Si la GPU no puede actualizarse lo suficientemente rápido, el fotograma actual se mantendrá y, como resultado, se reducirán los fps.
Más información está disponible en la documentación.
Unity sondea el acelerómetro de tu móvil varias veces por segundo. Desactívelo si no se utiliza en su aplicación o reduzca su frecuencia para obtener un mejor rendimiento.
Obtenga más información sobre el acelerómetro.
Divide tus jerarquías. Si sus GameObjects no necesitan estar anidados en la Jerarquía, simplifique la crianza.
Las jerarquías más pequeñas se benefician del subproceso múltiple para actualizar las transformaciones en su escena. Las jerarquías complejas generan cálculos de transformación innecesarios y costos de recolección de basura (GC).
Consulte Optimización de la jerarquía y esta charla de Unite para obtener consejos sobre transformaciones.
Los dos ejemplos anteriores utilizan el mismo modelo y textura; sin embargo, las configuraciones de arriba consumen más de cinco veces la memoria en comparación con las de abajo, sin una calidad visual mucho mejor.
La compresión de texturas ofrece importantes beneficios de rendimiento cuando se aplica correctamente, como tiempos de carga más rápidos, una menor huella de memoria y un rendimiento de renderizado dramáticamente aumentado. Las texturas comprimidas utilizan sólo una fracción del ancho de banda de memoria necesario para las texturas RGBA de 32 bits sin comprimir.
Consulte esta lista recomendada de formatos de compresión de texturas para plataformas de destino.
Las texturas pueden utilizar potencialmente un exceso de recursos, por lo que optimizar la configuración de importación es fundamental. En general, intenta seguir estas pautas:
- Reduzca el tamaño máximo: utilice la configuración mínima que produzca resultados visualmente aceptables. Esto no es destructivo y puede reducir rápidamente la memoria de textura.
- Utilice potencias de dos (POT): Unity requiere dimensiones de textura POT para los formatos de compresión de texturas.
- Desactive la opción Lectura/Escritura habilitada: cuando está habilitada, esta opción crea una copia en la memoria direccionable de la CPU y la GPU, duplicando la huella de memoria de la textura. Deshabilítelo en la mayoría de los casos y habilítelo solo si genera una textura en tiempo de ejecución que necesita sobrescribir. También puede aplicar esta opción a través de Texture2D.Apply, pasando makeNoLongerReadable configurado en True.
- Deshabilite los mapas Mip innecesarios: los mapas Mip no son necesarios para texturas que permanecen en un tamaño constante en pantalla, como Sprites 2D y gráficos UI. Sin embargo, deje Mip Maps habilitado para modelos 3D que varían en distancia desde la cámara.
Obtenga más información sobre la configuración de importación de texturas.
Atlasing es el proceso de agrupar varias texturas más pequeñas en una sola textura más grande. Los Atlas de texturas reducen el uso de memoria y requieren menos llamadas de extracción, lo que disminuye el esfuerzo requerido por la GPU.
- Para proyectos 2D: Utilice un Sprite Atlas (Activo > Crear > 2D > Sprite Atlas) en lugar de renderizar sprites o texturas individuales.
- Para proyectos 3D: Puede utilizar el paquete de creación de contenido digital (DCC) de su elección. También se pueden utilizar varias herramientas de terceros como MA_TextureAtlasser o TexturePacker para crear Atlas de texturas.
Combine texturas y reasigne UV para cualquier geometría 3D que no requiera mapas de alta resolución. Un editor visual le brinda la posibilidad de establecer y priorizar los tamaños y posiciones en Texture Atlas o Sprite Sheet.
Texture Packer consolida los mapas individuales en una textura grande. Luego, Unity puede emitir una única llamada de sorteo para acceder a las texturas empaquetadas con una sobrecarga de rendimiento menor.
Lea más sobre Sprite Atlases aquí.
Los modelos de alta resolución requieren más uso de memoria y potencialmente más trabajo para la GPU. Como tal, intenta mantener al mínimo la complejidad geométrica de los GameObjects en tus escenas. De lo contrario, Unity tiene que enviar datos de vértices importantes a la tarjeta gráfica.
La mejor práctica es reducir los modelos en su software DCC y eliminar los polígonos invisibles desde el punto de vista de la cámara. Por ejemplo, si nunca ves la parte trasera de un armario apoyada contra una pared, el modelo no debería tener ninguna cara allí.
Tenga en cuenta que en las GPU modernas, el cuello de botella suele estar relacionado con la densidad de polígonos y no con el número de polígonos. Intente realizar una pasada artística por todos los recursos para reducir el número de polígonos de objetos distantes. Los microtriángulos pueden ser una causa importante del bajo rendimiento de la GPU.
Dependiendo de la plataforma de destino, piense en agregar detalles a través de texturas de alta resolución para compensar la geometría de baja poli. Utilice texturas y mapas normales en lugar de aumentar la densidad de la malla. Reduzca la complejidad de los píxeles integrando tantos detalles como sea posible en las texturas. Por ejemplo, puede capturar las luces especulares en la textura misma para evitar calcular las luces en el sombreador de fragmentos.
Sea consciente y recuerde crear perfiles con regularidad. Después de todo, estas técnicas afectan el rendimiento y es posible que no sean adecuadas para su plataforma de destino.
Al igual que las texturas, las mallas pueden consumir un exceso de memoria si no se importan con cuidado. Pruebe estos consejos para minimizar el consumo de memoria de sus mallas:
- Compresión de malla: La compresión de malla puede reducir el espacio en disco (aunque la memoria en tiempo de ejecución no se ve afectada). Al mismo tiempo, la cuantización de malla puede generar inexactitud, así que experimente con niveles de compresión para ver qué funciona para sus modelos.
- Deshabilitar lectura/escritura: habilitar esta opción duplica la malla en la memoria, lo que mantiene una copia de la malla en la memoria del sistema y otra en la memoria de la GPU. En la mayoría de los casos, deberías desactivarlo. En Unity 2019.2 y versiones anteriores, esta opción está marcada de forma predeterminada.
- Deshabilite plataformas y combine formas: Si su malla no necesita animación de forma esquelética o combinada, desactive estas opciones.
- Deshabilitar normales y tangentes: Si está absolutamente seguro de que el material de la malla no necesitará normales ni tangentes, desmarque estas opciones para obtener ahorros adicionales.
Hay opciones adicionales de optimización de malla disponibles en la Configuración del reproductor:
- Compresión de vértices establece la compresión de vértices de cada canal. Por ejemplo, puede habilitar la compresión para todo excepto las posiciones y los UV del mapa de luz. Esto puede reducir el uso de memoria en tiempo de ejecución de sus mallas.
- *NOTA*: La configuración de Compresión de malla en la Configuración de importación de cada malla anula la configuración de Compresión de vértice. En ese caso, la copia en tiempo de ejecución de la malla no está comprimida y podría utilizar más memoria.
- Optimizar datos de malla elimina cualquier dato de las mallas que no sea requerido por el material aplicado a ellas (como tangentes, normales, colores y UV).
Al automatizar el proceso de auditoría, puede evitar cambiar accidentalmente la configuración de los activos. AssetPostProcessor puede ayudarle a estandarizar su configuración de importación o analizar activos existentes. Le permite ejecutar scripts al importar activos y, esencialmente, le solicita que personalice la configuración antes y/o después de importar modelos, texturas, audio y más.
Lea más sobre la auditoría de activos en la guía Comprensión de la optimización.
Unity utiliza un búfer de anillo para enviar texturas a la GPU. Puede ajustar manualmente este búfer de textura asíncrono a través de QualitySettings.asyncUploadBufferSize.
Si la velocidad de carga es demasiado lenta o el hilo principal se detiene al cargar varias texturas a la vez, ajuste estos búferes de textura. Generalmente puedes establecer el valor (en MB) al tamaño de la textura más grande que necesitas cargar en la escena.
Tenga en cuenta que cambiar los valores predeterminados puede generar una alta presión en la memoria. Además, no puede devolver la memoria circular al sistema después de que Unity la asigne. Si la memoria de la GPU se sobrecarga, la GPU descarga la textura más reciente y menos utilizada y obliga a la CPU a volver a cargarla la próxima vez que ingrese al frustum de la cámara.
Explore todas las restricciones de memoria para los buffers de textura en el tutorial de administración de memoriay consulte Optimización del rendimiento de carga para ver cómo puede mejorar los tiempos de carga.
El sistema Mip Map Streaming le brinda control sobre qué niveles de Mip Map deben cargarse en la memoria. Habilítelo yendo a la configuración de Calidad de Unity (Edición > Configuración del proyecto > Calidad) y marque la opción Transmisión de textura . Puede habilitar la transmisión de mapas Mip en la Configuración de importación de texturas en Avanzado.
Este sistema reduce la cantidad total de memoria necesaria para las texturas porque solo carga los mapas Mip necesarios para representar la posición actual de la cámara. De lo contrario, Unity carga todas las texturas de forma predeterminada.
Texture Streaming intercambia una pequeña cantidad de recursos de CPU para ahorrar una cantidad potencialmente grande de memoria de GPU. También reduce automáticamente los niveles de Mip Map para permanecer dentro del presupuesto de memoriadefinido por el usuario.
Puede utilizar la API Mip Map Streaming para un mayor control.
El sistema de activos direccionables simplifica la gestión de los activos que componen tu juego. Cualquier recurso, incluidas escenas, prefabricados, recursos de texto, etc., se puede marcar como direccionable y recibir un nombre único. Luego puedes llamar a este alias desde cualquier lugar.
Agregar este nivel adicional de abstracción entre el juego y sus activos puede simplificar ciertas tareas, como crear un paquete de contenido descargable por separado. Las direcciones direccionables también facilitan la referencia a esos paquetes de activos, ya sean locales o remotos.
Instale el paquete Addressables desde el Administrador de paquetes. Como resultado, cada activo o casa prefabricada del proyecto tiene la capacidad de volverse "direccionable".
Al marcar la opción debajo del nombre de un activo en el Inspector, se le asigna una dirección única y predeterminada. Una vez marcados, los activos correspondientes aparecen en la ventana Ventana > Gestión de activos > Direcciones > Grupos .
Ya sea que el activo esté alojado en otro lugar o almacenado localmente, el sistema lo ubicará utilizando la cadena de Nombre direccionable . Una casa prefabricada direccionable no se carga en la memoria hasta que se necesita y luego descarga automáticamente sus activos asociados cuando ya no está en uso. Esta publicación de blog sobre Cómo ahorrar memoria con direccionables demuestra cómo puede organizar sus grupos direccionables para ser más eficiente con la memoria.
Ver Direccionables: Introducción a los conceptos para obtener una descripción general rápida de cómo el sistema de activos direccionables puede funcionar en su proyecto.
Una de nuestras guías más completas recopila más de 80 consejos prácticos sobre cómo optimizar tus juegos para PC y consola. Creados por nuestros ingenieros expertos en Success and Accelerate Solutions, estos consejos detallados te ayudarán a aprovechar al máximo Unity y mejorar el rendimiento de tu juego.