Optimización de la interfaz de usuario de Unity (三) : Herramientas de creación de perfiles de la interfaz de usuario de Unity

Verificación de versión: 2017.3 -Dificultad: Avanzada

Hay varias herramientas de análisis que se pueden utilizar para analizar el rendimiento de UnityUI. Las principales herramientas son:

  • Unity Profiler
  • Depurador de marcos de Unity
  • Instrumentos de Xcode o Intel VTune
  • Depurador de cuadros de Xcode o Intel GPA

Las herramientas externas proporcionan análisis de CPU a nivel de método con una resolución de milisegundos (o mejor), así como llamadas de dibujo detalladas y análisis de sombreado. Las instrucciones para configurar y utilizar las herramientas anteriores están fuera del alcance de esta guía. Tenga en cuenta que el depurador y las herramientas del marco Xcode solo se pueden usar para compilaciones de IL2CPP en plataformas Apple, por lo que actualmente solo se pueden usar para configurar compilaciones de IOS.

Unity Profiler

El objetivo principal de UnityProfiler es realizar un análisis comparativo: habilitar y deshabilitar elementos de la interfaz de usuario mientras UnityProfiler se está ejecutando puede reducir rápidamente la parte de la jerarquía de la interfaz de usuario que es más responsable de los problemas de rendimiento.

Para analizar esto, observe las líneas de Canvas.BuildBatch y Canvas.endWillRenderCanvases en la salida del analizador.

Como se mencionó anteriormente, Canvas.BuildBatch es un cálculo de código nativo que realiza el proceso de generación de lotes de lienzo.

Canvas.SendWillRenderCanvases contiene un script de C # que llama al evento WillRenderCanvases del componente Canvas suscrito. La clase UnityUIsCanvasUpdateRegistry recibe este evento y lo usa para ejecutar el proceso de reconstrucción, como se describió anteriormente. Se espera que cualquier componente de IU sucio actualice sus "renderizadores de lienzo" en este momento.

Nota: para que sea más fácil ver la diferencia en el rendimiento de la interfaz de usuario, generalmente se recomienda deshabilitar todas las categorías de seguimiento, excepto "procesamiento", "secuencias de comandos" y "interfaz de usuario". Esto se puede hacer haciendo clic en el cuadro de color junto al nombre de la categoría de seguimiento en el lado izquierdo del Analizador de uso de CPU. También puede reordenar las categorías en el Analizador de CPU haciendo clic y arrastrando el nombre de la categoría hacia arriba o hacia abajo.

La categoría de interfaz de usuario es nueva en Unity 2017.1 y versiones posteriores. Desafortunadamente, algunas partes del proceso de actualización de la interfaz de usuario no están clasificadas correctamente, así que tenga cuidado al mirar la curva de la interfaz de usuario, ya que es posible que no contenga todas las llamadas relacionadas con la interfaz de usuario. Por ejemplo, Canvas.endWillRenderCanvases se clasifica como "UI", mientras que Canvas.BuildBatch se clasifica como "Otros" y "Representación".

En 2017.1 y posteriores, también hay un nuevo analizador de interfaz de usuario. De forma predeterminada, este generador de perfiles es el último en la ventana del generador de perfiles. Consta de dos horarios y un visor de lotes:

La primera línea de tiempo muestra el tiempo de CPU utilizado para dos categorías, a saber, diseño de cálculo y presentación. Tenga en cuenta que encuentra el mismo problema descrito anteriormente, y es posible que no se expliquen algunas funciones de la interfaz de usuario.

La segunda línea de tiempo muestra el número total de lotes, vértices y marcadores de eventos. En la captura de pantalla anterior, puede ver varios eventos de clic de botón. Estos marcadores pueden ayudarlo a determinar la causa del pico de CPU.

Finalmente, la característica más útil de UIProfiler es el visor de lotes en la parte inferior. A la izquierda, hay una vista de árbol de todos sus lienzos, y debajo de cada lienzo, una lista de los lotes que generan. Estas columnas proporcionan detalles interesantes sobre cada lienzo o lote, pero para comprender mejor cómo optimizar su interfaz de usuario, una de ellas es crucial, por lo que se interrumpe el lote.

Esta columna mostrará el motivo por el cual el lote seleccionado no se puede combinar con el lote anterior. Reducir la cantidad de lotes es una de las formas más efectivas de mejorar el rendimiento de la interfaz de usuario, por lo que es importante comprender qué puede romper el procesamiento por lotes.

Una de las razones más comunes, como se muestra en la captura de pantalla, es el uso de elementos de la interfaz de usuario con diferentes texturas o materiales. En muchos casos, esto se puede resolver fácilmente utilizando atlas de sprites . La última columna muestra el nombre del objeto de juego asociado con el lote. Puedes hacer doble clic en el nombre para seleccionar el objeto del juego en el editor (esto es especialmente útil cuando tienes varios objetos con el mismo nombre).

A partir de Unity 2017.3, el visor de lotes solo funciona en el editor. En el dispositivo, el procesamiento por lotes debería ser el mismo, por lo que sigue siendo muy útil. Si sospecha que el procesamiento por lotes en el dispositivo puede ser diferente, puede usar el depurador de marco que se describe a continuación.

Depurador de marcos de Unity

UnityFrameworkDebugger es una herramienta útil para reducir la cantidad de llamadas de dibujo generadas por UnityUI. Se puede acceder a esta herramienta incorporada a través del menú de la ventana en el editor de Unity. Cuando está habilitada, mostrará todas las llamadas de dibujo generadas por Unity, incluidas las llamadas generadas por UnityUI.

Es importante tener en cuenta que el depurador de framework se actualizará con la llamada de dibujo generada para mostrar la "Vista de juego" en el "Editor de Unity", por lo que puede usarse para probar diferentes configuraciones de IU sin ingresar al "Modo de juego".

La ubicación de las llamadas de dibujo de UnityUI depende del modo de representación seleccionado en el componente de lienzo que se está dibujando:

  • Espacio de pantalla: la  superposición aparecerá en el grupo Canvas.RenderOverlay.
  • Espacio de pantalla: la cámara aparecerá en el grupo Camer.Render como un subgrupo de Render.
  • World Space aparecerá como un subgrupo de Render. Geometría transparente de la cámara espacial mundial para cada lienzo visible

Todas las interfaces de usuario se pueden identificar mediante la línea "Shader: UI / Default" (suponiendo que el sombreador de la interfaz de usuario no haya sido reemplazado por un sombreador personalizado). Los detalles de la llamada de grupo o lotería. Vea el cuadro rojo resaltado en la captura de pantalla a continuación.

Al ver este conjunto de filas mientras se ajusta la interfaz de usuario, es relativamente sencillo maximizar la capacidad del lienzo para combinar elementos de la interfaz de usuario en lotes. La causa más común de lotes rotos relacionados con el diseño es la superposición no intencional.

Todos los componentes de UnityUI generan su geometría como una serie de cuaterniones. Sin embargo, muchos sprites de la interfaz de usuario o símbolos de texto de la interfaz de usuario solo ocupan una pequeña parte del archivo de cuaternión para representarlos y el resto es espacio. Por lo tanto, a menudo se encuentra que los diseñadores de UI han superpuesto accidentalmente múltiples tetragones diferentes, y sus texturas son de diferentes materiales, por lo que no pueden procesarse en lotes.

Dado que UnityUI opera completamente en una cola transparente, cualquier tetragono inestable superpuesto debe dibujarse antes de los cuaterniones irrompibles, por lo que no se puede procesar por lotes con otros tetragones colocados en los cuaterniones irrompibles.

Considere el caso de tres tetragones, A, B y C. Suponga que estos tres tetragones se superponen, y también suponga que los tetragones A y C usan el mismo material, y el cuaternión B usa un material separado. Por lo tanto, los lotes A o C no se pueden utilizar para Quad B.

Si el orden en la jerarquía (de arriba a abajo) es A, B, C, entonces A y C no se pueden agrupar porque B debe dibujarse encima de A y debajo de C. Sin embargo, si B se coloca antes o después del cuaternión por lotes, los cuaterniones por lotes se pueden agrupar; B solo necesita dibujarse antes o después de los cuaterniones por lotes, y no se insertan.

Para discutir este tema más a fondo, consulte la sección de pedidos secundarios del capítulo Canvas .

Instrumentos y VTune

Los instrumentos de Xcode y VTune de Intel permiten un perfil extremadamente profundo de reconstrucciones de UI de Unity y cálculos de lotes de Canvas en CPU de Apple o Intel, respectivamente. Los nombres de los métodos son casi idénticos a las etiquetas del generador de perfiles discutidas anteriormente en la sección Unity Profiler:

  • Canvas :: SendWillRenderCanvases es el padre C ++ que llama al método Canvas.SendWillRenderCanvases C # y gobierna esa línea en Unity Profiler. Contendrá el código utilizado para ejecutar el proceso de reconstrucción, como se describe en el capítulo anterior .

  • Canvas :: UpdateBatches es idéntico a Canvas.BuildBatch , pero incluye código repetitivo adicional que no está cubierto por la etiqueta Unity Profiler. Ejecuta el proceso de creación de lotes de Canvas, descrito anteriormente.

Cuando se usa junto con una aplicación de Unity creada a través de IL2CPP, estas herramientas se pueden usar para profundizar más en el código C # transpilado de Canvas :: SendWillRenderCanvases. De principal interés será el costo de los siguientes métodos. (Nota: los nombres de los métodos transpilados son aproximados).

  • IndexedSet_Sort y CanvasUpdateRegistry_SortLayoutList se utilizan para ordenar la lista de componentes de Layout sucios antes de que se vuelvan a calcular los diseños. Como se describió anteriormente, esto implica calcular el número de transformaciones principales por encima de cada componente de Diseño.
  • ClipperRegistry_Cull llama a todos los implementadores registrados de la interfaz IClipRegion . Los implementadores integrados incluyen RectMask2D , que usa la interfaz IClippable. Durante las llamadas de ClipperRegistry.Cull , los componentes de RectMask2D recorren todos los elementos recortables contenidos dentro de su jerarquía y les pide que actualicen su información de selección.
  • Graphic_Rebuild contendrá el costo de calcular realmente las mallas necesarias para representar la imagen, el texto u otros componentes derivados de gráficos. Debajo de esto habrá varios otros métodos como Graphic_UpdateGeometry y, más notablemente, Text_OnPopulateMesh .
    • Text_OnPopulateMesh es generalmente un punto de acceso cuando Best Fit está habilitado. Esto se analiza con más detalle más adelante en esta guía.
    • Los modificadores de malla, como Shadow_ModifyMesh y Outline_ModifyMesh , también se ejecutarán aquí. El costo de calcular las sombras paralelas de los componentes, los contornos y otros efectos especiales se puede ver a través de estos métodos.

Depurador de cuadros Xcode e Intel GPA

Las herramientas de depuración de tramas de bajo nivel son esenciales para perfilar el costo de partes individuales de la IU por lotes, así como para monitorear el costo del sobregiro de IU. El sobregiro del UI se analiza con más detalle más adelante en esta guía.

Usando el depurador de marcos de Xcode

Para probar si una interfaz de usuario determinada sobrecarga la GPU, se pueden emplear las herramientas de diagnóstico de GPU integradas de Xcode. Primero, configure el proyecto en cuestión para usar Metal u OpenGLES3, luego cree una compilación y abra el proyecto Xcode resultante. Algunas versiones de Xcode y combinaciones de dispositivos pueden admitir capturas de fotogramas OpenGLES 2, pero no hay garantía de que funcione .

Nota: En algunas versiones de Xcode, es necesario seleccionar la API de gráficos adecuada en el esquema de compilación para que funcione el generador de perfiles de gráficos. Para hacer esto, vaya al menú Producto en Xcode, expanda el elemento del menú Esquema y elija Editar esquema .... Seleccione Ejecutar destino y vaya a la pestaña Opciones. Cambie la opción de captura de fotogramas de GPU para que coincida con la API utilizada por su proyecto. Suponiendo que el proyecto de Unity está configurado para seleccionar automáticamente una API de gráficos, entonces la mayoría de los iPads modernos usarán Metal de forma predeterminada. En caso de duda, inicie el proyecto y observe los registros de depuración en Xcode. Una de las primeras líneas debe indicar qué ruta de renderizado (Metal, GLES3 o GLES2) se está inicializando.

Cree y ejecute el proyecto en un dispositivo iOS. El generador de perfiles de GPU se puede encontrar mostrando el panel Depurar en la barra lateral del navegador de Xcode y haciendo clic en la entrada FPS.

El primer punto de interés en el perfilador de GPU es el conjunto de tres barras en el centro de la pantalla, etiquetadas como "Tiler", "Renderer" y "Device". De estos dos:

  • "Tiler" es generalmente una medida de cuán estresada está la GPU al procesar la geometría, que incluye el tiempo dedicado a los sombreadores de vértices. Generalmente, un uso elevado de "Tiler" indica sombreadores de vértices excesivamente lentos o un número excesivo de vértices dibujados.
  • El “renderizador” es generalmente una medida de cuán estresadas están las tuberías de píxeles de la GPU. Por lo general, un uso elevado de "Procesador" indica que una aplicación excede la tasa de llenado máxima de la GPU o tiene sombreadores de fragmentos ineficientes.
  • "Dispositivo" es una medida compuesta del uso general de la GPU, que incluye el rendimiento de "Tiler" y "Renderer". Por lo general, se puede ignorar, ya que rastreará aproximadamente la más alta de las medidas de "Tiler" o "Renderer".

Para obtener más información sobre el generador de perfiles de GPU de Xcode, consulte este artículo de documentación .

El depurador de fotogramas de Xcode se puede activar haciendo clic en el pequeño icono de 'Cámara' oculto en la parte inferior del generador de perfiles de GPU. Está resaltado por una flecha y un cuadro rojo en la siguiente captura de pantalla.

Después de una breve pausa, debería aparecer la vista de resumen del depurador de cuadros, así:

Cuando se usa el sombreador de interfaz de usuario predeterminado, el costo de renderizar la geometría generada por el sistema de interfaz de usuario de Unity se mostrará en el paso del sombreador "UI / predeterminado" , asumiendo que el sombreador de interfaz de usuario predeterminado no ha sido reemplazado por un sombreador personalizado. Es posible ver este sombreador de UI predeterminado en la captura de pantalla anterior como Render Pipeline "UI / Default".

La interfaz de usuario de Unity solo genera quads, por lo que es poco probable que el sombreador de vértices haga hincapié en la tubería de mosaico de la GPU. Es probable que cualquier problema que aparezca en este pase de sombreado se deba a problemas de tasa de relleno.

Analizar los resultados del generador de perfiles

Después de recopilar los datos del perfil, se pueden sacar varias conclusiones. Si Canvas.BuildBatch o Canvas :: UpdateBatches parece estar usando una cantidad excesiva de tiempo de CPU, entonces el problema probable es un número excesivo de componentes Canvas Renderer en un solo Canvas. Consulte la sección División de lienzos del capítulo Lienzo .

Si se dedica una cantidad excesiva de tiempo a dibujar la interfaz de usuario en la GPU y el depurador de fotogramas indica que la canalización del sombreador de fragmentos es el cuello de botella, es probable que la interfaz de usuario supere la tasa de llenado de píxeles que la GPU es capaz de hacer. La causa más probable es un sobregiro excesivo de la IU. Consulte la sección Solución de problemas de tasa de llenado del capítulo Tasa de llenado, lienzos y entrada .

Si las reconstrucciones gráficas utilizan una CPU excesiva, como se ve por una gran parte del tiempo de la CPU que se destina a Canvas.SendWillRenderCanvases o Canvas :: SendWillRenderCanvases , se necesita un análisis más profundo. Es probable que alguna parte del proceso de reconstrucción gráfica sea la responsable.

En el caso de que una gran parte de WillRenderCanvas se gaste dentro de IndexedSet_Sort o CanvasUpdateRegistry_SortLayoutList , entonces se dedica tiempo a ordenar la lista de componentes de Layout sucios. Considere la posibilidad de reducir la cantidad de componentes de diseño en el lienzo. Consulte las secciones Reemplazo de diseños con RectTransforms y División de lienzos para conocer las posibles soluciones.

Si parece que se gasta demasiado tiempo en Text_OnPopulateMesh , entonces el culpable es simplemente la generación de mallas de texto. Consulte las secciones Mejor ajuste y Deshabilitación de lienzos para conocer las posibles soluciones y tenga en cuenta los consejos que se encuentran dentro de Dividir lienzos si gran parte del texto que se está reconstruyendo no tiene cambios en sus datos de cadena subyacentes.

Si se gasta tiempo dentro de Shadow_ModifyMesh o Outline_ModifyMesh (o cualquier otra implementación de ModifyMesh ), entonces el problema es el tiempo excesivo empleado en calcular modificadores de malla. Considere quitar estos componentes y lograr su efecto visual a través de imágenes estáticas.

Si no hay un punto de acceso particular dentro de Canvas.SendWillRenderCanvases , o parece estar ejecutando todos los fotogramas, entonces el problema es probable que los elementos dinámicos se hayan agrupado con elementos estáticos y estén obligando a todo el Canvas a reconstruirse con demasiada frecuencia. Consulte la sección División de lienzos .

Supongo que te gusta

Origin blog.csdn.net/Momo_Da/article/details/93532474
Recomendado
Clasificación