Buscar en Unity

Algunos de los mejores consejos para la optimización de la UI de Unity

Last updated: January 2019

What you will get from this page: Tips on how to create optimized UI elements for your content, including dividing up your canvases, avoiding the use of Camera.main and Layout Groups, smart pooling of UI objects and more.

You’ll find many more in this great session by Unity engineer Ian Dundore, Exprimiendo a Unity: Consejos para aumentar el rendimiento (section on Unity UI starts at 23:38).

Divide tus lienzos

Problema: Cuando uno o varios elementos cambian en el lienzo de la UI, se ensucia todo el lienzo.

El Lienzo is the basic component of Unity UI. It generates meshes that represent the UI elements placed on it, regenerates the meshes when UI elements change, and issues draw calls to the GPU so that the UI is actually displayed.

La generación de estas mallas puede ser costosa. Los elementos de la UI deben recopilarse en lotes, de manera que se invoquen en la menor cantidad de draw calls posible. Debido a que la generación de lotes es costosa, queremos regenerarlos solo cuando sea necesario. El problema es que, cuando uno o varios elementos cambian en un lienzo, todo el lienzo debe analizarse nuevamente para encontrar la manera óptima de invocar a todos sus elementos.

Muchos usuarios construyen toda la UI de su juego en un solo lienzo con miles de elementos. Así, cuando cambian un elemento, pueden experimentar un pico del CPU que les cuesta muchos milisegundos (para saber más acerca de por qué la reconstrucción es costosa, ve a la marca 24:55 de la charla de Ian).

Solución: Divide tus lienzos.

Cada lienzo es una isla en la que se aíslan los elementos con respecto a los que se encuentran en otros lienzos. Así, dividir tus lienzos es la principal herramienta disponible para resolver los problemas asociados con la agrupación en lotes en la UI de Unity.

También puedes anidar los lienzos, lo cual permite a los diseñadores crear UI jerárquicas grandes sin tener que pensar en qué lugar se encuentran los diferentes objetos en la pantalla, divididos entre muchos lienzos. Los lienzos hijos también aíslan el contenido, tanto de sus lienzos padres como de sus hermanos. Mantienen su propia geometría y efectúan su propia agrupación en lotes.

Al subdividir los lienzos con lienzos hijos, trata de agrupar los objetos en función de cuándo se actualizan. Por ejemplo, separa los elementos dinámicos de los estáticos (aproximadamente en 29:36, Ian presenta un ejemplo de la subdivisión de los lienzos en forma inteligente).

Uso óptimo de Graphic Raycaster

Problema: Uso óptimo del Graphic Raycaster:

El Graphic Raycaster es el componente que traduce tus entradas en eventos de la UI. Traduce las entradas de pantalla y toques en eventos y luego los envía a los elementos interesados de la UI. Necesitas un Graphic Raycaster en cada lienzo que requiera una entrada, incluidos los sublienzos.

A pesar del nombre, el Graphic Raycaster no es un emisor de rayos: de manera predeterminada, solo prueba los gráficos de la UI. Toma el conjunto de elementos de la UI que están interesados en recibir entradas en un lienzo dado y efectúa comprobaciones de la intersección: Verifica que el punto en el que se produce el evento de entrada contra el RectTransform de cada elemento del lienzo del Graphic Raycaster esté marcado como interactivo.

El desafío es que no todos los elementos de la UI están interesados en recibir actualizaciones.

Solución: Desactiva el Raycast Target para los elementos estáticos o no interactivos.

Por ejemplo, el texto de un botón. Al desactivar el Raycast Target, directamente se reducirá el número de verificaciones de la intersección que el Graphic Raycaster debe efectuar en cada cuadro.

Consejos para la optimización de la UI de Unity

Problema: De varias maneras, el Graphic Raycaster actúa como un emisor de rayos.

Si configuras el Modo Render en tu lienzo como Worldspace Camera o Screen Space Camera, también puedes configurar una máscara de bloqueo. La máscara de bloqueo determina si el Raycaster emitirá rayos a través de 2D o 3D Physics, para ver si algún objeto fde Physics está bloqueando la capacidad del usuario para interactuar con la UI.

Solución: Puede ser costoso emitir rayos a través 2D o 3D Physics; utiliza esta función con moderación.

Además, minimiza el número de Graphic Raycasters no agregándolos a los lienzos de la UI no interactivos, debido a que en este caso, no hay razón para comprobar si hay eventos de interacción.

Evita el uso de Camera.main

Problema: Los lienzos World Space necesitan saber de qué cámara deben provenir sus eventos de interacción.

Cuando se configura un lienzo para renderizar en un lienzo World Space o en un lienzo Screen Space Camera, es posible especificar la cámara que se utilizará para generar los eventos de interacción para el Graphic Raycaster de la UI. Esta configuración es necesaria para los lienzos "Screen Space - Camera" y se denomina "Render Camera".

Unity UI optimization tips screen space camera

Sin embargo, la configuración es opcional para los lienzos "World Space" y se denomina "Event Camera".

Unity UI optimization tips world space

Si dejas el campo Event Camera en blanco en un lienzo World Space, esto no significa que tu lienzo no recibirá los eventos. En cambio, este utiliza la cámara principal del juego. Para determinar qué cámara es la cámara principal, accede a la propiedad Camera.main.

Unity UI optimization tips camera main property

Dependiendo de la ruta de código que tome Unity, accede a Camera.main entre 7 a 10 veces por cuadro, por Graphic Raycaster, por World Space Canvas. ¡Y Camera.main llama a Object.FindObjectWithTag cada vez que se accede a él! Es evidente que todo esto no es algo bueno en el tiempo de ejecución.

Solución: Evita el uso de Camera.main.

Almacena en la memoria caché las referencias a las cámaras y crea un sistema para rastrear la cámara principal. Si utilizas lienzos World Space, siempre asigna una Event Camera. ¡No dejes esta configuración vacía! Si es necesario cambiar la Event Camera, escribe un código que actualice la propiedad Event Camera.

Evita el uso de Grupos de diseño en la medida de lo posible

Problema: Cada elemento de la UI que trate de ensuciar su diseño efectuará al menos una llamada a GetComponents.

Cuando uno o varios elementos hijos cambian en un sistema de diseño, se ensucia. El o los elementos hijos modificados invalidan el sistema de diseño al que pertenecen.

Algo acerca de los sistemas de diseño: Un sistema de diseño es un conjunto de Grupos de diseño que se encuentran directamente sobre un Elemento de diseño. Un elemento de diseño no es solo el componente del elemento de diseño: imágenes de la UI, textos y ScrollRect - estos también son elementos de diseño. Además, los ScrollRect también son grupos de diseño.

Volvamos al problema: Cada elemento de la UI que marca su diseño como sucio efectuará, como mínimo, una llamada a GetComponents. Esta llamada busca un Grupo de diseño en el padre del Elemento de diseño. Si lo encuentra, continúa ascendiendo por la jerarquía de Transforms hasta que deja de encontrar Grupos de diseño o llega a la raíz de la jerarquía, lo que ocurra primero. Por lo tanto, cada Grupo de diseño agrega una llamada a GetComponents para cada proceso de ensuciado de los Elementos de diseño hijos, haciendo que los Grupos de diseño anidados sean extremadamente perjudiciales para el desempeño.

Solución: Evita el uso de Grupos de diseño en la medida de lo posible.

Utiliza anclas para los diseños proporcionales. En las UI más usadas que cuentan con un número dinámico de elementos, considera escribir tu propio código que calcule los diseños y asegúrate de utilizarlo solo de acuerdo con la demanda, en lugar de hacerlo con cada cambio que se produzca.

Agrupa los objetos de la UI de una manera inteligente

Problema: Agrupación de los objetos de la UI de una manera incorrecta.

Con frecuencia, la gente agrupa los objetos de la UI cambiando la jerarquía de padres y luego deshabilitándolos, pero esto causa que muchos se ensucien de una manera innecesaria.

Solución: Deshabilita primero el objeto y luego cambia la jerarquía de padres en la agrupación.

Ensuciarás la vieja jerarquía una vez, pero luego, cuando cambies la jerarquía de padres, evitarás ensuciar la vieja jerarquía por segunda vez y no ensuciarás la nueva jerarquía en absoluto. Si estás eliminando un objeto de la agrupación, cámbiale los padres, luego actualiza los datos y después habilítalo.

Cómo ocultar un lienzo

Problema: Cómo ocultar un lienzo

A veces, necesitarás ocultar algunos elementos de la UI y lienzos. ¿Cómo puedes hacerlo de la manera más eficiente?

Solución: Deshabilita el componente lienzo propiamente dicho

Al deshabilitar el componente Lienzo se evitará que el lienzo envíe draw calls al GPU, de manera que el lienzo ya no será visible. Sin embargo, el lienzo no descargará su vertex buffer; mantendrá todas sus mallas y vértices y cuando vuelvas a habilitarlo, no activará una recompilación; simplemente empezará a dibujar estos elementos de nuevo.

Adicionalmente, al deshabilitar el componente de lienzo no se activan las costosas rellamadas OnDisable/OnEnable en la jerarquía del lienzo. Solo ten cuidado de deshabilitar a los Componentes hijos que ejecutan un código de ejecución por cuadro costoso.

Uso óptimo de animadores en los elementos de la UI

Problema: Uso de animadores en tu UI

Los animadores ensucian sus elementos en cada cuadro, aunque el valor de la animación no cambie. Los animadores no tienen comprobaciones de no-op.

Solución:

Only put animators on dynamic elements that always change. For elements that rarely change or that only change in response to events, for a short period of time, write your own code or tweening system (there are a number on the Asset Store).

Mas recursos

¡Debemos saberlo! ¿Te gustó este contenido?

Sí. Que sigan llegando Me da igual. Podría ser mejor
Lo tengo

Usamos cookies para brindarte la mejor experiencia en nuestro sitio web. Visita nuestra página de política de cookies si deseas más información.