यूनिटी गेम से जुड़े सामान्य ANR

Unity अलग-अलग वजहों से ऐसा होता है. सबसे सामान्य ANR के कारण होते हैं Android और Unity कॉम्पोनेंट और उनकी गलत जानकारी का गलत इस्तेमाल.

WebView

WebView एक Android क्लास है, जिसमें वेब पेज दिखाए जाते हैं. तीसरा पक्ष डाइनैमिक वेब कॉन्टेंट दिखाने के लिए एसडीके (जैसे कि विज्ञापन) WebView का इस्तेमाल करते हैं UnityPlayerActivity के अलावा किसी अन्य गतिविधि में. ANR की गड़बड़ी तब होती है, जब तीसरा पक्ष SDK टूल, WebView का गलत इस्तेमाल करते हैं.

स्‍टैक ट्रेस

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)

इमेज 1.futex के इंतज़ार की वजह से हुआ ANR स्टैक ट्रेस.

वजह

अब तक, इस समस्या की असल वजह पता नहीं चल पाई है. इसकी कुछ वजहें हो सकती हैं शामिल करें:

  • गलत विज्ञापन लागू करना.
  • WebView का पुराना वर्शन, क्योंकि हो सकता है कि उपयोगकर्ता ने अपडेट न करने का विकल्प चुना हो उसे अपने-आप अपडेट कर दिया जाएगा.
  • सिस्टम के संसाधनों (सीपीयू, जीपीयू वगैरह) का ज़्यादा इस्तेमाल होता है. ऐसा करने के लिए, बहुत ज़्यादा पैसे खर्च करने पड़ सकते हैं प्रोफ़ाइल बनाना.
  • शडर कंपाइलेशन क्रैश हो जाता है, जिससे यह पता चल सकता है कि कॉन्टेंट में ऐसा शेडर है जो काम नहीं करता या उपयोगकर्ता के पास पुराना WebView है वर्शन इंस्टॉल किया गया.

समाधान

  • यह पता लगाने के लिए कि किस तरह के कॉन्टेंट की वजह से WebView, मुख्य थ्रेड, जब भी कोई वेब पेज लोड हो या दिखने लगे, तो अपने गेम में लॉग जोड़ें, या बंद.
    • बैकट्रेस या Crashlytics का इस्तेमाल किया जा सकता है रिपोर्टिंग सेवाएं उपलब्ध हैं.
    • फिर, डेटा का विश्लेषण करने और समस्या का पता लगाने के बाद, खोज बॉक्स में आपत्तिजनक विज्ञापन देने वाले लोग या कंपनियां.
    • यह पक्का करने के लिए कि समस्या मेमोरी से जुड़ी न हो, मेमोरी लॉग शामिल करें.
  • उपयोगकर्ता को Google Play से WebView को अपडेट करने के बारे में सूचना दें. Android 5.0 से (एपीआई लेवल 21) और उसके बाद वाले वर्शन के लिए, WebView को APK में ले जाया गया है. इसलिए, यह काम किया जा सकता है इन्हें Android प्लैटफ़ॉर्म से अलग अपडेट किया जाता है. यह देखने के लिए कि WebView का कौनसा वर्शन डिवाइस पर इस्तेमाल किया जा रहा है, तो सेटिंग > ऐप्लिकेशन > Android सिस्टम वेबव्यू और पेज के सबसे नीचे मौजूद वर्शन देखें.
ऐप्लिकेशन की जानकारी वाली स्क्रीन, जिसमें वेबव्यू वर्शन दिखाए गए हैं.
पहली इमेज. WebView का वर्शन देखें.

यूनिटी पॉज़

जब UnityPlayerActivity को onPause() कॉल आता है, तो इसकी ये चेन ऑपरेशन शुरू होने की तारीख:

  1. UnityPlayerActivity, Unity रनटाइम इंजन को यह सूचना देता है कि गतिविधि रोका गया.
  2. Unity सभी ऐसे MonoBehaviour को कॉल करता है जो OnApplicationPause इवेंट.
  3. Unity अपने कॉम्पोनेंट और मॉड्यूल को बंद कर देता है, जैसे कि आवाज़ चलाना, रेंडरिंग, और ऐनिमेशन शामिल हैं.
  4. यह पक्का करने के लिए कि Unity Android Player (यूएपी) और इंजन, दोनों एक ही हों सिंक किए गए होने पर, UAP चार सेकंड तक इंतज़ार करता है, ताकि इंजन बंद हो जाए.
  5. अगर इस कार्रवाई में पांच सेकंड से ज़्यादा समय लगता है, तो सिस्टम ANR की गड़बड़ी ट्रिगर कर देता है.

स्‍टैक ट्रेस

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

तीसरी इमेज. यह ANR सेमाफ़ोर की वजह से होता है, जो कभी रिलीज़ नहीं होता.

समाधान

पक्का करें कि आपके C# गेम कोड को इवेंट को रोकें या फिर से शुरू करें.

  • अपने गेम की प्रोफ़ाइल बनाएं और देखें कि OnApplicationPause महंगा है या नहीं कार्रवाई. आपके पास Stopwatch का इस्तेमाल करने का विकल्प है.
  • I/O से जुड़ी कार्रवाइयों या सिंक्रोनस नेटवर्क अनुरोधों से बचें.
  • इसका इस्तेमाल करके ऑपरेशन को किसी दूसरी Thread पर ले जाएं Task. Unity 2023.1, आसान एआई मॉडल के साथ काम करता है C# का इस्तेमाल करके, एसिंक्रोनस प्रोग्रामिंग मॉडल async और await कीवर्ड.

UnitySendMessage को ब्लॉक किया गया

Java Unity प्लगिन और SDK टूल, JNI का इस्तेमाल करके C# गेम लेयर को डेटा भेजते हैं. हालांकि, इस बातचीत में आपके डोमेन के मूल मैसेज की वजह से मुख्य थ्रेड ब्लॉक हो सकता है सिंक करने का रूटीन, जैसे कि म्यूटेक्स. लॉक से जुड़े विवाद की वजह से ANR की गड़बड़ी होती है.

स्‍टैक ट्रेस

चौथी इमेज में ANR की गड़बड़ी, C# कोड में लंबे समय तक चलने की वजह से हुई. Java प्लगिन. Unity इंजन, गैर-प्राथमिकता इनहेरिटेंस का इस्तेमाल करता है म्यूट करें.

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)

चौथी इमेज. लॉक के विवाद की वजह से होने वाली ANR की गड़बड़ी.

वजह

समस्या यह है कि आवेदन के समय कई संदेश भेजे जा रहे हैं फिर से शुरू कर दिया गया है. मैसेज इसलिए सूची में हैं, क्योंकि गेम खेलने के दौरान उन्हें भेजा नहीं जा सकता बैकग्राउंड में मौजूद है. सभी संदेश एक साथ प्रेषित करने के लिए जब ऐप फिर से शुरू हो जाता है.

रोके जाने की अवधि के दौरान, आप आमतौर पर अपने गेम की जानकारी सर्वर; उदाहरण के लिए, आप गेम में किसी खिलाड़ी की स्थिति रिकॉर्ड करते हैं, ताकि प्लेयर गेम के दोबारा शुरू होने पर, उसी जगह पर वापस आ सकते हैं.

यह वर्कलोड, दूसरे तीसरे पक्ष के कोड के साथ मिलकर अपना वर्कलोड बनाता है, डिवाइस के रिसॉर्स को ओवरलोड कर सकता है. खास तौर पर, मुख्य थ्रेड को. मुख्य थ्रेड, किसी ऐप्लिकेशन का यूज़र इंटरफ़ेस चलाता है. इसी डिवाइस पर ANR की मुख्य समस्या होती है. इसलिए, मुख्य थ्रेड में अगर कोई वर्कलोड ज़्यादा जोड़ा जाता है, तो ANR की गड़बड़ी होने की संभावना बढ़ जाती है.

समाधान

ऐप्लिकेशन रोके जाने के दौरान, पक्का करें कि आपके कोड से जुड़ी सभी कार्रवाइयां ज़रूरी हैं या अपने डिवाइस की मेमोरी में उपयोगकर्ता की स्थिति को सेव करके देखें. और हां, आपने रोकने की अवधि के बाद भी इन कार्रवाइयों को पूरा किया जा सकता है.

कुछ तरीके:

  • किसी मैसेज को थ्रेड पर हैंडल करने वाली C# कार्रवाई को दूसरी जगह ले जाएं मुख्य थ्रेड के अलावा अन्य.
    • अगर आपका कोड Unity के मुख्य थ्रेड के कॉन्टेक्स्ट पर निर्भर नहीं है, तो इसका इस्तेमाल करें मैसेज के बजाय, बातचीत के लिए Task.
  • गेम के रोके जाने पर, अपने प्लगिन से एक से ज़्यादा मैसेज न भेजें.
    • गेम के बैकग्राउंड में चलने के दौरान इंजन मैसेज नहीं भेज सकता.
    • अपने गेम को डेटा की पिछली स्थिति सिर्फ़ तब भेजें, जब इससे आपके गेम पर कोई असर न पड़े सुविधा पर काम करता है.

रेफ़रलकर्ता इंस्टॉल करें

Play Store का रेफ़रल देने वाला एक यूनीक स्ट्रिंग होती है, जो Play Store को भेजी जाती है. जब उपयोगकर्ता किसी विज्ञापन पर क्लिक करता है. यह Android के लिए खास तौर पर बनाया गया विज्ञापन ट्रैकिंग आइडेंटिफ़ायर है. एक बार इंस्टॉल करने के बाद, ऐप्लिकेशन एट्रिब्यूशन पार्टनर को इंस्टॉल रेफ़रर भेजता है, जो सोर्स से मेल खाता है और इंस्टॉल के साथ (कन्वर्ज़न को एट्रिब्यूट किया जा रहा है).

स्‍टैक ट्रेस

पांचवीं इमेज में, एक ऐसे गेम का ANR स्टैक ट्रेस दिखाया गया है जो Facebook SDK टूल का इस्तेमाल करके इंस्टॉल एट्रिब्यूशन फिर से पाएं.

पांचवीं इमेज. Android की ज़रूरी जानकारी वाली रिपोर्ट में बाइंडर कॉल की जानकारी शामिल होती है.

वजह

ANR की गड़बड़ी, धीमे बाइंडर कॉल की वजह से हुई थी. हालांकि, इसकी असल वजह यह नहीं हो सकती कि SDK टूल के सोर्स कोड के ऐक्सेस के बिना तय किया जाता है.

समाधान

इस तरह की समस्या को हल करने के लिए, SDK टूल के डेवलपर या कई लोग ऑनलाइन प्लैटफ़ॉर्म पर किसी समस्या का समाधान ढूंढ रहे हैं. साथ ही, यह जांच रहे हैं कि क्या वह SDK टूल के वर्शन से दूसरों के लिए ANR की गड़बड़ी को ठीक किया जा सकता है या किसी छोटे वर्शन के साथ भी एक्सपेरिमेंट किया जा सकता है रोल आउट रणनीति तय की.

Google, SDK टूल इंडेक्स पेज उपलब्ध कराता है, जिसमें इस्तेमाल के बारे में डेटा होता है Google Play ऐप्लिकेशन से इकट्ठा की गई जानकारी से लेकर, वे एट्रिब्यूट और सिग्नल उपलब्ध कराते हैं जिनकी मदद से यह तय किया जा सकता है कि उन्हें अपने ऐप्लिकेशन से किसी SDK टूल को रखना या हटाना.

अन्य संसाधन

एएनआर के बारे में ज़्यादा जानने के लिए, नीचे दिए गए संसाधन देखें: