Cómo depurar errores de ANR

Resolver los ANR en tu juego de Unity es un proceso sistemático:

Figura 1: Pasos para resolver los errores de ANR en juegos de Unity.

Integra servicios de informes

Los servicios de informes, como Android vitals, Firebase Crashlytics y Backtrace (un socio certificado de Unity), proporcionan registro y análisis de errores para tu juego a gran escala. Integra los SDK de los servicios de informes en tu juego al principio del ciclo de desarrollo. Analiza qué servicio de informes se adapta mejor a las necesidades y el presupuesto de tu juego.

Los diferentes servicios de informes tienen distintas formas de capturar los errores de ANR. Incluye un segundo servicio de informes para aumentar las probabilidades de obtener datos válidos que respalden tu decisión de corregir los errores de ANR.

La integración de los SDKs de informes no afecta el rendimiento del juego ni el tamaño del APK.

Analiza símbolos

Analiza los informes de tu servicio de informes y verifica si los seguimientos de pila están en un formato legible. Consulta Simboliza las fallas de Android y ANR para los juegos de Unity para obtener más información.

Figura 2: Crashlytics muestra el ID de compilación y faltan símbolos libil2cpp.so.

Cómo verificar el ID de compilación de símbolos

Si el sistema de informes muestra el ID de compilación faltante, pero los símbolos de compilación aún existen en el almacenamiento de la máquina de compilación, es posible verificar el ID de compilación de los símbolos y, luego, subirlos al servicio de informes. De lo contrario, se requiere una nueva compilación para subir los archivos de símbolos.

En Windows o macOS, haz lo siguiente:

  1. Navega a la carpeta de símbolos según tu backend de scripting (consulta la Resolución):
    1. Usa el siguiente comando (en Windows, usa Cygwin para ejecutar la utilidad readelf).
    2. El uso de grep es opcional para filtrar la salida de texto.
    3. Cómo buscar el ID de compilación
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

Inspecciona el código del juego

Cuando el registro de seguimiento muestra una función en la biblioteca libil2cpp.so, el error ocurrió en el código C#, que se convierte a C++. La biblioteca libil2cpp.so no solo tiene el código de tu juego, sino también complementos y paquetes.

El nombre de archivo de C++ sigue el nombre del ensamblado definido en el proyecto de Unity. De lo contrario, el nombre del archivo tendrá el nombre predeterminado Assembly-C#. Por ejemplo, la figura 3 muestra el error en el archivo Game.cpp (destacado en azul), que es el nombre definido en el archivo Assembly Definition. Logger es el nombre de la clase (destacado en rojo) en la secuencia de comandos de C#, seguido del nombre de la función (destacado en verde). Finalmente, se muestra el nombre completo que generó el convertidor de IL2CPP (destacado en naranja).

Figura 3: Pila de llamadas del proyecto de prueba de Backtrace.

Para inspeccionar el código del juego, haz lo siguiente:

  • Examina el proyecto de C# en busca de código sospechoso. Por lo general, las excepciones no controladas de C# no provocan un error de ANR ni una falla de la aplicación. Aun así, asegúrate de que el código se ejecute correctamente en diferentes situaciones. Comprueba si el código usa un módulo de motor de terceros y analiza si una versión reciente introdujo el error. Además, revisa si actualizaste Unity recientemente o si el error solo ocurre en dispositivos específicos.
  • Exporta el juego como un proyecto de Android Studio. Con acceso completo al código fuente en C# convertido de tu juego, puedes encontrar la función que causa el error de ANR. El código C++ se ve muy diferente del código C#, y la conversión de código rara vez tiene un problema. Si encuentras algo, envía un ticket de asistencia a Unity.
  • Revisa el código fuente del juego y asegúrate de que se limpie correctamente cualquier lógica que se ejecute en las devoluciones de llamada OnApplicationFocus() y OnApplicationPause().
    • El motor de Unity tiene un tiempo de espera para pausar su ejecución. Una carga de trabajo excesiva en estas devoluciones de llamada puede provocar un error de ANR.
    • Agrega registros o rutas de navegación a partes del código para mejorar tu análisis de datos.
  • Usa el Generador de perfiles de Unity para investigar el rendimiento del juego. Crear perfiles de tu app también puede ser una excelente manera de identificar los cuellos de botella que podrían estar causando el error de ANR.
  • Una excelente manera de identificar operaciones de E/S prolongadas en el subproceso principal es usar el modo estricto.
  • Analiza el historial de Android vitals o de otro servicio de informes, y verifica las versiones de lanzamiento del juego en las que se produce el error con mayor frecuencia. Revisa tu código fuente en el historial de control de versiones y compara los cambios de código entre las versiones. Si encuentras algo sospechoso, experimenta con cada cambio o posible solución de forma individual.
  • Examina el historial de informes de ANR de Google Play para los dispositivos y las versiones de Android que reciben la mayor cantidad de ANR. Si los dispositivos o las versiones están desactualizados, es probable que puedas ignorarlos de forma segura si hacerlo no afecta la rentabilidad del juego. Estudia los datos con atención, ya que un grupo específico de usuarios ya no podrá jugar tu juego. Para obtener más información, consulta el panel de distribución.
  • Revisa el código fuente del juego para asegurarte de no llamar a ningún código que pueda causar un problema. Por ejemplo, finish puede ser destructivo si no se usa correctamente. Consulta las guías para desarrolladores de Android para obtener más información sobre el desarrollo en Android.
  • Después de revisar los datos y exportar la compilación del juego a Android Studio, trabajarás con código C y C++, por lo que podrás aprovechar al máximo las herramientas más allá de las soluciones estándar de Unity, como el Generador de perfiles de memoria de Android, el Generador de perfiles de CPU de Android y perfetto.

Código del motor de Unity

Para saber si se produce un error de ANR en el motor de Unity, busca libUnity.so o libMain.so en los seguimientos de pila. Si los encuentras, sigue estos pasos:

  • Primero, busca en los canales de la comunidad (Foros de Unity, Discusiones de Unity, Stackoverflow).
  • Si no encuentras nada, informa un error para resolver el problema. Proporciona un seguimiento de pila con símbolos para que los ingenieros del motor puedan comprender y resolver mejor el error.
  • Comprueba si la LTS de Unity más reciente realizó mejoras relacionadas con tus problemas. Si es así, actualiza tu juego para usar esa versión. (Es posible que esta solución solo esté disponible para algunos desarrolladores).
  • Si tu código usa un Activity personalizado en lugar del predeterminado, revisa el código Java para asegurarte de que la actividad no cause ningún problema.

SDK de terceros

  • Comprueba que todas las bibliotecas externas estén actualizadas y no tengan informes de fallas o ANR para la versión más reciente de Android.
  • Visita los foros de Unity para ver si ya se resolvieron errores en una versión posterior o si Unity o un miembro de la comunidad proporcionaron una solución alternativa.
  • Revisa el informe de ANR de Google Play y asegúrate de que Google no haya identificado ya el error. Google conoce algunos errores de ANR y está trabajando activamente para solucionarlos.

Biblioteca del sistema

Por lo general, las bibliotecas del sistema están lejos del control del desarrollador, pero no representan un porcentaje significativo de los errores de ANR. Más allá de comunicarte con el desarrollador de la biblioteca o agregar registros para acotar el problema, los ANR de la biblioteca del sistema son difíciles de resolver.

Motivos de salida

ApplicationExitInfo es una API de Android para comprender las causas de los errores de ANR. Si tu juego usa Unity 6 o una versión posterior, puedes llamar a ApplicationExitInfo directamente. En versiones anteriores de Unity, debes implementar tu propio complemento para habilitar las llamadas de ApplicationExitInfo desde Unity.

Crashlytics también usa ApplicationExitInfo, pero tu propia implementación te brinda un mayor control y te permite incluir información más pertinente.