Creación de perfiles en Unity 2021 LTS: Qué, cuándo y cómo

Desarrollar experiencia con el conjunto de herramientas de perfilado de Unity es una de las habilidades más útiles que puedes añadir a tu caja de herramientas de desarrollo de juegos. La creación minuciosa de perfiles puede aumentar enormemente el rendimiento de tu juego, así que queremos ayudarte a empezar con los consejos clave de nuestro recién publicado libro electrónico, Ultimate guide to profiling Unity games (Guía definitiva para crear perfiles de juegos Unity).
Todos los creadores de juegos saben que un rendimiento fluido es esencial para crear experiencias de juego envolventes y, para conseguirlo, hay que perfilar el juego. No sólo hay que saber qué herramientas utilizar y cómo, sino cuándo utilizarlas.
Nuestra guía de más de 70 páginas sobre perfiles avanzados, recién salida de la imprenta, se ha creado en colaboración con expertos internos y externos. Recopila consejos y conocimientos sobre cómo perfilar una aplicación en Unity e identificar cuellos de botella en el rendimiento, entre otras buenas prácticas.
Veamos algunos consejos útiles del libro electrónico.
La creación de perfiles es como un trabajo detectivesco, en el que se desentrañan los misterios de por qué el rendimiento de la aplicación se está ralentizando o por qué el código está asignando un exceso de memoria.
Las herramientas de creación de perfiles le ayudan a comprender lo que ocurre "bajo el capó" de su proyecto Unity. Pero no espere a que aparezcan problemas de rendimiento significativos para echar mano de sus herramientas de detective.
Los mejores beneficios de la creación de perfiles se obtienen cuando se planifica al principio del ciclo de vida de desarrollo del proyecto, en lugar de justo antes de enviar el juego. Es un proceso continuo, proactivo e iterativo. Mediante la elaboración temprana y frecuente de perfiles, usted y su equipo pueden comprender y establecer una "firma de rendimiento" para el proyecto. Si el rendimiento cae en picado, por ejemplo, podrá detectar fácilmente cuándo las cosas van mal y poner remedio rápidamente al problema.
También puedes hacer comparaciones de rendimiento antes y después en trozos más pequeños utilizando un sencillo procedimiento de tres puntos: En primer lugar, establezca una línea de base mediante la creación de perfiles antes de realizar cambios importantes. A continuación, perfil durante el desarrollo para hacer un seguimiento del rendimiento y el presupuesto, y por último, perfil después de aplicar los cambios para verificar si han tenido el efecto deseado.
Usted debe tratar de perfilar una compilación de desarrollo de su juego, en lugar de perfilarlo desde el Editor de Unity. Esto se debe a dos razones:
Los datos sobre el rendimiento y el uso de memoria de las versiones de desarrollo independientes son mucho más precisos que los resultados de la creación de perfiles de un juego en el editor. Esto se debe a que la ventana Profiler registra datos del propio Editor, lo que puede sesgar los resultados.
Algunos problemas de rendimiento sólo aparecerán cuando el juego se ejecute en su hardware o sistemas operativos de destino, lo que se te escapará si realizas el perfil exclusivamente en el Editor.
Los resultados de perfilado más precisos se obtienen ejecutando y perfilando compilaciones en dispositivos de destino y utilizando herramientas específicas de la plataforma para profundizar en las características de hardware de cada plataforma de destino.
Aunque Unity incluye una serie de potentes herramientas de perfilado gratuitas para analizar y optimizar el código, tanto en el editor como en el hardware, también existen varias herramientas de perfilado nativas diseñadas para cada plataforma, como las disponibles en Arm, Apple, Sony y Microsoft. El uso de una combinación proporciona una visión más holística del rendimiento de las aplicaciones en todos los dispositivos de destino.
Para obtener una descripción completa de las herramientas disponibles, consulte la página de herramientas de creación de perfiles aquí.
Las herramientas de perfilado de Unity están disponibles en el Editor y en el Gestor de Paquetes. Cada herramienta se especializa en perfilar varias partes del proceso (un flujo de trabajo holístico de "suma de todas las partes"). Familiarícese con los siguientes perfiladores para que formen parte de su caja de herramientas cotidiana:
- El Unity Profiler es por donde querrá empezar y pasar la mayor parte de su tiempo. Mide el rendimiento del Editor de Unity, tu aplicación en modo Play, y se conecta al dispositivo que ejecuta tu aplicación en modo Desarrollo. El Perfilador de Unity recopila y muestra datos sobre el rendimiento de su aplicación, como cuánto tiempo de CPU se está utilizando para diferentes tareas, desde audio y física hasta renderización y animación. Echa un vistazo a este curso sobre creación de perfiles para empezar.
- El Memory Profiler proporciona un análisis en profundidad del rendimiento de la memoria para identificar dónde puede reducir el uso de memoria en partes de su proyecto y del Editor. El Memory Profiler está actualmente en vista previa pero se espera que sea verificado en Unity 2022 LTS.
- El Analizador de Perfiles agrega y visualiza tanto datos de fotogramas como de marcadores de un conjunto de fotogramas de Unity Profiler para ayudarle a examinar su comportamiento a lo largo de muchos fotogramas (complementando el análisis de un solo fotograma ya disponible en Unity Profiler). También le permite comparar dos conjuntos de datos de perfiles para determinar cómo afectan sus cambios al rendimiento de la aplicación.
- El depurador de fotogramas permite congelar la reproducción de un juego en ejecución en un fotograma concreto y, a continuación, ver las llamadas de dibujo individuales utilizadas para renderizar ese fotograma. Además de listar las llamadas a dibujo, el depurador te permite recorrerlas una a una, para que puedas ver cómo se construye la escena a partir de sus elementos gráficos.
- El paquete Profiling Core proporciona APIs para añadir información contextual a las capturas de Unity Profiler.
Steve McGreal, ingeniero sénior de Unity y coautor de nuestro libro electrónico sobre perfiles avanzados, ha elaborado la siguiente descripción general de alto nivel. No dude en utilizarla como hoja de referencia.
Aunque la explicación detallada sobre cómo utilizar las herramientas se encuentra en el libro electrónico, este diagrama de flujo ilustra tres observaciones principales que debe tener en cuenta para su flujo de trabajo:

Descargue aquí la versión imprimible en PDF de este gráfico. Para más información, consulte los recursos enlazados sobre cómo utilizar cada una de las herramientas de creación de perfiles al final de esta entrada.
Una forma habitual en que los jugadores miden el rendimiento es a través de la tasa de fotogramas, o fotogramas por segundo. Sin embargo, se recomienda utilizar el tiempo de fotograma en milisegundos.
Por ejemplo, puedes tener un juego que renderiza 59 fotogramas en 0,75 segundos en tiempo de ejecución, y el siguiente fotograma tarda 0,25 segundos en renderizarse. La tasa media de fotogramas por segundo de 60 fps suena bien, pero en realidad los jugadores notarán un efecto de tartamudeo, ya que el último fotograma tarda un cuarto de segundo en renderizarse.
Esfuérzate por conseguir un presupuesto de tiempo específico por fotograma al perfilar y optimizar tu juego, ya que esto es crucial para crear una experiencia de jugador fluida y coherente. Cada fotograma tendrá un presupuesto de tiempo basado en los fps objetivo. Una aplicación orientada a 30 fps debería tardar siempre menos de 33,33 ms por fotograma (1000 ms / 30 fps). Del mismo modo, un objetivo de 60 fps deja 16,66 ms por fotograma.
La mayoría de los juegos modernos de consola y PC pretenden alcanzar una frecuencia de imagen de 60 fps o más. En los juegos de RV, en realidad es más importante evitar una frecuencia de imagen regularmente alta, ya que puede causar náuseas o incomodidad a los jugadores. Los juegos para móviles también pueden requerir presupuestos de fotogramas restrictivos para evitar el sobrecalentamiento de los dispositivos en los que se ejecutan. Por ejemplo, un juego para móviles puede tener un objetivo de 30 fps con un presupuesto de fotogramas de sólo 21-22 ms para que la CPU y la GPU se enfríen entre fotogramas.
Utiliza el Unity Profiler para ver si estás dentro del presupuesto de marcos. A continuación se muestra una imagen de una captura de perfilado de un juego Unity para móviles con perfilado y optimización en curso. El juego alcanza los 60 fps en móviles de altas especificaciones, y los 30 fps en móviles de especificaciones medias/bajas, como el de esta captura:

Se trata de un juego que funciona cómodamente dentro del presupuesto de fotogramas de ~22 ms necesario para 30 fps sin sobrecalentarse. Observe que WaitForTargetfps rellena el tiempo del hilo principal, hasta VSync y los tiempos grises de inactividad en el hilo de renderizado y el hilo trabajador. Además, observe el intervalo VBlank mirando los tiempos finales de Gfx. La presentación fotograma a fotograma dibuja una escala de tiempo en el área de la línea de tiempo o en la regla de tiempo de la parte superior para medir de uno de ellos al siguiente.
Si estás dentro del presupuesto de fotogramas, incluidos los ajustes realizados en el presupuesto para tener en cuenta el uso de la batería y el estrangulamiento térmico, entonces has terminado con éxito la creación de perfiles de rendimiento hasta la próxima vez: ¡enhorabuena! Ahora mira el uso de memoria para ver si también está dentro del presupuesto.
Dicho esto, si tu juego no se ajusta al presupuesto de fotogramas, el siguiente paso es detectar el cuello de botella. En otras palabras, averigua si lo que más tarda es la CPU o la GPU. Si se trata de la CPU, determine qué subproceso está más ocupado: ahí reside el cuello de botella.
El objetivo de la elaboración de perfiles es identificar los cuellos de botella como objetivos de optimización. Si te basas en conjeturas, puedes acabar optimizando partes del juego que no son cuellos de botella, con lo que la mejora será escasa o nula. Algunas "optimizaciones" pueden incluso empeorar el rendimiento general del juego.
El hilo principal es donde toda la lógica del juego y los scripts realizan su trabajo por defecto; donde las características y sistemas como la física, la animación, la interfaz de usuario y el renderizado tienen lugar.
En la captura de pantalla siguiente se muestra un ejemplo de un proyecto vinculado al subproceso principal:

Aunque los hilos de render y trabajador se parecen al ejemplo anterior que está dentro del presupuesto de fotogramas, el hilo principal aquí está claramente ocupado con trabajo durante todo el fotograma. Incluso si se tiene en cuenta la pequeña cantidad de sobrecarga de Profiler al final del fotograma, el hilo principal está ocupado durante más de 45 ms, lo que significa que este proyecto alcanza frecuencias de fotogramas inferiores a 22 fps. No hay ningún marcador que muestre el hilo principal ocioso esperando VSync; está ocupado durante todo el fotograma.
La siguiente fase de la investigación consiste en identificar las partes del bastidor que tardan más tiempo y determinar las causas subyacentes. Utilice tanto Unity Profiler como Profile Analyzer para evaluar y abordar los mayores costes. Los cuellos de botella más comunes suelen derivar de la física, los scripts no optimizados, el colector de basura (GC), la animación, las cámaras y la interfaz de usuario. Si el origen del problema no es obvio de inmediato, pruebe a activar Deep Profiling, Call Stacks o a utilizar un perfilador de CPU nativo.
En nuestra guía de optimización del rendimiento de 95 páginas, hemos recopilado una lista de escollos comunes con los que puede encontrarse y para los que debe prepararse.
Durante el proceso de renderizado, el subproceso principal examina la escena y realiza la selección de la cámara, la ordenación de la profundidad y el procesamiento por lotes de las llamadas de dibujo, para compilar una lista de cosas a renderizar. Esta lista se pasa al hilo de renderizado, que la traduce de la representación interna de Unity, agnóstica a la plataforma, a las llamadas a la API gráfica necesarias para instruir a la GPU en una plataforma concreta.
En la captura del Profiler que se muestra a continuación, se puede ver que el hilo principal espera al hilo de renderizado antes de empezar a renderizar en el fotograma actual, como indica el marcador Gfx.WaitForPresentOnGfxThreadmarker.

El subproceso de renderizado sigue enviando comandos de llamada de dibujo del fotograma anterior, pero no está preparado para aceptar nuevas llamadas de dibujo del subproceso principal. El hilo de renderizado pasa tiempo en Camera.Render.
El módulo Rendering Profiler comparte una visión general del número de lotes de llamadas de dibujo y llamadas SetPass para cada fotograma. La mejor herramienta para investigar qué lotes de llamadas de dibujo envía tu hilo de renderizado a la GPU es el depurador de fotogramas. Entre las causas más comunes de los cuellos de botella en los subprocesos de renderizado se incluyen una mala dosificación de las llamadas de dibujo, la existencia de varias cámaras activas en la escena y una selección de cámaras ineficiente.
Estar limitado por hilos de la CPU, además de los hilos principales o de renderizado, no es un problema común, pero puede surgir en proyectos que utilizan la pila de tecnología orientada a datos (DOTS), especialmente si el trabajo se desplaza del hilo principal a los hilos de trabajo utilizando el sistema de trabajos de C#.
Aquí tienes una captura del modo Play en el Editor que muestra un proyecto DOTS ejecutando una simulación de fluidos de partículas en la CPU:

Como puede ver, los subprocesos de los trabajadores están repletos de trabajos. Esto sugiere que se está desplazando una gran cantidad de trabajo del hilo principal. Observe que el tiempo de fotograma de 48,14 ms y el marcador gris WaitForJobGroupID de 35,57 ms en el subproceso principal indican que los subprocesos trabajadores están realizando más trabajo del que se puede conseguir de forma realista en un solo fotograma en esta CPU.
WaitForJobGroupID muestra que el subproceso principal ha programado trabajos para que se ejecuten de forma asíncrona en los subprocesos de los trabajadores, pero necesita los resultados de esos trabajos antes de que los subprocesos de los trabajadores hayan terminado de ejecutarlos. Los marcadores azules de Profiler debajo de WaitForJobGroupID representan el hilo principal ejecutando trabajos mientras espera, en un intento de hacer que los trabajos terminen antes.
Es posible que los trabajos de tu proyecto no estén tan paralelizados como en este ejemplo. Tal vez sólo tengas un trabajo largo ejecutándose en un único hilo de trabajo. Esto está bien, siempre y cuando el tiempo entre el trabajo programado y el momento en que debe completarse sea suficiente para que el trabajo se ejecute. Si no es así, verá que el hilo principal se detiene, esperando a que el trabajo se complete, como en la captura de pantalla anterior.
Puede utilizar la función Eventos de flujo en la vista de línea de tiempo del módulo CPU Usage Profiler para ver cuándo se programan los trabajos y cuándo el subproceso principal espera sus resultados. Para más información sobre cómo escribir código DOTS eficiente, consulte nuestras mejores prácticas DOTS.
Puede que notes que tu hilo principal pasa tiempo esperando al hilo de renderizado (como muestran marcadores del Profiler como Gfx.WaitForPresentOnGfxThread). Pero al mismo tiempo, su hilo de render puede mostrar marcadores como Gfx.PresentFrame o <GraphicsAPIName>.WaitForLastPresent. Esto significa que su aplicación está vinculada a la GPU. Por tanto, tendrás que centrar tus esfuerzos de optimización en los cuellos de botella de la GPU para mejorar el rendimiento general.
La siguiente captura se realizó en un Samsung Galaxy S7 utilizando la API gráfica Vulkan. Aunque parte del tiempo empleado en Gfx.PresentFrame en este ejemplo podría estar relacionado con la espera de VSync, la duración extrema de este marcador de Profiler demuestra que la mayor parte del tiempo se emplea en esperar a que la GPU termine de renderizar el fotograma anterior.

Si tu aplicación parece estar vinculada a la GPU, puedes utilizar el depurador de fotogramas para conocer rápidamente los lotes de llamadas de dibujo que se envían a la GPU. Sin embargo, esta herramienta no puede presentar ninguna información específica sobre la sincronización de la GPU. Sólo revela cómo está construida la escena.
Para investigar detenidamente la causa de los cuellos de botella de la GPU, examina una captura de GPU de un GPU Profiler adecuado. La herramienta que se utilice dependerá del hardware de destino y de la API gráfica elegida.
Entre las causas más comunes del bajo rendimiento de la GPU se incluyen los shaders ineficientes, los efectos de postprocesado caros, el sobredibujo transparente (a menudo de efectos de partículas o UI), las texturas grandes o sin comprimir, las mallas con un número de polígonos excesivamente alto y las resoluciones de salida excesivas (es decir, renderizar a 4K).

La optimización del rendimiento y la creación de perfiles son temas masivos. Si desea obtener más información, consulte nuestro libro electrónico publicado recientemente, Guía definitiva para crear perfiles de juegos Unity. Obtendrá más de 80 páginas de consejos y trucos creados en colaboración con múltiples expertos, incluidos los de nuestro equipo de servicios de asistencia integrados.
De hecho, algunos de estos expertos también colaboraron en la elaboración de nuestra guía de 100 páginas sobre optimización del rendimiento para móviles y PC/consola, repleta de consejos prácticos sobre cómo evitar los cuellos de botella. Para obtener recursos adicionales, echa un vistazo a nuestra serie de entradas de blog anteriores sobre física, interfaz de usuario y configuración de audio, gráficos y activos en móviles o consolas, y arquitectura de memoria y código.
Si está interesado en saber cómo su equipo puede obtener acceso directo a ingenieros, asesoramiento experto y orientación sobre proyectos, consulte aquí los planes de éxito de Unity.

Conéctate a nuestro nuevo seminario web Ultimate Profiling Tips en el que participarán expertos de SYBO Games, Arm y Unity para obtener consejos sobre cómo identificar los problemas de rendimiento más comunes en los juegos para móviles, utilizando tanto Unity como herramientas de perfilado nativas.
Este seminario web abarcará:
- Consideraciones clave para crear un código ágil y eficaz y optimizar el uso de la memoria para un rendimiento fluido en dispositivos de gama baja y alta.
- Gestionar el control térmico para conservar los valiosos ciclos de la batería en los dispositivos móviles
- Perfilar estrategias en todas las fases del desarrollo del juego y cómo ponerlas a prueba para construir una metodología sólida.
- Opiniones de expertos sobre la creación de perfiles de Android
Únase a nuestra mesa redonda y a las preguntas y respuestas en directo el 14 de junio de 2022 a las 11:00 h ET / 8:00 h PT.
Queremos ayudarle a sacar el máximo partido de sus aplicaciones Unity. Si hay algún tema de optimización en el que te gustaría que profundizáramos, háznoslo saber en los foros. También nos gustaría conocer los formatos que prefiere para poder mejorar nuestros libros electrónicos y otros materiales didácticos.