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 सिस्टम वेबव्यू और पेज के सबसे नीचे मौजूद वर्शन देखें.
यूनिटी पॉज़
जब UnityPlayerActivity
को onPause()
कॉल आता है, तो इसकी ये चेन
ऑपरेशन शुरू होने की तारीख:
UnityPlayerActivity
, Unity रनटाइम इंजन को यह सूचना देता है कि गतिविधि रोका गया.- Unity सभी ऐसे
MonoBehaviour
को कॉल करता है जोOnApplicationPause
इवेंट. - Unity अपने कॉम्पोनेंट और मॉड्यूल को बंद कर देता है, जैसे कि आवाज़ चलाना, रेंडरिंग, और ऐनिमेशन शामिल हैं.
- यह पक्का करने के लिए कि
Unity Android Player
(यूएपी) और इंजन, दोनों एक ही हों सिंक किए गए होने पर, UAP चार सेकंड तक इंतज़ार करता है, ताकि इंजन बंद हो जाए. - अगर इस कार्रवाई में पांच सेकंड से ज़्यादा समय लगता है, तो सिस्टम 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
.
- अगर आपका कोड Unity के मुख्य थ्रेड के कॉन्टेक्स्ट पर निर्भर नहीं है, तो इसका इस्तेमाल करें
मैसेज के बजाय, बातचीत के लिए
- गेम के रोके जाने पर, अपने प्लगिन से एक से ज़्यादा मैसेज न भेजें.
- गेम के बैकग्राउंड में चलने के दौरान इंजन मैसेज नहीं भेज सकता.
- अपने गेम को डेटा की पिछली स्थिति सिर्फ़ तब भेजें, जब इससे आपके गेम पर कोई असर न पड़े सुविधा पर काम करता है.
रेफ़रलकर्ता इंस्टॉल करें
Play Store का रेफ़रल देने वाला एक यूनीक स्ट्रिंग होती है, जो Play Store को भेजी जाती है. जब उपयोगकर्ता किसी विज्ञापन पर क्लिक करता है. यह Android के लिए खास तौर पर बनाया गया विज्ञापन ट्रैकिंग आइडेंटिफ़ायर है. एक बार इंस्टॉल करने के बाद, ऐप्लिकेशन एट्रिब्यूशन पार्टनर को इंस्टॉल रेफ़रर भेजता है, जो सोर्स से मेल खाता है और इंस्टॉल के साथ (कन्वर्ज़न को एट्रिब्यूट किया जा रहा है).
स्टैक ट्रेस
पांचवीं इमेज में, एक ऐसे गेम का ANR स्टैक ट्रेस दिखाया गया है जो Facebook SDK टूल का इस्तेमाल करके इंस्टॉल एट्रिब्यूशन फिर से पाएं.
वजह
ANR की गड़बड़ी, धीमे बाइंडर कॉल की वजह से हुई थी. हालांकि, इसकी असल वजह यह नहीं हो सकती कि SDK टूल के सोर्स कोड के ऐक्सेस के बिना तय किया जाता है.
समाधान
इस तरह की समस्या को हल करने के लिए, SDK टूल के डेवलपर या कई लोग ऑनलाइन प्लैटफ़ॉर्म पर किसी समस्या का समाधान ढूंढ रहे हैं. साथ ही, यह जांच रहे हैं कि क्या वह SDK टूल के वर्शन से दूसरों के लिए ANR की गड़बड़ी को ठीक किया जा सकता है या किसी छोटे वर्शन के साथ भी एक्सपेरिमेंट किया जा सकता है रोल आउट रणनीति तय की.
Google, SDK टूल इंडेक्स पेज उपलब्ध कराता है, जिसमें इस्तेमाल के बारे में डेटा होता है Google Play ऐप्लिकेशन से इकट्ठा की गई जानकारी से लेकर, वे एट्रिब्यूट और सिग्नल उपलब्ध कराते हैं जिनकी मदद से यह तय किया जा सकता है कि उन्हें अपने ऐप्लिकेशन से किसी SDK टूल को रखना या हटाना.
अन्य संसाधन
एएनआर के बारे में ज़्यादा जानने के लिए, नीचे दिए गए संसाधन देखें:
- ANR डीबग करना — Android गेम डेवलपमेंट
- ANR — ऐप्लिकेशन की क्वालिटी