Esta página proporciona pautas y prácticas recomendadas sobre cómo optimizar el rendimiento en dispositivos móviles y obtener la mayor fidelidad posible de las funciones de rango dinámico alto en dispositivos móviles. Entre estos aspectos se incluyen:
Información sobre los factores que contribuyen a tu presupuesto de rendimiento en dispositivos móviles
Prácticas recomendadas para empaquetar proyectos con funciones de rango dinámico alto para móviles habilitadas
Una tutorial por las herramientas disponibles para medir la sobrecarga en el rendimiento de tus aplicaciones de Unreal Engine.
Los siguientes enlaces contienen información útil sobre temas generales de rendimiento en Android:
Conocer tu presupuesto de rendimiento
El dispositivo objetivo para tu aplicación dispone de una cantidad finita de recursos disponibles, tanto para almacenar objetos en la memoria como para procesarlos. Al compilar tu aplicación, debes decidir en qué gastar esos recursos. Deberías familiarizarte con las capacidades de tu dispositivo en términos de velocidad, subprocesos y ancho de banda de la CPU y la GPU, así como con la memoria del dispositivo, la memoria gráfica y el espacio disponible en disco.
También deberías realizar comparativas de tu dispositivo para saber cómo funcionará y dónde encontrará sobrecargas en el rendimiento. Puedes realizar comparativas de un dispositivo ejecutando una aplicación exigente o una demostración técnica en él, y observando sus estadísticas de rendimiento.
Comandos de consola para mostrar estadísticas de rendimiento
Puedes consultar las estadísticas de rendimiento con una serie de comandos de consola. Para abrir la consola de desarrolladores en un dispositivo móvil, pulsa sobre la pantalla con cuatro dedos a la vez. Esto abrirá un teclado en pantalla y un diálogo donde podrás introducir comandos de consola.
La consola y el comando de toque con cuatro dedos solo están disponibles en las compilaciones de desarrollo. No están disponibles en las versiones de distribución o prueba.
Dentro de la consola, puedes introducir comandos para mostrar información de depuración en la pantalla. La siguiente tabla incluye una lista de comandos que proporcionan información sobre el rendimiento:
| Comando | Descripción |
|---|---|
Stat GPU | Muestra el tiempo en milisegundos que emplea la GPU en distintos procesos. Algunos dispositivos que ejecutan Vulkan pueden ser compatibles con stat GPU, pero no es compatible directamente con la mayoría de los dispositivos móviles. |
Stat Unit | Muestra el tiempo en milisegundos que emplea la CPU en distintos procesos. También muestra el subproceso del juego, el subproceso de renderizado y los tiempos de la GPU. |
Stat UnitGraph | Muestra un gráfico con el uso de la CPU y la GPU a lo largo del tiempo. Esto puede ayudar a identificar picos. |
Stat TextureGroup | Muestra la cantidad de memoria utilizada por los distintos grupos de texturas. |
Si quieres conocer más comandos de consola para analizar el rendimiento de tu aplicación en el dispositivo, consulta Comandos Stat.
Factores comunes de rendimiento
Ahora que ya sabes dónde buscar los datos de rendimiento en tu dispositivo, esta sección te familiarizará con los factores que más suelen afectar al rendimiento en los renderizadores de dispositivos móviles de Unreal Engine. Si sabes cuáles de estos elementos están afectando a tu aplicación y cómo, podrás identificar y solucionar los problemas rápidamente con las herramientas de diagnóstico de Unreal Engine.
Mapas normales frente a mallas de alta densidad de vértices
Los renderizadores para dispositivos móviles de Unreal Engine son eficientes a la hora de renderizar grandes cantidades de vértices, mientras que los mapas normales de alta calidad en renderizadores para móviles pueden tener problemas con la profundidad de bits y suponer un mayor coste de rendimiento que un modelo con muchos polígonos.
En hardware de gama baja, los mapas normales pueden mejorar enormemente la calidad de los reflejos y la iluminación en la superficie de un modelo. Sin embargo, las formas sutiles, como los paneles de la carrocería de un coche, pueden exceder los deltas de 8 bits que se utilizan normalmente para estos mapas, lo que resulta en bandas visibles en el renderizado final.
Puedes utilizar mapas normales de 16 bits para compensar esto, pero el coste en píxeles de las normales de 16 bits supera el coste en vértices de una malla de mayor densidad. Las normales de 16 bits no están comprimidas en el motor, lo que significa que también son ocho veces más grandes que un mapa normal.
En el ejemplo de abajo, utilizamos paneles de carrocería de alta densidad sin mapas normales. En el caso del Galaxy Tab S6, los paneles de nuestra carrocería suman unos 500 000 vértices.
Prácticas recomendadas para mapas normales de alta resolución
Hacer el bake de vértices de alta resolución en un mapa normal para un modelo con pocos polígonos puede ser un proceso complejo, y muchos factores pueden reducir la calidad de la textura de un mapa normal cuando se encuentra dentro del motor. Existen muchos conjuntos de herramientas para realizar el bake de mapas normales, pero recomendamos xNormal. El proceso que utilizamos para xNormal es más o menos el siguiente:
Realiza el bake del mapa normal en xNormal como un TIFF de 8k con 4xAA.
Importa el archivo TIFF a Photoshop y reduce su resolución a una textura de 1K.
Aplica un desenfoque gaussiano con un valor de 0,35 px.
Convierte la imagen de 16 bits a 8 bits.
Exporta la imagen a un TGA de 24 bits.
Importa el mapa normal final en Unreal.
Para garantizar que las normales de superficie usadas en el proceso de baking son las mismas que las presentes en el motor, deberías exportar las normales optimizadas desde dentro de Unreal. Importa el modelo de baking a UE, elige si crear sus propias normales, y luego exporta el modelo de baking de UE para que se realice el bake en xNormal. Este es un paso importante a la hora de crear mapas normales de alta resolución, ya que xNormal necesita conocer las normales de superficie de la malla para aplicar las desfases del modelo de alta resolución.
Por último, hay dos opciones que reducirán los artefactos al renderizar mallas estáticas:
Usar UV de precisión absoluta
Usar base de tangentes de alta precisión
Ambos ajustes están disponibles en el Editor de mallas estáticas, dentro del panel de detalles , debajo de los LOD.
Dibujar llamadas
Las peticiones de trazado son búsquedas de recursos que se producen en cada fotograma. La cantidad de peticiones de trazado que utiliza tu aplicación depende de la cantidad de mallas únicas que haya en tu escena, así como de la cantidad de identificadores de materiales únicos que utilice cada malla. Actualmente, un alto número de peticiones de trazado es lo que más contribuye a un bajo rendimiento gráfico, y deberías reducirlas tanto como sea posible.
Por ejemplo, un modelo de coche altamente optimizado puede tener solo cinco o seis mallas separadas, y cada uno de esos componentes puede tener un único material.
Un buen objetivo para las peticiones de trazado en una escena optimizada es aproximadamente 700 en un Galaxy Tab S6, y menos de 500 en hardware de gama baja. En proyectos para HMI, que tienden a utilizar materiales muy únicos o complejos, 100 peticiones de trazado sería un buen objetivo en un Galaxy Tab S6, mientras que menos de 50 sería preferible.
Puedes producir el recuento de peticiones de trazado con el comando de consola Stat RHI.
Ten en cuenta que el recuento de peticiones de trazado cambiará en función de si estás en PIE o en el dispositivo. |
Cómo reducir el recuento de mallas
La forma más sencilla de reducir las peticiones de trazado es reducir el número de mallas únicas en tu mundo. Para ello, puedes combinar tantos objetos como sea posible en una sola malla con un conjunto de herramientas de creación de contenido digital (DCC), como Maya, 3DSMax o Blender, antes de importarlos a Unreal.
Cómo reducir el recuento de ID de materiales
Existen varias opciones posibles para reducir el número de materiales únicos en una malla.
El método más sencillo es utilizar un programa como Substance Painter, que integra varios materiales en la misma textura. Esto te permite aprovechar una gran cantidad de tipos de material en un material de UE muy simple, que luego utilizar usar como base para instancias de material con entradas de texturas simples. Esto también puede reducir el recuento de instrucciones de materiales, lo que mejora aún más el rendimiento.
El segundo método utiliza el enmascaramiento para un enfoque más procedimental. Los materiales pueden denotar ciertas características de una superficie, como el color, la rugosidad o las cualidades metálicas. En lugar de utilizar un material distinto para las diferentes partes de una malla, puedes utilizar máscaras para separar partes de los UV de una malla y aplicar distintos ajustes a cada sección. Puedes crear una máscara básica utilizando una textura en blanco y negro, pero es más eficiente utilizar colores de vértices.
En el ejemplo de abajo, los colores de vértices se utilizan para definir diferentes tipos de material, y el material define parámetros que pueden influir en el aspecto de esas piezas individualmente. El enmascaramiento de colores de vértices es más eficiente y crea una separación más nítida, ya que no depende de la resolución de la textura.
Materiales
La complejidad del material puede aumentar el coste en píxeles de un renderizado. Cuantas más instrucciones haya para cada píxel, más tiempo tendrá que dedicar el renderizado a calcular su valor final. Los materiales opacos son los menos costosos, pero pueden variar mucho según el modelo de sombreado o el código base del sombreador.
Puedes consultar el recuento de instrucciones de un material en la ventana Estadísticas del Editor de materiales.
El recuento de instrucciones también aumentará en función del número de funciones matemáticas que haya en un material. Cuántos más nodos haya, más costoso será renderizar el material. Algunas operaciones concretas también tienen un coste superior. Intenta limitar el número de instrucciones cuando compiles materiales más complejos.
Los materiales traslúcidos y transparentes son algunos de los tipos de materiales más caros. Las capas individuales de traslucidez tienen un elevado coste por píxel, y cuando se apilan y renderizan varias capas de transparencia, el coste es mucho mayor. Esto se conoce como superposición de píxeles.
Los faros y las luces traseras de los vehículos son ejemplos de áreas problemáticas con la transparencia. En muchos casos, utilizamos en cambio mapas de texturas pintados a mano para reducir la complejidad de los materiales. Las formas complejas y la profundidad se pueden ilustrar bien, incluso con una textura plana.
Cómo optimizar la resolución de las texturas
Las texturas de alta resolución requieren mucho espacio, tanto para su almacenamiento en un dispositivo como en la memoria de texturas del mismo, y las texturas más grandes requieren más píxeles para renderizarse y procesarse. Aunque pueden aumentar la fidelidad, el tamaño de las texturas tiene rendimientos decrecientes en función de la resolución de pantalla de tu dispositivo y del ángulo de visión de la textura. Es importante utilizar la textura más pequeña posible para obtener el nivel de fidelidad deseado.
Para determinar tus necesidades de textura, primero debes definir la posición de la cámara y el campo de visión (FOV) desde el que verás tu modelo. Esto ayudará a determinar el espacio en pantalla de todas las mallas y materiales.
Una vez determinada la posición de la cámara, puedes utilizar una textura de depuración especial para determinar la resolución de la textura que se utilizará para los distintos materiales. Esta textura utiliza el comportamiento de los mapas MIP para determinar la resolución necesaria para los distintos componentes, aplicando distintos colores a cada mapa MIP. Esto facilita la identificación de qué MIP está utilizando el material y qué resolución de textura debería utilizarse.
Conecta la textura incluida en el canal emisivo de un material Unlit y luego aplica ese material a tu malla. Al observar la malla desde la distancia de cámara adecuada, el código de colores indicará qué nivel de MIP está utilizando el motor para renderizar. El nivel más alto observado debería ser el tamaño de textura nativo de tus mapas de oclusión ambiental y normal.
Tamaño del paquete y tiempo de arranque
Al empaquetar una aplicación y sus recursos, existe un equilibrio entre el tamaño del paquete en el disco y el rendimiento de arranque en tiempo de ejecución.
Cuando la compresión ZLib está habilitada, el tamaño del paquete de tu aplicación será menor. Sin embargo, esto requiere más tiempo de la CPU para cargar la aplicación, lo que puede ralentizar la velocidad de arranque. Para optimizar el tiempo de arranque, puedes deshabilitar la compresión.
Ajustes de transmisión recomendados
Se recomiendan los siguientes ajustes de transmisión en DefaultEngine.ini. Esto proporciona tiempo adicional al inicio de una aplicación para la carga asincrónica de recursos, lo que puede mejorar el tiempo de arranque.
[/Script/Engine.StreamingSettings]
s.PriorityAsyncLoadingExtraTime=275.0
s.LevelStreamingActorsUpdateTimeLimit=250.0
s.PriorityLevelStreamingActorsUpdateExtraTime=250.0Ajustes de empaquetado recomendados
Se recomiendan los siguientes ajustes de empaquetado en DefaultEngine.ini. Estos ajustes reducen la cantidad de compresión que se utiliza al empaquetar recursos, ya que los archivos .pak sin comprimir se cargan significativamente más rápido que los archivos comprimidos con ZLib al iniciar.
[/Script/UnrealEd.ProjectPackagingSettings]
bCompressed=False
BuildConfiguration=PPBC_Development
bShareMaterialShaderCode=True
bSharedMaterialNativeLibraries=True
bSkipEditorContent=TrueCómo analizar el tamaño de los paquetes en el disco
UE cuenta con varias herramientas útiles que pueden proporcionar información sobre la huella de datos de los recursos.
Mapa de tamaños
El mapa de tamaño lee y compara el consumo relativo de memoria de los recursos en el editor. Para utilizar esto, debes activar el complemento AssetManagerEditor. Después, puedes acceder a él haciendo clic con el botón derecho en una carpeta en el Explorador de contenido y seleccionando Mapa de tamaño en el menú contextual.
El mapa de tamaño muestra una ventana con iconos que representan la cantidad de memoria que consumen las carpetas y los archivos. Cuanto más grande sea el icono, más espacio ocupará el archivo.
Para obtener más información sobre el uso del mapa de tamaño, consulta Cooking and Chunking (cooking y fragmentación).
El mapa de tamaño lee la huella de los recursos a medida que se utilizan en el editor. Después de empaquetar tu proyecto, el consumo de memoria será diferente. Esto se debe a los distintos tipos de compresión que se producen durante el proceso de cooking. Como regla general, el mapa de tamaño representará el tamaño más grande posible que podría tener un recurso.
Estadísticas
La herramienta de estadísticas ofrece información más detallada sobre el uso de recursos dentro de un nivel. Puedes encontrarla en el menú desplegable Ventana.
La ventana de estadísticas desglosa el número de recursos en tus archivos de nivel y puede mostrar todos los niveles o solo algunos específicos. Las estadísticas de formas primitivas muestran información sobre el número de triángulos, el consumo de memoria y el recuento.
Otros datos que se muestran en esta lista incluyen el uso de texturas y la información de iluminación de la malla estática. El modo de lista de la ventana de estadísticas puede ilustrar rápidamente qué recursos están consumiendo más memoria. Los datos de Estadísticas de consolidador también son muy útiles, ya que enumeran todos los recursos con cooking en el último proceso de procesamiento de paquete.
Informes de memoria
Aunque las herramientas de estadísticas y mapa de tamaño muestran la huella de datos de tus archivos dentro de Unreal Editor, el comando de consola Memreport -full se puede utilizar desde una instalación de la aplicación lanzada en un dispositivo objetivo. Esto proporciona una visión detallada y precisa del tamaño de tus archivos tal y como existirán con los ajustes de compresión de tu dispositivo.
Una vez que la app se ha creado en la configuración de desarrollo y cargada en el dispositivo, puedes abrir la ventana de la consola e introducir el comando. Esta instantánea de memoria se guarda en el directorio del proyecto, en el dispositivo. El directorio suele ser Game/[TuAplicación]/[TuAplicación]/Saved/Profiling/Memreports/, pero esto puede variar.
El archivo .memreport es un archivo de texto que se puede leer en la mayoría de editores de texto. El principio del texto incluye información sobre la memoria asignada y los tamaños de los grupos, mientras que la mayor parte del texto muestra un registro de los niveles cargados, estadísticas de RHI, objetivos de renderizado, información de la escena y más. Toda esta información es valiosa, ya que representa los datos reales que pasaron el proceso de cooking y empaquetado.
Si buscas el término Listado de todas las texturas, encontrarás una lista de todas las texturas de tu aplicación, junto con información detallada sobre el tipo de textura, el grupo, el tamaño y el consumo de memoria. La lista está ordenada por tamaño de memoria, y las texturas más grandes se muestran primero. Es una forma rápida y sencilla de detectar qué texturas están consumiendo más memoria.
Cómo analizar el tiempo de arranque
Entre los factores que afectan al tiempo de arranque se encuentran los siguientes:
El tiempo necesario para cargar y descomprimir los recursos iniciales.
El tamaño total de la aplicación.
Cualquier complementos que deba activarse en la instalación del usuario.
La cantidad de datos de cadena que debe analizarse.
Cualquier asignación o fragmentación de memoria en el dispositivo del usuario.
Existen varias herramientas disponibles para analizar el tiempo de arranque de tu aplicación, pero la más recomendable es Unreal Insights, ya que puede crear perfiles de datos de rendimiento de forma remota desde un dispositivo objetivo. Para obtener información completa sobre este conjunto de herramientas, consulta la sección Unreal Insights.
Para ver un ejemplo de cómo utilizar Unreal Insights en una aplicación de Android, consulta