Optimización de la interfaz de usuario de Unity

imagen


Este artículo analiza la optimización de los elementos de la interfaz de usuario de proyectos realizados en Unity. Basado en información de documentación oficial y experiencia personal, traté de explicar claramente los principios de operación de los elementos de la interfaz de usuario. También aquí encontrará consejos prácticos que ayudarán a mejorar el rendimiento de su proyecto con respecto a la interfaz de usuario.



Terminología


Los elementos de la interfaz de usuario son todos los elementos de Unity relacionados con la creación de una interfaz de usuario. Esto incluye, por ejemplo: botón, texto, imagen, menú desplegable, etc.
Canvas (canvas) : el elemento básico de la interfaz de usuario, que es un contenedor para el resto de los elementos.
Malla : un conjunto de parámetros que describen un modelo 3D.
Un quad es una malla que es un cuadrilátero.
Lote : combina mallas de objetos en una malla grande para una representación más rápida.
Draw-call : un comando para dibujar desde el motor a la API de gráficos (por ejemplo, OpenGL o Direct3D).
Cola transparente : una cola para representar objetos transparentes.
Mezcla alfa ( mezcla alfa): un algoritmo para mezclar píxeles en el canal alfa para obtener una imagen con transparencia.
Atlas es un tipo de recurso que combina varias texturas en una.


Introductorio


En la optimización de la interfaz de usuario, no hay reglas universales que funcionen en cualquier situación. Todo se reduce a encontrar un equilibrio entre el costo del procesamiento por lotes y el número de llamadas de extracción. Se pueden distinguir cuatro problemas principales:


  • Carga de GPU demasiado alta (exceso de carga en el render);
  • demasiada carga de CPU al reconstruir el lienzo;
  • demasiados elementos cambiantes que conducen a la reconstrucción del lienzo;
  • La carga de la CPU es demasiado grande para la generación de malla (generalmente asociada con el texto).

Representación de la interfaz de usuario de Unity


El elemento básico de la interfaz de usuario de Unity es el lienzo. Es responsable de generar, ordenar y renderizar mallas de elementos de interfaz secundarios. Todos los elementos de la interfaz de usuario deben ser elementos secundarios de cualquier lienzo; de lo contrario, no se mostrarán en el juego.
imagen
La representación se produce desde el objeto más alejado hasta el más alejado de la cámara (de atrás hacia adelante) en la cola Transparente con mezcla alfa.


Por separado, debe tenerse en cuenta que la transparencia de los elementos de la interfaz de usuario NO afecta el rendimiento. Incluso si el elemento consiste completamente en píxeles "opacos", se representará mediante una combinación alfa.


También es importante comprender que al procesar, se procesan todos los píxeles de todos los elementos activos. No depende de si son visibles, bloqueados por otros objetos o incluso completamente transparentes.


Rediseñando la interfaz de usuario


El rediseño de la interfaz de usuario es un proceso de varios pasos, que incluye construir las mallas de cada elemento de la interfaz de usuario e intentar parchear estas mallas para minimizar el número de llamadas de extracción .


La reconstrucción tiene lugar en cuatro etapas:


  1. Se analizan las estructuras de los elementos.
  2. Se reconstruyen las mallas de todos los elementos activos, incluidos los elementos con cero transparencia.
  3. Reconstruye materiales para mallas de elementos de malla.
  4. Todos los elementos se dibujan según su orden.

El lienzo reconstruido se almacena en caché y se reutiliza hasta que uno de los elementos del lienzo se marca como modificado.
Se marcan los objetos sucios que se han activado o desactivado; quienes han cambiado material, posición, escala, rotación; el valor del texto del componente de texto ha cambiado; reasignación de los padres, etc.


En este caso, la reconstrucción del lienzo nuevamente contiene al menos un elemento modificado. Es cierto que esto solo se aplica al lienzo en el que se encuentra el elemento. Es decir, los cambios en los elementos en los lienzos secundarios no afectan a los principales.


Cuantos más elementos en el lienzo, mayor será el costo de analizar y ordenar objetos.


Malla


Fusionar mallas, o lotes, ayuda a reducir la carga en la GPU al reducir el número de llamadas de extracción. Durante el proceso de procesamiento por lotes, las mallas se ordenan por profundidad y se comprueba la superposición. Al pasar del elemento distante al elemento cercano (o del elemento superior al inferior en la jerarquía), los objetos con los mismos materiales o texturas se combinan en una malla dentro del mismo lienzo. Para esto, no debe haber objetos con otros materiales entre ellos. Además, los objetos con otros materiales no deben superponerse a los objetos horneados con sus contenedores generales. La operación de procesamiento por lotes es de subprocesos múltiples, su rendimiento varía mucho según la cantidad de núcleos en el procesador.


El texto puede revolotear con otro texto si tienen la misma fuente. No importa si la configuración de fuente y los estilos son iguales o diferentes. Si las fuentes son diferentes, el texto no se desplazará.


También debe tenerse en cuenta que el texto puede superponerse a un objeto con su contenedor general, y dicha superposición puede omitirse fácilmente.
imagen


Considera un ejemplo. Hay tres objetos A, B y C dispuestos en una jerarquía de esta manera:
imagen
imagen
En la imagen de la izquierda, los objetos A y C se fusionarán, porque tienen el mismo material y no se cruzan con el objeto B. En la imagen de la derecha, los objetos A y C no se combinarán, porque hay una intersección con el objeto B.


Consejos generales de optimización de la interfaz de usuario


Antes de comenzar la optimización, es muy recomendable que perfile la IU. Esto ayudará a identificar los cuellos de botella que conducen a la pérdida de rendimiento (si existe). Para la creación de perfiles, hay muchas herramientas, tanto integradas en Unity (Unity Profiler) como de terceros. Pero no discutiremos los problemas de la UI en este artículo.


Aquí hay algunas sugerencias para optimizar su interfaz de usuario en Unity:


  1. Apaga los objetos invisibles. Si un elemento se superpone con un elemento opaco, debe deshabilitar su GameObject o el GameObject padre del elemento superpuesto. Al mismo tiempo, aún se dibujarán elementos de interfaz con alfa establecido en 0. Para tales objetos, debe habilitar Cull Transparent Mesh en el componente Canvas Renderer o simplemente deshabilitar objetos invisibles.
    imagen
  2. Deshabilita los objetos del mundo ocultos por una interfaz opaca. Si la interfaz no cubre todo el mundo, puede guardarla en la Textura de renderizado y apagar la cámara mundial.
  3. Minimice el número de píxeles para dibujar. Combina tantas imágenes como sea posible en una. Por ejemplo, tiene sentido hacer que los botones sean un solo sprite, en lugar de capas separadas con un fondo, trazo, cuerpo del botón, etc. Esto reducirá la flexibilidad de trabajar con dichos elementos y puede conducir a la obstrucción de recursos, por lo que se debe buscar un compromiso.
    imagen
  4. Evite elementos vacíos que solo sirven para organizar la estructura (no utilice elementos como nombres de "carpetas" en la jerarquía de documentos).
  5. Evite cruzar objetos que no puedan hornearse entre sí. Si es posible, lo mejor es cambiar la posición en la jerarquía, el tamaño del contenedor o la posición de los elementos superpuestos y sin apelmazamiento.
  6. Utilice un lienzo separado o anidado para elementos dinámicos. Por lo tanto, minimiza el costo de ordenar y reconstruir la estructura del lienzo que contiene una gran cantidad de elementos. Los lienzos anidados son más convenientes, porque heredar la configuración del lienzo principal. Al mismo tiempo, al cambiar el lienzo principal, todos los anidados también se reconstruirán. Esto es bastante raro, pero sucede (por ejemplo, al cambiar la resolución de la pantalla). Tenga en cuenta que los objetos de diferentes lienzos o lienzos anidados NO se hornean para la representación conjunta. Se recomienda dividir los lienzos de acuerdo con la regularidad de la actualización de los elementos. Los elementos estáticos deben colocarse en un lienzo separado, luego se dibujarán solo una vez. Si hay elementos que cambian constantemente, entonces es mejor combinarlos en otro lienzo, porque aún se harán reconstruir mutuamente. Los objetos cambiantes también se pueden dividir en varios lienzos por la frecuencia de actualización. Por ejemplo, los elementos actualizados en cada cuadro se colocan en un lienzo y los elementos se actualizan con menos frecuencia en otro.
  7. Deshabilitar Pixel Perfect aumentará significativamente la productividad. Esto es especialmente cierto para los objetos constantemente actualizados con una gran cantidad de elementos (por ejemplo, inventario de desplazamiento).
    imagen
    El lienzo
    imagen
    Lienzo anidado
  8. Si necesita deshabilitar el lienzo, no deshabilite el objeto que lo contiene (a través de la función SetActive ). La próxima vez que active los elementos de este lienzo se marcan como modificados y todos los elementos se reconstruyen. Es mejor desactivar el componente del lienzo en sí mismo, entonces toda la estructura y los datos horneados no cambiarán y la próxima vez que active el componente del lienzo, simplemente comenzarán su dibujo.
  9. Para lienzos con Screen Space - Camera o World Space seleccionado en el parámetro Render Mode , siempre instale una cámara. Si no lo instala, el sistema de interfaz de usuario en cada cuadro lo buscará a través de Object.FindObjectWithTag para encontrar Camera.main , y esto afectará el rendimiento.
  10. Para no crear varias texturas idénticas, puede crear una en tonos de gris y "pintarla" a través del componente Imagen seleccionando el color deseado.
  11. Deje el indicador de destino de Raycast solo en los elementos que necesitan eventos de entrada y elimine el resto. Por defecto, el objetivo de Raycast está habilitado en muchos elementos (Imagen, Texto, etc.). Esto complica y ralentiza el trabajo del componente Raycaster , que maneja los eventos de entrada en Unity UI. Al hacer clic o grabar, recorre toda la jerarquía de elementos y busca todos los componentes gráficos con el conjunto de indicadores Raycast Target, luego los verifica por la posibilidad de eventos de entrada y, después de pasar los controles con éxito, los agrega a la lista de resultados. Después de eso, la lista de resultados se ordena por profundidad, los objetos fuera de la pantalla se descartan. Como resultado, da la lista de resultados final.
    En Unity UI, muchos componentes (imagen, texto, etc.) tienen el indicador de destino de Raycast .

imagen
Raycast Target en el componente de imagen.


imagen
TextMeshPro lo tiene oculto en la pestaña Configuración adicional .


imagen
Para TextMeshPro, puede establecer la configuración predeterminada de Raycast Target en Configuración del reproductor -> TextMest Pro -> Configuración -> Activar Raycast Target .


Los elementos se prueban cuando:


  • Raycast Target habilitado
  • el elemento en sí está encendido y activado;
  • el punto de inserción está en la intersección con RectTransform.

También tiene sentido eliminar el indicador Raycast Target de los elementos secundarios si el objeto raíz ya lo tiene y se superpone completamente a los elementos secundarios con su geometría. Por ejemplo, el botón estándar de Unity UI.



La imagen se superpone completamente al texto con su forma, en este caso, puede eliminar el objetivo Raycast del componente de texto.



Si todos los elementos del lienzo no esperan eventos de entrada, puede eliminar el componente Graphic Raycaster del lienzo / lienzo anidado.


Trabaja con texto y su optimización


El texto en la interfaz de Unity consta de cuadrículas en las que cada símbolo se crea su propio quad. La malla se reconstruye cada vez que cambia el valor del texto. La reconstrucción también ocurre si el componente de texto o su padre se ha apagado y encendido nuevamente.


Por defecto, las fuentes en Unity se agregan como dinámicas. Para cada fuente dinámica utilizada en el componente de texto en el escenario, se crea un atlas. Solo los personajes usados ​​se incluyen en este atlas. Por ejemplo, si el campo de texto contiene el texto "Texto nuevo", entonces el atlas creado para él contendrá los caracteres "N", "e", "w", "T", "x" y "t". Para cada personaje que sea diferente en tamaño o estilo, se creará una representación en el atlas.



Texto en el escenario



Atlas de fuentes


Si durante la ejecución del programa el contenido del componente de texto cambia y aparecen caracteres que no están en el atlas, se reconstruirá todo el atlas. Si hay espacio libre en la textura del atlas, entonces los símbolos necesarios simplemente se agregarán allí. Al mismo tiempo, los caracteres que no están actualmente en uso no se eliminarán. Si no hay suficiente espacio en el atlas para nuevos caracteres, su tamaño se duplicará y se volverá a llenar según los caracteres utilizados en los componentes de texto activos.


Si se establece un número estrictamente definido de caracteres para un proyecto, por ejemplo, solo el alfabeto latino, entonces vale la pena usar fuentes estáticas que se almacenan permanentemente en la memoria. Si su proyecto permite una gran cantidad de caracteres, es mejor detenerse en las fuentes dinámicas.
También puede mejorar el rendimiento reemplazando el componente de texto con un sprite. Por ejemplo, los números que aparecen en el juego (puntuación) se pueden hacer usando sprites de un atlas que contiene un conjunto de solo los caracteres necesarios. En este caso, no habrá costos para reconstruir el lienzo y el atlas de la fuente.


El uso de fuentes alternativas, enumeradas en el campo Nombres de fuente en la configuración de fuente, aumenta la memoria utilizada. Esto es especialmente notable en las fuentes pictográficas.


No se recomienda usar Best Fit , ya que Esta opción conduce a un desbordamiento rápido del atlas y provoca su reestructuración.
El ajuste óptimo ignora la configuración del tamaño de fuente e intenta ajustar el texto en el rectángulo de contorno del componente de texto.


Ahora algunas palabras sobre TextMeshPro (TMP) , un reemplazo popular para el componente de texto estándar de Unity. TextMeshPro también reconstruye su cuadrícula cada vez que cambia el valor del texto. Sin embargo, el texto TMP no usa fuentes dinámicas. Para ello, se generan por adelantado atlas de fuentes, que incluyen todos los caracteres necesarios. Si para algún texto en la escena no hay caracteres en la fuente asignada a su componente, entonces TMP comienza a buscar fuentes de respaldo. Si no hay nada allí, entonces TMP intentará encontrar este carácter en todas las fuentes descargadas.


Best Fit en TMP no crea problemas como un componente de texto normal, por lo que puede usarse.


Una gran cantidad de fuentes con diferentes localizaciones o grandes atlas de fuentes pueden ocupar mucha memoria. Por lo tanto, es mejor usar precargar solo las fuentes necesarias para una localización específica.


World Space recomienda usar TextMeshPro en lugar de TextMeshProUGUI .
TextMeshProUGUI se utiliza en lienzos.


Atlas de sprites


Los atlas de sprites son un tipo de recurso que combina varias texturas en una. Le permiten reducir el número de sorteos ( llamadas de sorteo ) y aumentar la productividad.


Creación del atlas.
Cree un atlas: Activo> Crear> Sprite Atlas .
Seleccione el atlas y coloque el sprite necesario en Objetos para empacar .
imagen
Haga clic en Vista previa del paquete para obtener una vista previa del atlas.
imagen
Tenga en cuenta que incluso si uno o más sprites del atlas se usan en la escena, el atlas aún se cargará en su totalidad. Por lo tanto, no tiene sentido intentar incrustar todas las imágenes en un atlas gigante, que en dispositivos con poca RAM puede tomar su parte tangible. Es mejor dividir en algunos atlas más pequeños, por ejemplo, el atlas de la interfaz de usuario del menú del juego y el atlas de la interfaz del modo de juego.


Evite grandes espacios vacíos en el atlas, para no ocupar espacio en exceso de memoria. Para hacer esto, puede cambiar el tamaño del atlas o agregar imágenes adicionales para llenar el espacio vacío tanto como sea posible.
imagen
imagen
Para las imágenes que no están en el atlas, debe seleccionar la configuración correcta.
Para cada formato de compresión, existen requisitos bajo los cuales funcionará eficientemente. Los requisitos de imagen más comunes:


  • ancho y alto deben ser múltiplos de la potencia de dos;
  • ancho y alto deben ser múltiplos de 4;
  • ambos párrafos anteriores juntos.
    De lo contrario, la textura no se comprimirá y se producirán costos adicionales de memoria del dispositivo.

Al elegir un formato de compresión, Unity le dirá si no se cumplen los requisitos para el formato seleccionado.
imagen


Además, no olvide que los formatos son diferentes del dispositivo de destino. Para obtener más información y recomendaciones sobre formatos, consulte la documentación oficial :


Resumir los métodos de optimización.


  • Deshabilitar objetos invisibles y transparentes
  • Minimiza la cantidad de artículos
  • Evite cruzar objetos que no se puedan hornear entre sí
  • Distribuya elementos por lienzo según la frecuencia de actualización
  • Para lienzos con elementos actualizados con frecuencia, deshabilite Pixel Perfect
  • Deshabilite Raycast Target en elementos no seleccionables
  • Elimine el componente Graphic Raycaster en el lienzo para el que no se puede hacer clic en todos los elementos
  • Para componentes de texto normales no use Best Fit
  • Para TextMeshPro en World Space, use TextMeshPro en lugar de TextMeshProUGUI. TextMeshProUGUI utilizado en lienzos
  • Configure la cámara en la configuración del lienzo, si es necesario
  • Deshabilite el lienzo deshabilitando el componente del lienzo
  • Usa sprites en escala de grises y colorea la configuración del componente de imagen
  • Usa atlas sprites
  • Utilice el tamaño y el formato de compresión correctos para las texturas que no están en el atlas

Fuentes:


Información completa de optimización de UI de Unity


Otra fuente oficial sobre este tema contiene información en una forma más concisa.


Libros Blancos Atlas


Información adicional sobre formatos de compresión de textura

Source: https://habr.com/ru/post/470608/


All Articles