Novedades sobre productos

Cómo optimizar el rendimiento para Android XR con Unity

Lectura de 6 min
Luke Hopkins
Ingeniero de Relaciones con Desarrolladores, Android

El Samsung Galaxy XR ya está aquí, con tecnología de Android XR. Esta entrada de blog forma parte de nuestra Semana de enfoque en Android XR, en la que proporcionamos recursos (entradas de blog, videos, código de muestra y mucho más) diseñados para ayudarte a aprender, compilar y preparar tus apps para Android XR.  

Esta semana, Samsung lanzó Galaxy XR, creado en colaboración con Google y Qualcomm. Este es un momento emocionante para los desarrolladores, y queremos ayudarte a obtener el mejor rendimiento posible de tu app de RE.

Si bien el rendimiento deficiente en juegos y apps en dispositivos que no son de XR puede ser frustrante para el usuario, en el mundo de la XR, el rendimiento no es solo opcional, sino fundamental para el éxito de tu app. Si no alcanzas el objetivo de velocidad de fotogramas en XR, puede causar problemas mucho más graves, como mareos. 

En esta guía, te explicaremos las optimizaciones de rendimiento esenciales que debes comprender para el desarrollo de Android XR. Aprenderás qué funciones ofrecen las mayores ganancias de rendimiento, cuándo usarlas y cómo funcionan en conjunto para ayudarte a alcanzar tus objetivos de velocidad de fotogramas.

Esto es lo que buscamos: 

  • Mínimo: 72 FPS (parte de nuestros lineamientos de calidad de Play)
  • Opcional: 90 FPS con un presupuesto de 11 ms por fotograma

Para obtener más información sobre por qué es importante mantener una velocidad de fotogramas tan alta, consulta nuestros lineamientos de rendimiento.   

Funciones de rendimiento específicas de XR

Comenzaremos con dos funciones de rendimiento específicas de la XR: renderización foveal y submuestreo de Vulkan. 

Renderización foveal

El renderizado foveal es una optimización que tiene dos modos. El primero es un modo estático que renderiza el centro de la pantalla con una resolución más alta y reduce progresivamente la resolución a medida que miras hacia afuera.

El segundo es el modo de seguimiento ocular, que renderiza específicamente el área en la que estás mirando con todo detalle, a la vez que reduce la calidad que se muestra en la periferia. Básicamente, imita el funcionamiento de la visión humana, en la que solo vemos detalles precisos en el área específica en la que nos enfocamos.

La renderización foveal reduce significativamente la carga de trabajo de la GPU sin sacrificar la calidad de imagen percibida por el usuario. La belleza del renderizado foveal es que los usuarios no notarán la calidad reducida en su visión periférica, pero tu GPU sí notará el rendimiento mejorado.

Imagina que estás creando una experiencia de museo con artefactos 3D complejos. Sin la renderización foveal, tendrías dificultades para mantener 90 FPS al intentar renderizar todo en el "campo visual". Con la renderización foveal, puedes mantener esos detalles de alta calidad donde mira el usuario, pero el entorno de fondo se renderiza con una calidad inferior. Tus usuarios no notarán la diferencia, pero tendrás espacio para agregar más detalles a la escena.

Submuestreo de Vulkan

El submuestreo de Vulkan es el mejor amigo de la renderización foveal. Mientras que el renderizado foveal decide qué renderizar en diferentes niveles de calidad, el submuestreo de Vulkan controla cómo renderizar de manera eficiente los diferentes niveles de calidad con mapas de densidad de fragmentos.

Cuando se combina con la renderización foveal, el submuestreo de Vulkan te brinda 0.5 ms adicionales de rendimiento. También ayuda a suavizar los bordes irregulares en la visión periférica, lo que hace que la imagen general se vea más nítida.

Por ejemplo, en un juego de simulador de vuelo en el que los usuarios se enfocan en los instrumentos y los controles, combinar el renderizado foveal con el submuestreo de Vulkan significa que los controles detallados se renderizan con nitidez, pero la estructura periférica de la cabina usa menos recursos. Esos 0.5 ms adicionales no parecen mucho, pero marcan la diferencia entre tener espacio para un elemento interactivo adicional o perder fotogramas durante momentos intensos.

Funciones de GPU para escenas complejas

Además del renderizado foveal y el submuestreo de Vulkan, hay algunas funciones de GPU que reducen la tensión innecesaria a través de la creación de instancias y el descarte inteligentes. Son particularmente eficaces para escenas complejas con geometría repetida o una oclusión significativa.

Cajón residente en la GPU

El cajón residente de la GPU usa automáticamente la creación de instancias de la GPU para reducir las llamadas de dibujo y liberar tiempo de procesamiento de la CPU. Por lo tanto, en lugar de que la CPU le indique a la GPU sobre cada objeto de forma individual, la GPU agrupa los objetos similares.

Esta función es más eficaz para escenas grandes con mallas repetidas, como árboles en un bosque, muebles en un edificio de oficinas o accesorios dispersos por un entorno.

Imagina una escena de un bosque con 200 árboles que usan la misma malla base. Sin el GPU Resident Drawer, tienes 200 llamadas de dibujo que consumen la GPU y, por lo tanto, liberan la CPU. Cuando habilites esta función, la GPU creará instancias de esos árboles de forma inteligente, lo que debería reducir la cantidad de llamadas de dibujo a entre 5 y 10. Esto representa un ahorro masivo de GPU que puedes invertir en la lógica del juego o en los cálculos de física.

GPU Occlusion Culling

GPU Occlusion Culling usa la GPU en lugar de la CPU para identificar y omitir la renderización de objetos ocultos. Detecta automáticamente lo que está oculto detrás de otros objetos, por lo que no desperdicias la GPU en elementos que el usuario no puede ver.

Esta función es especialmente útil en espacios interiores con varias habitaciones, entornos densos o escenas arquitectónicas en las que las paredes, los pisos y los objetos bloquean la vista de forma natural.

Por ejemplo, supongamos que estás creando una experiencia de casa con varias habitaciones. Cuando el usuario está en la sala de estar, ¿por qué desperdiciar ciclos de GPU renderizando la cocina completamente detallada que está completamente oculta detrás de una pared? El descarte por oclusión de la GPU omite automáticamente la renderización de esos objetos ocultos, lo que te brinda más presupuesto de rendimiento para lo que realmente es visible.

Supervisa tu rendimiento

No basta con usar estas funciones. También debes medir tus optimizaciones para cuantificar su impacto y verificar que los cambios realmente funcionen.

API de Metrics

La API de Performance Metrics proporciona supervisión en tiempo real del uso de memoria, el rendimiento de la CPU y el rendimiento de la GPU de tus apps. Te proporciona datos integrales de las capas de compositor y de tiempo de ejecución, para que puedas ver exactamente lo que sucede en tu aplicación.

Establece un valor de referencia antes de realizar los cambios, aplica una optimización, mide el impacto y realiza iteraciones. Este enfoque basado en datos significa que sabes que realmente estás mejorando el rendimiento en lugar de suponerlo.

Antes de habilitar el renderizado foveal, la latencia de fotogramas de la GPU podría ser de 13 ms, lo que supera tu presupuesto de 11 ms. Habilita la renderización foveal, vuelve a medir y, con suerte, verás que se reduce a 9 ms. Esto te da 4 ms de margen para agregar más detalles a la escena, mejorar la calidad visual en otros lugares o, simplemente, garantizar un rendimiento más fluido en una mayor variedad de contenido.

Sin estas métricas, la optimización se realiza sin datos. La API de Metrics te dice la verdad sobre lo que realmente ayuda a tu caso de uso específico.

Frame Debugger

El Frame Debugger es la herramienta integrada de Unity para comprender exactamente cómo se renderiza tu escena, fotograma por fotograma. Te muestra la secuencia de llamadas de dibujo y te permite recorrerlas paso a paso para verificar que tus optimizaciones funcionen correctamente.

¿Quieres confirmar que SRP Batcher funciona? Busca entradas "RenderLoopNewBatcher" en el depurador de fotogramas. ¿Se verifica si el cajón residente de la GPU se procesa por lotes correctamente? Busca las entradas "Hybrid Batch Group". Estas confirmaciones visuales te ayudan a comprender si la configuración de optimización realmente está surtiendo efecto.

Recorre los primeros 50 comandos de dibujo de tu escena. Si ves que los objetos similares se dibujan de forma individual en lugar de por lotes, significa que la creación de instancias o la creación de lotes no funcionan correctamente. El depurador de fotogramas hace que estos problemas sean visibles de inmediato para que puedas abordarlos.

Optimizaciones adicionales

Además de las optimizaciones que ya mencionamos, nuestra guía de rendimiento completa también incluye otras optimizaciones adicionales. A continuación, proporcionamos un breve resumen:

  • Configuración del URP: Inhabilita HDR y el procesamiento posterior para la XR en dispositivos móviles. Estas funciones proporcionan un impacto visual mínimo en comparación con su costo de rendimiento en el hardware para dispositivos móviles, por lo que obtendrás ganancias de rendimiento medibles con diferencias visuales apenas perceptibles.
  • SRP Batcher: Reduce la sobrecarga de la CPU para las escenas con muchos materiales que usan la misma variante de sombreador. Si minimizas los cambios de estado de renderización entre las llamadas de dibujo, puedes reducir significativamente el tiempo de CPU dedicado a la renderización.
  • Frecuencia de actualización de la pantalla: Se ajusta de forma dinámica entre 72 y 90 FPS según la complejidad de la escena. Reduce la velocidad de fotogramas durante las secuencias complejas para mantener la estabilidad y, luego, auméntala durante los momentos más simples para lograr una interacción muy fluida.
  • Texturas opacas o de profundidad: Inhabilita estas opciones, a menos que sean necesarias específicamente para los efectos de sombreador. Provocan operaciones de copia de GPU innecesarias que desperdician rendimiento sin proporcionar beneficios para la mayoría de las aplicaciones.
  • URP Render Scale: Este parámetro de configuración te permite renderizar con una resolución reducida para obtener beneficios de rendimiento o aumentar la resolución del renderizado para mejorar la calidad visual.

Para obtener instrucciones paso a paso sobre estas y otras optimizaciones, consulta nuestra Guía completa de rendimiento de Unity para Android XR.

Conclusión

El rendimiento de tu app de XR no es solo una casilla de verificación técnica. Es la diferencia entre una experiencia cómoda y atractiva, y una que hace que los usuarios se sientan mal o incómodos. Las optimizaciones que analizamos son tu kit de herramientas para alcanzar esos objetivos críticos de velocidad de fotogramas en los dispositivos XR más recientes.

Esta es tu hoja de ruta:

  1. Comienza con el renderizado foveal y el submuestreo de Vulkan. Estas funciones específicas para XR ofrecen ahorros inmediatos y notables en la GPU.
  2. Agrega GPU Resident Drawer y Occlusion Culling si tienes escenas complejas con geometría repetida o espacios interiores.
  3. Supervisa todo con la API de Metrics para asegurarte de que los cambios realmente ayuden.
  4. Explora optimizaciones adicionales del URP para obtener un margen de rendimiento adicional

Es fundamental medir continuamente y realizar iteraciones. No todas las optimizaciones beneficiarán a todos los proyectos por igual, por lo que debes usar la API de Metrics de rendimiento para tener una idea clara de lo que realmente ayuda a tu caso de uso específico.

Próximos pasos: Amplía tus habilidades

¿Quieres conocer más detalles? Consulta los siguientes recursos:

  • Guía de rendimiento de Unity para Android XR: Instrucciones de implementación paso a paso completas para todas las funciones que se abordan aquí.
  • Getting Started with Unity and Android XR: Configura tu entorno de desarrollo y comienza a compilar.
  • Documentación para desarrolladores de Android XR: Guías completas para todas las funciones de Android XR
Escrito por:

Seguir leyendo