ANR courants dans les jeux Unity

Les erreurs ANR Unity se produisent pour diverses raisons. Les erreurs ANR les plus courantes sont causées par les usages abusifs des composants Android et Unity, ainsi que leurs problèmes de communication.

WebView

WebView est une classe Android qui affiche des pages Web. Tierce Les SDK (tels que les annonces) utilisent WebView pour afficher du contenu Web dynamique dans des activités autres que UnityPlayerActivity. Des erreurs ANR se produisent lorsque des Les SDK utilisent WebView de manière abusive.

Trace de la pile

La trace de la pile est votre premier recours pour comprendre la cause de l'erreur ANR.

/data/app/~~p-0ksfCD6bF6Sdq6kpVePg==/com.google.android.webview-5YQZOqKbbqp-uoLY6WYnTw==/base.apk!libmonochrome.so
  at J.N.Mhc_M_H$ (Native method)
  at org.chromium.components.viz.service.frame_sinks.ExternalBeginFrameSourceAndroid.doFrame (chromium-TrichromeWebViewGoogle.aab-stable-579013831:60)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1054)
  at android.view.Choreographer.doCallbacks (Choreographer.java:878)
  at android.view.Choreographer.doFrame (Choreographer.java:807)
  at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1041)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:223)
  at android.app.ActivityThread.main (ActivityThread.java:7721)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:592)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:952)

Figure 1 : Trace de la pile ANR causée par une attente futex

Cause

Jusqu'à présent, la cause racine de ce problème n'est pas claire. Certaines causes potentielles peuvent incluent:

  • Mauvaise mise en œuvre de l'annonce.
  • Version obsolète de WebView, car l'utilisateur a peut-être choisi de ne pas la mettre à jour automatiquement l'application.
  • Utilisation élevée des ressources système (processeur, GPU, etc.), ce qui peut nécessiter beaucoup de et le profilage.
  • La compilation de nuanceurs plante, ce qui peut indiquer que le le contenu comporte un nuanceur incompatible ou que l'utilisateur dispose d'un ancien WebView installée.

Solution

  • Pour identifier le type de contenu qui entraîne le blocage de WebView thread principal, ajoutez des journaux à votre jeu chaque fois qu'une page Web est chargée, affichée, ou fermé.
    • Vous pouvez utiliser Backtrace ou Crashlytics de création de rapports.
    • Après avoir analysé les données et identifié le problème, essayez de désactiver le les fournisseurs d'annonces incriminés.
    • Incluez des journaux de mémoire pour vous assurer que le problème n'est pas lié à la mémoire.
  • Demandez à l'utilisateur de mettre à jour le WebView depuis Google Play. À partir d'Android 5.0 (niveau d'API 21) ou version ultérieure, WebView a été transféré vers un APK. Par conséquent, il peut être mis à jour séparément de la plate-forme Android. Pour connaître la version de WebView est en cours d'utilisation sur un appareil, accédez à Paramètres > Applications > Système Android WebView et examinez la version en bas de la page.
<ph type="x-smartling-placeholder">
</ph> Écran d&#39;informations sur l&#39;application affichant les versions de WebView.
Figure 1. Vérifiez la version de WebView.

Pause de l'unité

Lorsque UnityPlayerActivity reçoit un appel onPause(), la chaîne suivante de début des opérations:

  1. UnityPlayerActivity informe le moteur d'exécution Unity que l'activité a en pause.
  2. Unity appelle chaque élément MonoBehaviour qui implémente le l'événement OnApplicationPause.
  3. Unity arrête ses composants et modules, comme la lecture audio, le rendu, la boucle de jeu et l'animation.
  4. Pour vous assurer que Unity Android Player (UAP) et le moteur sont synchronisés, l'UAP attend 4 secondes que le moteur s'arrête.
  5. Si cette opération prend plus de cinq secondes, le système déclenche une erreur ANR.

Trace de la pile

"main" tid=1 Timed Waiting
jdk.internal.misc.Unsafe.park (Native method)
java.util.concurrent.locks.LockSupport.parkNanos (LockSupport.java:234)
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos (AbstractQueuedSynchronizer.java:1079)
java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos (AbstractQueuedSynchronizer.java:1369)
java.util.concurrent.Semaphore.tryAcquire (Semaphore.java:415)
com.unity3d.player.UnityPlayer.pauseUnity (UnityPlayer.java:833)
com.unity3d.player.UnityPlayer.pause (UnityPlayer.java:796)
com.unity3d.player.UnityPlayerActivity.onPause (UnityPlayerActivity.java:117)
android.app.Activity.performPause (Activity.java:8517)
android.app.Instrumentation.callActivityOnPause (Instrumentation.java:1618)
android.app.ActivityThread.performPauseActivityIfNeeded (ActivityThread.java:5061)
android.app.ActivityThread.performPauseActivity (ActivityThread.java:5022)
android.app.ActivityThread.handlePauseActivity (ActivityThread.java:4974)
android.app.servertransaction.PauseActivityItem.execute (PauseActivityItem.java:48)
android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:179)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2303)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:201)
android.os.Looper.loop (Looper.java:288)
android.app.ActivityThread.main (ActivityThread.java:7884)
java.lang.reflect.Method.invoke (Native method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)

Figure 3. ANR causée par un sémaphore qui n'est jamais publié.

Solution

Assurez-vous que l'exécution du code de votre jeu C# ne prend pas trop de temps lors d'une suspendre ou reprendre l'événement.

  • Profilez votre jeu et vérifiez si OnApplicationPause est cher opération. Vous pouvez utiliser un Stopwatch.
  • Évitez les opérations d'E/S ou les requêtes réseau synchrones.
  • Déplacez les opérations vers un autre objet Thread à l'aide de la méthode Task Unity 2023.1 prend en charge un modèle de programmation asynchrone avec C#. async et await.

UnitySendMessage bloqué

Les plug-ins et SDK Unity de Java envoient des données à la couche de jeu C# à l'aide de JNI. Cependant, cette communication peut bloquer le thread principal en raison d'un de synchronisation d'une routine de synchronisation telle qu'un mutex, ce qui provoque une erreur ANR due à un conflit de verrouillage.

Trace de la pile

L'erreur ANR de la figure 4 est causée par une longue opération dans le code C# appelée par un Plug-in Java. Le moteur Unity utilise un héritage non prioritaire mutex pour garantir une exécution correcte.

libc.so NonPI::MutexLockWithTimeout(pthread_mutex_internal_t*, bool, timespec const*) + 604
com.unity3d.player.UnityPlayer.nativeUnitySendMessage (Native method)
com.unity3d.player.UnityPlayer.UnitySendMessage (UnityPlayer.java:665)

Figure 4. ANR provoqué par un conflit de verrouillage.

Cause

Le problème est que plusieurs messages sont distribués lorsque l'application est réactivée. Les messages sont en file d'attente, car ils ne peuvent pas être envoyés pendant le jeu en arrière-plan. Les messages sont tous distribués simultanément lorsque l'application reprend.

Pendant une période de pause, vous stockez généralement les informations de votre jeu sur le serveur ; Par exemple, vous enregistrez la position d'un joueur dans le jeu peut revenir au même endroit lorsque la partie reprend.

Cette charge de travail, combinée à d'autres codes tiers créant sa propre charge de travail, peut surcharger les ressources de l'appareil, en particulier le thread principal. La principale Le thread exécute l'interface utilisateur d'une application et constitue souvent l'emplacement principal des erreurs ANR. Donc, toute charge de travail supplémentaire sur le thread principal augmente le risque d'erreur ANR.

Solution

Lors de la mise en pause d'une application, assurez-vous que toutes les actions liées au code sont nécessaires. essayez d'enregistrer l'état de l'utilisateur dans la mémoire locale de l'appareil. Et, bien sûr, voir si vous pouvez aussi effectuer ces actions en dehors de la période de suspension.

Voici quelques approches:

  • Déplacer l'opération C# qui gère un message vers un thread autre que le thread principal.
    • Si votre code ne dépend pas du contexte du thread principal Unity, utilisez Task pour la communication au lieu du message.
  • N'envoyez pas plusieurs messages depuis votre plug-in lorsque le jeu est mis en pause.
    • Le moteur ne peut pas envoyer de messages lorsque le jeu est en arrière-plan.
    • N'envoyez le dernier état des données à votre jeu que si cela n'a pas d'incidence sur votre jeu de Google Cloud.

Installer Referrer

Play Install Referrer est une chaîne unique envoyée au Play Store chaque fois qu'un clique sur une annonce. Il s'agit d'un identifiant de suivi d'annonce spécifique à Android. Une fois l'application envoie l'URL de provenance de l'installation au partenaire d'attribution, qui associe la source à l'installation (attribution de la conversion).

Trace de la pile

La figure 5 montre une trace de la pile ANR d'un jeu qui utilise le SDK Facebook pour récupérer l'attribution des installations.

Figure 5 : Rapport Android Vitals contenant un appel de liaison.

Cause

L'erreur ANR a été causée par un appel de liaison lent. Cependant, la cause racine ne peut pas être déterminé sans accéder au code source du SDK.

Solution

La résolution de ce type de problème implique une communication avec le développeur du SDK ou un qui recherchent en ligne une solution potentielle, qu'ils vérifient du SDK permet de résoudre l'erreur ANR pour d'autres utilisateurs, voire d'expérimenter avec un petit stratégie de déploiement.

Google fournit une page SDK Index qui regroupe les données d'utilisation. depuis les applications Google Play avec des informations collectées via la détection de code fournissent des attributs et des signaux conçus pour vous aider à décider d'adopter ou non, conserver ou supprimer un SDK de votre application.

Ressources supplémentaires

Pour en savoir plus sur les erreurs ANR, consultez les ressources suivantes: