Déboguer les erreurs ANR

Pour résoudre les erreurs ANR dans votre jeu Unity, vous devez suivre une procédure systématique :

Figure 1. Étapes à suivre pour résoudre les erreurs ANR dans les jeux Unity

Intégrer des services de reporting

Les services de reporting tels qu'Android Vitals, Firebase Crashlytics et Backtrace (partenaire Unity certifié) fournissent la journalisation et l'analyse des erreurs pour votre jeu à grande échelle. Intégrez les SDK des services de création de rapports à votre jeu dès le début du cycle de développement. Analysez le service de reporting qui correspond le mieux aux besoins et au budget de votre jeu.

Les différents services de création de rapports ne capturent pas les ANR de la même manière. Incluez un deuxième service de reporting pour augmenter vos chances d'obtenir des données valides afin de vous aider à prendre la décision de corriger les ANR.

L'intégration de SDK de reporting n'a aucune incidence sur les performances du jeu ni sur la taille de l'APK.

Analyser les symboles

Analysez les rapports de votre service de création de rapports et vérifiez si les traces de pile sont dans un format lisible. Pour en savoir plus, consultez Décoder les plantages Android et les erreurs ANR pour les jeux Unity.

Figure 2. Crashlytics affiche l'ID de build et les symboles libil2cpp.so manquants.

Vérifier l'ID de compilation des symboles

Si le système de reporting affiche l'ID de build manquant, mais que les symboles de build existent toujours dans le stockage de la machine de compilation, il est possible de vérifier l'ID de build des symboles, puis de les importer dans le service de reporting. Sinon, une nouvelle version est requise pour importer les fichiers de symboles.

Sur Windows ou macOS :

  1. Accédez au dossier des symboles en fonction de votre backend de script (voir Résolution) :
    1. Exécutez la commande suivante (sous Windows, utilisez Cygwin pour exécuter l'utilitaire readelf).
    2. L'utilisation de grep est facultative pour filtrer le texte généré.
    3. Rechercher l'ID de build
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

Inspecter le code du jeu

Lorsque la trace de pile affiche une fonction dans la bibliothèque libil2cpp.so, l'erreur s'est produite dans le code C#, qui est converti en C++. La bibliothèque libil2cpp.so contient non seulement le code de votre jeu, mais aussi des plug-ins et des packages.

Le nom de fichier C++ suit le nom de l'assembly défini dans le projet Unity. Sinon, le nom de fichier est celui de l'assembly C# par défaut. Par exemple, la figure 3 montre l'erreur sur le fichier Game.cpp (en bleu), qui est le nom défini dans le fichier de définition de l'assemblage. Logger correspond au nom de la classe (en rouge) dans le script C#, suivi du nom de la fonction (en vert). Enfin, le nom complet généré par le convertisseur IL2CPP (mis en surbrillance en orange).

Figure 3. Pile d'appel du projet de test depuis Backtrace.

Inspectez le code de votre jeu en procédant comme suit :

  • Examinez le projet C# à la recherche de code suspect. En général, les exceptions C# non gérées ne provoquent pas d'ANR ni de plantage de l'application. Malgré tout, assurez-vous que le code s'exécute correctement dans différentes situations. Vérifiez si le code utilise un module de moteur tiers et analysez si une version récente a introduit l'erreur. Vérifiez également si vous avez récemment mis à jour Unity ou si l'erreur ne se produit que sur des appareils spécifiques.
  • Exportez le jeu en tant que projet Android Studio. En ayant un accès complet au code source C# converti de votre jeu, vous pouvez trouver la fonction qui provoque l'ANR. Le code C++ est très différent de votre code C#, et la conversion du code pose rarement problème. Si vous trouvez quelque chose, envoyez une demande d'assistance à Unity.
  • Examinez le code source du jeu et assurez-vous que toute logique s'exécutant dans les rappels OnApplicationFocus() et OnApplicationPause() est correctement nettoyée.
    • Le moteur Unity dispose d'un délai avant de suspendre son exécution. Une charge de travail excessive sur ces rappels peut entraîner une erreur ANR.
    • Ajoutez des journaux ou des breadcrumbs à des parties du code pour améliorer l'analyse de vos données.
  • Utilisez le profileur Unity pour examiner les performances du jeu. Le profilage de votre application peut également être un excellent moyen d'identifier les goulots d'étranglement susceptibles de provoquer l'ANR.
  • Le mode strict est un excellent moyen d'identifier les opérations d'E/S longues sur le thread principal.
  • Analysez l'historique d'Android Vitals ou d'un autre service de reporting, et vérifiez les versions de publication du jeu pour lesquelles l'erreur se produit le plus souvent. Examinez votre code source dans l'historique du contrôle des versions et comparez les modifications de code entre les versions. Si vous détectez quelque chose de suspect, testez chaque modification ou solution potentielle individuellement.
  • Examinez l'historique des rapports ANR Google Play pour les appareils et les versions d'Android qui reçoivent le plus d'ANR. Si les appareils ou les versions sont obsolètes, vous pouvez probablement les ignorer sans risque si cela n'a pas d'impact sur la rentabilité du jeu. Étudiez attentivement les données, car un groupe d'utilisateurs spécifique ne pourra plus jouer à votre jeu. Pour en savoir plus, consultez la page Tableau de bord "Distribution".
  • Examinez le code source du jeu pour vous assurer de ne pas appeler de code susceptible de poser problème. Par exemple, finish peut être destructif s'il n'est pas utilisé correctement. Pour en savoir plus sur le développement Android, consultez les guides du développeur Android.
  • Après avoir examiné les données et exporté la version du jeu vers Android Studio, vous manipulez du code C et C++. Vous pouvez donc profiter pleinement d'outils allant au-delà des solutions standards de Unity, tels que Android Memory Profiler, Android CPU Profiler et perfetto.

Code du moteur Unity

Pour savoir si une ANR se produit côté moteur Unity, recherchez libUnity.so ou libMain.so dans les traces de pile. Si vous les trouvez, procédez comme suit :

  • Commencez par rechercher dans les canaux de la communauté (Forums Unity, Discussions Unity, Stackoverflow).
  • Si vous ne trouvez rien, signalez un bug pour résoudre le problème. Fournissez une trace de pile symbolisée pour que les ingénieurs du moteur puissent mieux comprendre et résoudre l'erreur.
  • Vérifiez si la dernière version LTS de Unity a apporté des améliorations concernant vos problèmes. Si c'est le cas, mettez à niveau votre jeu pour utiliser cette version. (Cette solution n'est peut-être possible que pour certains développeurs.)
  • Si votre code utilise un Activity personnalisé au lieu de celui par défaut, examinez le code Java pour vous assurer que l'activité ne pose aucun problème.

SDK tiers

  • Vérifiez que toutes les bibliothèques tierces sont à jour et qu'aucun plantage ni ANR n'ont été signalés pour la dernière version d'Android.
  • Consultez les forums Unity pour voir si des erreurs ont déjà été résolues dans une version ultérieure ou si une solution de contournement a été fournie par Unity ou un membre de la communauté.
  • Consultez le rapport Google Play sur les erreurs ANR et assurez-vous que l'erreur n'a pas déjà été identifiée par Google. Google a connaissance de certaines erreurs ANR et s'efforce activement de les corriger.

Bibliothèque système

Les bibliothèques système sont généralement hors du contrôle du développeur, mais elles ne représentent pas un pourcentage important d'ANR. Au-delà de contacter le développeur de la bibliothèque ou d'ajouter des journaux pour cerner le problème, il est difficile de résoudre les ANR de la bibliothèque système.

Motifs de sortie

ApplicationExitInfo est une API Android permettant de comprendre les causes des erreurs ANR. Si votre jeu utilise Unity 6 ou version ultérieure, vous pouvez appeler ApplicationExitInfo directement. Pour les anciennes versions d'Unity, vous devez implémenter votre propre plug-in pour activer les appels ApplicationExitInfo depuis Unity.

Crashlytics utilise également ApplicationExitInfo, mais votre propre implémentation vous offre un contrôle plus précis et vous permet d'inclure des informations plus pertinentes.