Häufige ANR-Fehler bei Unity-Spielen

Unity-ANR-Fehler können aus verschiedenen Gründen auftreten. Die häufigsten ANR-Fehler werden durch Missbrauch von Android- und Unity-Komponenten und deren Missverständnisse

WebView

WebView ist eine Android-Klasse, in der Webseiten angezeigt werden. Drittanbieter SDKs (z. B. Anzeigen) verwenden WebView, um dynamische Webinhalte anzuzeigen bei anderen Aktivitäten als UnityPlayerActivity. ANR-Fehler treten auf, wenn Drittanbieter SDKs missbrauchen WebView.

Stacktrace

Der Stacktrace ist Ihre erste Möglichkeit, die Ursache des ANR-Fehlers zu verstehen.

/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)

Abbildung 1.ANR-Stacktrace, der durch eine Futex-Wartezeit verursacht wird.

Ursache

Bislang ist die Ursache dieses Problems unklar. Einige mögliche Ursachen können umfassen:

  • Schlechte Anzeigenimplementierung
  • Eine veraltete Version von WebView, da der Nutzer sich möglicherweise gegen das Update entschieden hat die App automatisch.
  • Hohe Nutzung der Systemressourcen (CPU, GPU usw.), was möglicherweise viel Profilerstellung.
  • Die Shader-Kompilierung stürzt ab, was darauf hindeuten könnte, dass der Der Inhalt weist einen inkompatiblen Shader oder einen alten WebView auf Version installiert ist.

Lösung

  • Um herauszufinden, welche Art von Inhalten der WebView blockiert, Logs zu eurem Spiel hinzufügen, sobald eine Webseite geladen, angezeigt und angezeigt wird, oder geschlossen ist.
    • Sie können Backtrace oder Crashlytics verwenden. Meldedienste.
    • Wenn Sie die Daten analysiert und das Problem gefunden haben, versuchen Sie, die die als problematisch erachtet werden.
    • Fügen Sie Arbeitsspeicherprotokolle hinzu, um sicherzustellen, dass das Problem nicht mit dem Arbeitsspeicher zusammenhängt.
  • Benachrichtigen Sie den Nutzer, die WebView in Google Play zu aktualisieren. Ab Android 5.0 (API-Level 21) und höher, wurde WebView in ein APK verschoben. Daher kann es sein, unabhängig von der Android-Plattform aktualisiert werden. So finden Sie heraus, welche Version von WebView auf einem Gerät verwendet wird, rufen Sie Einstellungen > Apps > Android-System WebView und sehen Sie sich die Version unten auf der Seite an.
<ph type="x-smartling-placeholder">
</ph> App-Infobildschirm mit den WebView-Versionen
Abbildung 1. Prüfen Sie die WebView-Version.

Unity-Pause

Wenn UnityPlayerActivity einen onPause()-Aufruf empfängt, wird die folgende Kette von Vorgänge beginnt:

  1. UnityPlayerActivity benachrichtigt die Unity-Laufzeit-Engine, dass die Aktivität pausiert.
  2. Unity ruft alle MonoBehaviour auf, in denen die OnApplicationPause-Ereignis.
  3. Unity stoppt seine Komponenten und Module, z. B. die Tonwiedergabe, das Rendering, eine Spielschleife und eine Animation.
  4. Sowohl Unity Android Player (UAP) als auch die Engine synchronisiert werden, wartet das UAP 4 Sekunden, bis die Suchmaschine abgeschaltet wird.
  5. Wenn dieser Vorgang länger als 5 Sekunden dauert, löst das System einen ANR-Fehler aus.

Stacktrace

"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)

Abbildung 3: ANR-Fehler aufgrund einer nie veröffentlichten Semaphore.

Lösung

Achten Sie darauf, dass die Ausführung des C#-Spielcodes während einer Pausieren oder Fortsetzen des Termins.

  • Profil für dein Spiel erstellen und prüfen, ob OnApplicationPause teuer ist . Sie können einen Stopwatch verwenden.
  • Vermeiden Sie E/A-Vorgänge oder synchrone Netzwerkanfragen.
  • Verschieben Sie die Vorgänge mithilfe der MethodeThread Task Unity 2023.1 unterstützt eine vereinfachte asynchrones Programmiermodell mit C# async und await Keywords.

UnitySendMessage blockiert

Java Unity-Plug-ins und -SDKs senden Daten mithilfe von JNI an die C#-Spieleebene. Diese Kommunikation kann jedoch den Hauptthread aufgrund einer nativen wie einem Mutex, der aufgrund eines Sperrkonflikts einen ANR-Fehler verursacht.

Stacktrace

Der ANR-Fehler in Abbildung 4 wurde durch einen langen Vorgang im C#-Code verursacht, der von einem Java-Plug-in. Die Unity-Engine verwendet eine übernommene Übernahme ohne Priorität. mutex für eine korrekte Ausführung an.

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)

Abbildung 4: ANR-Fehler aufgrund eines Sperrkonflikts.

Ursache

Das Problem ist, dass mehrere Nachrichten gesendet werden, wenn die Anwendung wird fortgesetzt. Die Nachrichten befinden sich in der Warteschlange, da sie während des Spiels nicht gesendet werden können. im Hintergrund. Die Nachrichten werden alle gleichzeitig gesendet, wenn der wird die App fortgesetzt.

Während einer Pause speichern Sie die Informationen zu Ihrem Spiel in der Regel im Server; z. B. die Position eines Spielers im Spiel, wenn das Spiel fortgesetzt wird.

Diese Arbeitslast, kombiniert mit anderem Code von Drittanbietern, erstellt eine eigene Arbeitslast, die Ressourcen des Geräts, insbesondere den Hauptthread, überlasten kann. Die wichtigsten führt die Benutzeroberfläche einer App aus und ist oft der Hauptort von ANR-Fehlern. Also: Jede zusätzliche Arbeitslast im Hauptthread erhöht das Risiko eines ANR-Fehlers.

Lösung

Prüfen Sie, ob während einer App-Pause alle Codeaktionen erforderlich sind, oder versuchen Sie, den Status des Nutzers im lokalen Arbeitsspeicher des Geräts zu speichern. Und natürlich können Sie sich ob Sie diese Aktionen auch außerhalb der Pause ausführen können.

Einige Ansätze:

  • C#-Vorgang, der eine Nachricht verarbeitet, in einen Thread verschieben als der Hauptthread.
    • Wenn Ihr Code nicht vom Kontext des Hauptthreads von Unity abhängt, verwenden Sie Task für Kommunikation statt Nachrichten.
  • Senden Sie nicht mehrere Nachrichten über Ihr Plug-in, wenn das Spiel pausiert ist.
    • Während das Spiel im Hintergrund läuft, kann die Engine keine Nachrichten senden.
    • Senden Sie nur dann den letzten Datenstatus an Ihr Spiel, wenn dies keine Auswirkungen auf Ihr Spiel hat. Funktionalität.

Verweis-URL installieren

Die Play Install Referrer ist ein eindeutiger String, der jedes Mal an den Play Store gesendet wird, auf eine Anzeige klickt. Es ist eine Android-spezifische ID für das Anzeigen-Tracking. Einmal installiert haben, sendet die App die Verweis-URL für die Installation an den Attributionspartner, der der Quelle mit der Installation übereinstimmt (die Conversion wird zugeordnet).

Stacktrace

Abbildung 5 zeigt einen ANR-Stacktrace eines Spiels, das das Facebook SDK verwendet, um und rufen Sie die Attribution der Installationen ab.

<ph type="x-smartling-placeholder">
</ph>
Abbildung 5: Android Vitals-Bericht mit einem Binder-Aufruf.

Ursache

Der ANR-Fehler wurde durch einen langsamen Binder-Aufruf verursacht. Die Grundursache kann jedoch nicht ohne Zugriff auf den SDK-Quellcode festzulegen.

Lösung

Zur Lösung dieses Problems muss mit dem SDK-Entwickler oder einem häufig online nach einer möglichen Lösung gesucht, Version des SDK den ANR-Fehler für andere behebt für die Einführungsstrategie.

Google stellt eine SDK-Index-Seite zur Verfügung, auf der Nutzungsdaten von Google Play-Apps mit durch Codeerkennung erfassten Informationen bieten Attribute und Signale, die Ihnen bei der Entscheidung helfen, ein SDK aus Ihrer App zu behalten oder zu entfernen.

Weitere Informationen

Weitere Informationen zu ANR-Fehlern finden Sie in den folgenden Ressourcen: