Unity Oyunlarında Yaygın ANR'ler

Unity ANR'leri çeşitli nedenlerden kaynaklanır. En yaygın ANR'lerin nedeni hatalı iletişim ve iletişim sorunları.

Web Görünümü

WebView, web sayfalarını gösteren bir Android sınıfıdır. Üçüncü taraf SDK'lar (ör. reklamlar), dinamik web içeriğini görüntülemek için WebView kullanır UnityPlayerActivity dışındaki etkinliklerde. ANR'ler, üçüncü tarafın SDK'lar, WebView politikasını kötüye kullanıyor.

Yığın izi

Yığın izleme, ANR'nin nedenini anlamak için başvuracağınız ilk başvurudur.

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

Şekil 1. futex beklemeden kaynaklanan ANR yığın izlemesi.

Neden

Şu ana kadar bu sorunun temel nedeni belirsiz. Bazı olası nedenler şunlardır:

  • Kötü reklam uygulaması.
  • Kullanıcı güncelleme yapmayı tercih etmemiş olabileceğinden eski bir WebView sürümü otomatik olarak yüklenir.
  • Sistem kaynaklarının (CPU, GPU vb.) yüksek oranda kullanımı. Bu da çok fazla profil çıkarma.
  • Gölgelendirme derlemesi kilitleniyor ve bu da içerik uyumsuz bir gölgelendiriciye sahip veya kullanıcının eski bir WebView sahibi var sürümü yüklendi.

Çözüm

  • Hangi içerik türünün WebView tarafından engellenmesine neden olduğunu bulmak için ana iş parçacığı, bir web sayfası yüklendiğinde, görüntülendiğinde emin olun.
    • Geri izleme veya Crashlytics'i kullanabilirsiniz raporlama hizmetleridir.
    • Ardından, verileri analiz edip sorunu bulduktan sonra rahatsız edici reklam sağlayıcıları.
    • Sorunun bellekle ilgili olmadığından emin olmak için bellek günlüklerini ekleyin.
  • Google Play'den WebView öğesini güncellemesi için kullanıcıyı uyarın. Android 5.0'dan (API düzeyi 21) ve sonraki sürümler için WebView, bir APK'ya taşındı. Bu nedenle, Android platformundan ayrı olarak güncellenir. WebView sürümünün hangisi olduğunu öğrenmek için bir cihazda kullanılıyorsa Ayarlar > Uygulamalar > Android Sistemi WebView'u tıklayın ve sayfanın alt kısmından sürüme bakın.
ziyaret edin.
WebView sürümlerinin gösterildiği uygulama bilgi ekranı.
Şekil 1. WebView sürümünü kontrol edin.

Unity duraklatma

UnityPlayerActivity bir onPause() çağrısı aldığında aşağıdaki zincir işlemlerin başlangıcı:

  1. UnityPlayerActivity, Unity çalışma zamanı motoruna etkinliğin duraklatıldı.
  2. Unity, şunu uygulayan her MonoBehaviour OnApplicationPause etkinliği.
  3. Unity, ses çalma, oluşturma ve yayınlama gibi bileşenleri ve modülleri oyun döngüsü ve animasyon.
  4. Hem Unity Android Player (UAP) hem de motorun UAP, motorun durması için 4 saniye bekler.
  5. Bu işlem 5 saniyeden uzun sürerse sistem bir ANR tetikler.

Yığın izi

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

Şekil 3. Hiç yayınlanmayan bir semaforun neden olduğu ANR.

Çözüm

C# oyun kodunuzun devam ettirebilirsiniz.

  • Oyununuzun profilini çıkarın ve OnApplicationPause cihazının pahalı bir cihaz olup olmadığını kontrol edin. işlemidir. Stopwatch kullanabilirsiniz.
  • G/Ç işlemlerinden veya eşzamanlı ağ isteklerinden kaçının.
  • İşlemleri başka bir Thread'e taşımak için Task. Unity 2023.1, basitleştirilmiş bir C# kullanan eşzamansız programlama modeli async ve await anahtar kelime.

UnitySendMessage engellendi

Java Unity eklentileri ve SDK'ları, JNI kullanarak C# oyun katmanına veri gönderir. Ancak bu iletişim, senkronizasyon rutini gibi, kilit çakışması nedeniyle ANR'ye neden oluyor.

Yığın izi

Şekil 4'teki ANR, C# kodunda Java eklentisi. Unity motoru, bir Öncelikli Olmayan Devralma komutunun doğru yürütülmesini sağlamak için

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)

Şekil 4. Kilit anlaşmazlığından kaynaklanan ANR.

Neden

Sorun, uygulama aynı anda birkaç iletinin gönderilmesi devam ettirilir. Mesajlar oyun sırasında gönderilemediği için sıraya alındı arka planda. emin olun.

Duraklama döneminde oyununuzun bilgileri genellikle şurada saklanır: sunucu; Örneğin, bir oyuncunun oyundaki konumunu kaydedersiniz. oyun devam ettiğinde aynı yere dönebilir.

Bu iş yükü, kendi iş yükünü oluşturan diğer üçüncü taraf kodlarıyla birlikte kullanıldığında cihaz kaynaklarında, özellikle de ana iş parçacığında aşırı yüklenmeye yol açabilir. Ana iş parçacığı bir uygulamanın kullanıcı arayüzünü çalıştırır ve genellikle ANR'lerin ana konumudur. Dolayısıyla, ana iş parçacığında ek iş yükü, ANR olasılığını artırır.

Çözüm

Uygulama duraklatması sırasında tüm kod işlemlerinizin gerekli olduğundan emin olun veya kullanıcının durumunu yerel cihazınızın belleğine kaydetmeyi deneyin. Tabii ki bu işlemleri duraklatma süresinin dışında da tamamlayıp tamamlayamayacağınızı belirleyin.

Birkaç yaklaşım:

  • İletiyi işleyen C# işlemini ileti dizisine taşıma diğerlerini görebilirsiniz.
    • Kodunuz Unity'nin ana iş parçacığı bağlamına bağlı değilse Mesaj yerine iletişim için Task.
  • Oyun duraklatıldığında eklentinizden birden fazla mesaj göndermeyin.
    • Oyun arka plandayken motor mesaj gönderemez.
    • Son veri durumunu yalnızca oyununuzu etkilemiyorsa gönderin işlevi görür.

Yönlendiren'i yükleyin

Play Install Referrer, bir Kullanıcı bir reklamı tıkladığında. Android'e özel bir reklam izleme kimliğidir. Bir kez yüklendiğinde uygulama, yükleme yönlendirenini ilişkilendirme iş ortağına gönderir. Bu da kaynağı yüklemeyle eşleştirir (dönüşümü ilişkilendirme).

Yığın izi

Şekil 5'te, aşağıdakileri yapmak için Facebook SDK'sını kullanan bir oyuna ait ANR yığın izlemesi (stack trace) gösterilmektedir almalarını isteyebilirsiniz.

Şekil 5. Bağlayıcı çağrısı içeren Android Vitals raporu.

Neden

ANR, yavaş bir bağlayıcı çağrısından kaynaklandı. Ancak, sorunun temel nedeni erişimi olmadan belirlenir.

Çözüm

Bu tür sorunları çözmek için SDK geliştiricisiyle veya potansiyel bir çözüm ararken, yeni bir çözüm olup olmadığını veya SDK'nın ANR'yi diğer kullanıcılar için çözdüğünü ve hatta küçük bir stratejik düşünmeyi kullanacaksınız.

Google, kullanım verilerini birleştiren bir SDK Dizini sayfası sağlar kod algılama üzerinden toplanan bilgilerle Google Play uygulamalarından gelen karar verirken size yol gösterecek olan özellikleri ve sinyalleri kullanmaya devam edebilir veya uygulamanızdan kaldırabilirsiniz.

Ek kaynaklar

ANR'ler hakkında daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın: