Errori ANR comuni dei giochi Unity

Gli errori ANR Unity si verificano per diversi motivi. Gli errori ANR più comuni sono causati da uso improprio dei componenti di Android e Unity e dei relativi problemi di comunicazione.

WebView

WebView è un corso Android che mostra pagine web. Di terze parti Gli SDK (ad esempio gli annunci) utilizzano WebView per visualizzare contenuti web dinamici in attività diverse da UnityPlayerActivity. Gli errori ANR si verificano quando Gli SDK fanno un uso improprio di WebView.

Analisi dello stack

L'analisi dello stack è il primo ricorso per comprendere la causa dell'errore 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)

Figura 1.Analisi dello stack ANR causata da un'attesa futex.

Causa

Al momento, la causa principale di questo problema non è chiara. Alcune potenziali cause include:

  • Implementazione errata degli annunci.
  • Una versione obsoleta di WebView perché l'utente potrebbe aver scelto di non eseguire l'aggiornamento l'app automaticamente.
  • Utilizzo elevato di risorse di sistema (CPU, GPU, ecc.), che può richiedere la profilazione.
  • La compilazione Shader ha un arresto anomalo, il che potrebbe indicare che i contenuti hanno uno shaker incompatibile o che l'utente ha un vecchio WebView installata.

Soluzione

  • Per restringere il tipo di contenuti che causano il blocco da parte di WebView thread principale, aggiungi log al tuo gioco ogni volta che una pagina web viene caricata, visualizzata o chiuso.
    • Puoi utilizzare Backtrace o Crashlytics. servizi di reporting.
    • Dopodiché, dopo aver analizzato i dati e aver individuato il problema, prova a disattivare lo trasgressori.
    • Includi i log della memoria per assicurarti che il problema non sia correlato alla memoria.
  • Avvisa l'utente di aggiornare WebView da Google Play. Da Android 5.0 (livello API 21) e versioni successive, WebView è stato spostato in un APK. Pertanto, può essere aggiornati separatamente dalla piattaforma Android. Per visualizzare quale versione di WebView è in uso su un dispositivo, vai a Impostazioni > App > Sistema Android WebView e la versione in fondo alla pagina.
di Gemini Advanced.
Schermata di informazioni sull'app che mostra le versioni di WebView.
Figura 1. Controlla la versione di WebView.

Pausa del formato Unity

Quando UnityPlayerActivity riceve una chiamata onPause(), la seguente catena di dell'avvio delle operazioni:

  1. UnityPlayerActivity comunica al motore di runtime Unity che l'attività è in pausa.
  2. Unity chiama ogni MonoBehaviour che implementa la funzione OnApplicationPause.
  3. Unity interrompe i suoi componenti e moduli, come riproduzione audio, rendering, ciclo di gioco e animazione.
  4. Per assicurarti che sia Unity Android Player (UAP) sia il motore sono sincronizzati, l'UAP attende 4 secondi per l'arresto del motore.
  5. Se l'operazione richiede più di 5 secondi, il sistema attiva un errore ANR.

Analisi dello stack

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

Figura 3. Errore ANR causato da un semaforo mai pubblicato.

Soluzione

Assicurati che l'esecuzione del codice di gioco C# non richieda troppo tempo durante un metti in pausa o riprendi l'evento.

  • Profila il tuo gioco e controlla se il OnApplicationPause è costoso operativa. Puoi usare un Stopwatch.
  • Evita operazioni di I/O o richieste di rete sincrone.
  • Sposta le operazioni in un'altra Thread utilizzando il metodo Task. Unity 2023.1 supporta una versione modello di programmazione asincrona utilizzando C# async e await parole chiave.

UnitySendMessage bloccato

Gli SDK e i plug-in Java Unity inviano i dati al livello del gioco C# utilizzando JNI. Tuttavia, questa comunicazione potrebbe bloccare il thread principale a causa di un errore di una routine di sincronizzazione, come un mutex, che causa un errore ANR a causa del conflitto del blocco.

Analisi dello stack

L'errore ANR nella figura 4 è causato da un'operazione lunga nel codice C# chiamata da un Plug-in Java. Il motore Unity utilizza un'ereditarietà non prioritaria mutex per garantire la corretta esecuzione.

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)

Figura 4. Errore ANR causato da un conflitto di blocchi.

Causa

Il problema è che vengono inviati diversi messaggi quando l'applicazione viene ripreso. I messaggi sono in coda perché non possono essere inviati durante la partita è in background. I messaggi vengono inviati tutti contemporaneamente quando e l'app riprenderà.

Durante un periodo di pausa, in genere memorizzi le informazioni del gioco nella server; ad esempio, registri la posizione di un giocatore nel gioco affinché quest'ultimo può tornare nello stesso luogo quando la partita riprende.

Questo carico di lavoro, combinato con altro codice di terze parti che crea il proprio carico di lavoro, può sovraccaricare le risorse del dispositivo, in particolare il thread principale. Il principale il thread esegue l'interfaccia utente di un'app ed è spesso la posizione principale degli ANR. Quindi, qualsiasi carico di lavoro aggiunto al thread principale aumenta il potenziale di un errore ANR.

Soluzione

Durante la pausa di un'applicazione, assicurati che tutte le azioni relative al codice siano necessarie oppure prova a salvare lo stato dell'utente nella memoria locale del dispositivo. E, naturalmente, vedi se puoi completare queste azioni anche al di fuori del periodo di pausa.

Alcuni approcci:

  • Spostare l'operazione C# che gestisce un messaggio in un thread diversi dal thread principale.
    • Se il tuo codice non dipende dal contesto del thread principale di Unity, usa Task per la comunicazione anziché per il messaggio.
  • Non inviare più messaggi dal tuo plug-in quando il gioco è in pausa.
    • Il motore non può inviare messaggi mentre il gioco è in background.
    • Invia al tuo gioco l'ultimo stato dei dati solo se questo non influisce su quest'ultimo funzionalità.

Installa referrer

Play Install Referrer è una stringa univoca inviata al Play Store ogni volta che un un utente fa clic su un annuncio. Si tratta di un identificatore di monitoraggio degli annunci specifico di Android. Una volta installata, l'app invia il referrer di installazione al partner di attribuzione, che corrisponde alla sorgente all'installazione (attribuisce la conversione).

Analisi dello stack

La figura 5 mostra un'analisi dello stack ANR di un gioco che utilizza l'SDK di Facebook per recuperare l'attribuzione delle installazioni.

Figura 5. Report Android vitals contenente una chiamata a Binder.

Causa

L'errore ANR è stato causato da una chiamata a binder lenta. Tuttavia, la causa principale non può essere determinato senza accesso al codice sorgente dell'SDK.

Soluzione

Per risolvere questo tipo di problema è necessario comunicare con lo sviluppatore dell'SDK o spesso cercano online una potenziale soluzione, controllando se un nuovo dell'SDK risolve l'errore ANR per altri o anche sperimentando con un di lancio.

Google fornisce una pagina SDK Index che combina i dati sull'utilizzo dalle app Google Play con informazioni raccolte tramite il rilevamento del codice per fornire attributi e indicatori pensati per aiutarti a decidere se adottare, mantenere o rimuovere un SDK dalla tua app.

Risorse aggiuntive

Per scoprire di più sugli errori ANR, consulta le seguenti risorse: