ANR ডিবাগ করুন

আপনার ইউনিটি গেমে ANR সমাধান করা একটি পদ্ধতিগত প্রক্রিয়া:

চিত্র ১. ইউনিটি গেমে ANR সমাধানের ধাপসমূহ।

রিপোর্টিং পরিষেবাগুলি একীভূত করুন

Android vitals , Firebase Crashlytics , এবং Backtrace (একটি সার্টিফাইড ইউনিটি পার্টনার)-এর মতো রিপোর্টিং সার্ভিসগুলো আপনার গেমের জন্য বৃহৎ পরিসরে এরর লগিং এবং অ্যানালাইসিস প্রদান করে। ডেভেলপমেন্ট সাইকেলের শুরুতেই আপনার গেমে রিপোর্টিং সার্ভিস SDK-গুলো ইন্টিগ্রেট করুন। বিশ্লেষণ করে দেখুন কোন রিপোর্টিং সার্ভিসটি আপনার গেমের প্রয়োজন ও বাজেটের জন্য সবচেয়ে উপযুক্ত।

বিভিন্ন রিপোর্টিং সার্ভিসের ANR ক্যাপচার করার পদ্ধতি ভিন্ন। ANR ঠিক করার ক্ষেত্রে আপনার সিদ্ধান্তকে সমর্থন করার জন্য বৈধ ডেটা পাওয়ার সম্ভাবনা বাড়াতে একটি দ্বিতীয় রিপোর্টিং সার্ভিস অন্তর্ভুক্ত করুন।

রিপোর্টিং SDK ইন্টিগ্রেট করলে গেমের পারফরম্যান্স বা APK সাইজের উপর কোনো প্রভাব পড়ে না।

প্রতীক বিশ্লেষণ করুন

আপনার রিপোর্টিং পরিষেবা থেকে প্রাপ্ত রিপোর্টগুলো বিশ্লেষণ করুন এবং স্ট্যাক ট্রেসগুলো পাঠযোগ্য বিন্যাসে আছে কিনা তা পরীক্ষা করুন। আরও তথ্যের জন্য Symbolicate Android crashes এবং Unity গেমসের জন্য ANR দেখুন।

চিত্র ২. ক্র্যাশলিটিক্সে বিল্ড আইডি এবং অনুপস্থিত libil2cpp.so সিম্বলগুলো দেখানো হচ্ছে।

সিম্বল বিল্ড আইডি কীভাবে চেক করবেন

যদি রিপোর্টিং সিস্টেমে বিল্ড আইডি অনুপস্থিত দেখায় কিন্তু বিল্ড সিম্বলগুলো বিল্ড মেশিনের স্টোরেজে থেকে যায়, তবে সিম্বলগুলোর বিল্ড আইডি যাচাই করে সেগুলোকে রিপোর্টিং সার্ভিসে আপলোড করা সম্ভব। অন্যথায়, সিম্বল ফাইলগুলো আপলোড করার জন্য একটি নতুন বিল্ড তৈরি করতে হবে।

উইন্ডোজ বা ম্যাকওএস-এ:

  1. আপনার স্ক্রিপ্টিং ব্যাকএন্ড অনুযায়ী সিম্বলস ফোল্ডারে যান ( রেজোলিউশন দেখুন :)
    1. নিম্নলিখিত কমান্ডটি ব্যবহার করুন (উইন্ডোজে, readelf ইউটিলিটিটি চালানোর জন্য Cygwin ব্যবহার করুন)।
    2. টেক্সট আউটপুট ফিল্টার করার জন্য গ্রেপ (Grep) ব্যবহার ঐচ্ছিক।
    3. বিল্ড আইডি খুঁজুন
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

গেম কোড পরিদর্শন করুন

যখন স্ট্যাক ট্রেসে libil2cpp.so লাইব্রেরির কোনো ফাংশন দেখা যায়, তখন বুঝতে হবে ত্রুটিটি C# কোডে ঘটেছে, যা C++ এ রূপান্তরিত করা হয়েছে। libil2cpp.so লাইব্রেরিতে শুধু আপনার গেমের কোডই নয়, প্লাগইন এবং প্যাকেজও থাকে।

ইউনিটি প্রজেক্টে সংজ্ঞায়িত অ্যাসেম্বলি নামটি C++ ফাইলের নামে বসে। অন্যথায়, ফাইলের নামটি ডিফল্ট অ্যাসেম্বলি-C# নাম অনুযায়ী হয়। উদাহরণস্বরূপ, চিত্র ৩-এ Game.cpp ফাইলের ত্রুটিটি দেখানো হয়েছে (নীল রঙে চিহ্নিত), যার নামটি অ্যাসেম্বলি ডেফিনিশন ফাইলে সংজ্ঞায়িত করা আছে। C# স্ক্রিপ্টে Logger হলো ক্লাসের নাম (লাল রঙে চিহ্নিত), এরপরে রয়েছে ফাংশনের নাম (সবুজ রঙে চিহ্নিত)। সবশেষে, IL2CPP কনভার্টার দ্বারা তৈরি করা সম্পূর্ণ নামটি (কমলা রঙে চিহ্নিত)।

চিত্র ৩. ব্যাকট্রেস থেকে প্রাপ্ত টেস্ট প্রজেক্টের কল স্ট্যাক।

নিম্নলিখিত কাজগুলো করে আপনার গেম কোড পরীক্ষা করুন:

  • কোনো সন্দেহজনক কোডের জন্য C# প্রজেক্টটি পরীক্ষা করুন। সাধারণত, C# এর আনহ্যান্ডেলড এক্সেপশনগুলো ANR বা অ্যাপ্লিকেশন ক্র্যাশের কারণ হয় না। তা সত্ত্বেও, কোডটি বিভিন্ন পরিস্থিতিতে সঠিকভাবে চলে কিনা তা নিশ্চিত করুন। কোডটি কোনো থার্ড-পার্টি ইঞ্জিন মডিউল ব্যবহার করছে কিনা তা পরীক্ষা করুন এবং সাম্প্রতিক কোনো রিলিজের কারণে এই ত্রুটিটি এসেছে কিনা তা বিশ্লেষণ করুন। এছাড়াও, আপনি সম্প্রতি ইউনিটি আপডেট করেছেন কিনা বা ত্রুটিটি শুধুমাত্র নির্দিষ্ট ডিভাইসে ঘটছে কিনা তা পর্যালোচনা করুন।
  • গেমটিকে একটি অ্যান্ড্রয়েড স্টুডিও প্রজেক্ট হিসেবে এক্সপোর্ট করুন । আপনার গেমের রূপান্তরিত C# সোর্স কোডে সম্পূর্ণ অ্যাক্সেস পেলে, আপনি ANR সমস্যার কারণ হওয়া ফাংশনটি খুঁজে বের করতে পারবেন। C++ কোডটি আপনার C# কোড থেকে দেখতে অনেকটাই আলাদা, এবং কোড রূপান্তরে খুব কমই কোনো সমস্যা হয়। যদি আপনি কিছু খুঁজে পান, তবে ইউনিটির কাছে একটি সাপোর্ট টিকেট ফাইল করুন।
  • গেমের সোর্স কোড পর্যালোচনা করুন এবং নিশ্চিত করুন যে OnApplicationFocus()OnApplicationPause() কলব্যাকগুলিতে চলমান সমস্ত লজিক যথাযথভাবে পরিমার্জিত হয়েছে।
    • ইউনিটি ইঞ্জিনের কার্য সম্পাদন থামানোর জন্য একটি টাইমআউট থাকে; এই কলব্যাকগুলির উপর অতিরিক্ত কাজের চাপ একটি ANR ঘটাতে পারে।
    • আপনার ডেটা বিশ্লেষণকে আরও উন্নত করতে কোডের বিভিন্ন অংশে লগ বা ব্রেডক্রাম্ব যোগ করুন।
  • গেমটির পারফরম্যান্স খতিয়ে দেখতে ইউনিটি প্রোফাইলার ব্যবহার করুন। আপনার অ্যাপের প্রোফাইলিং সেইসব প্রতিবন্ধকতা শনাক্ত করার একটি দারুণ উপায় হতে পারে, যা ANR-এর কারণ হতে পারে।
  • প্রধান থ্রেডে দীর্ঘ I/O অপারেশন শনাক্ত করার একটি দারুণ উপায় হলো স্ট্রিক্ট মোড ব্যবহার করা।
  • অ্যান্ড্রয়েড ভাইটালস বা অন্য কোনো রিপোর্টিং সার্ভিসের হিস্ট্রি বিশ্লেষণ করুন এবং গেমটির কোন রিলিজ ভার্সনগুলোতে এই ত্রুটিটি সবচেয়ে বেশি ঘটছে তা পরীক্ষা করুন। আপনার ভার্সন কন্ট্রোল হিস্ট্রিতে সোর্স কোড পর্যালোচনা করুন এবং বিভিন্ন রিলিজের মধ্যে কোডের পরিবর্তনগুলো তুলনা করুন। যদি কোনো সন্দেহজনক কিছু খুঁজে পান, তবে প্রতিটি পরিবর্তন বা সম্ভাব্য সমাধান নিয়ে আলাদাভাবে পরীক্ষা-নিরীক্ষা করুন।
  • যেসব ডিভাইস এবং অ্যান্ড্রয়েড ভার্সনে সবচেয়ে বেশি ANR এসেছে, সেগুলোর জন্য Google Play-এর ANR রিপোর্টিং হিস্ট্রি পরীক্ষা করুন। ডিভাইস বা ভার্সনগুলো যদি পুরোনো হয়ে থাকে, তবে সম্ভবত আপনি নিরাপদে সেগুলোকে উপেক্ষা করতে পারেন, যদি তা গেমটির লাভজনকতাকে প্রভাবিত না করে। ডেটা সাবধানে বিশ্লেষণ করুন, কারণ ব্যবহারকারীদের একটি নির্দিষ্ট গোষ্ঠী আর আপনার গেমটি খেলতে পারবে না। আরও তথ্যের জন্য, ডিস্ট্রিবিউশন ড্যাশবোর্ড দেখুন।
  • গেমের সোর্স কোড পর্যালোচনা করে নিশ্চিত করুন যে আপনি এমন কোনো কোড কল করছেন না যা কোনো সমস্যা সৃষ্টি করতে পারে; উদাহরণস্বরূপ, `finish` ফাংশনটি সঠিকভাবে ব্যবহার না করা হলে ক্ষতিকর হতে পারে। অ্যান্ড্রয়েড ডেভেলপমেন্ট সম্পর্কে আরও জানতে অ্যান্ড্রয়েড ডেভেলপার গাইডগুলো দেখুন।
  • ডেটা পর্যালোচনা করে গেম বিল্ডটি অ্যান্ড্রয়েড স্টুডিওতে এক্সপোর্ট করার পর, আপনি C এবং C++ কোড নিয়ে কাজ করেন। তাই আপনি ইউনিটির সাধারণ সমাধানগুলোর বাইরেও বিভিন্ন টুলের পূর্ণ সুবিধা নিতে পারেন, যেমন— অ্যান্ড্রয়েড মেমোরি প্রোফাইলার , অ্যান্ড্রয়েড সিপিইউ প্রোফাইলার এবং পারফেটটো

ইউনিটি ইঞ্জিন কোড

ইউনিটি ইঞ্জিনের দিক থেকে কোনো ANR হচ্ছে কিনা তা জানতে, স্ট্যাক ট্রেসে libUnity.so বা libMain.so আছে কিনা তা পরীক্ষা করুন। যদি সেগুলি খুঁজে পান, তাহলে নিম্নলিখিত পদক্ষেপগুলি গ্রহণ করুন:

  • প্রথমে, কমিউনিটি চ্যানেলগুলোতে ( ইউনিটি ফোরাম , ইউনিটি ডিসকাশন , স্ট্যাকওভারফ্লো ) অনুসন্ধান করুন।
  • যদি আপনি কিছু খুঁজে না পান, তাহলে সমস্যাটি সমাধানের জন্য একটি বাগ রিপোর্ট করুন । একটি সিম্বলিকেটেড স্ট্যাক ট্রেস প্রদান করুন, যাতে ইঞ্জিনের ইঞ্জিনিয়াররা ত্রুটিটি আরও ভালোভাবে বুঝতে ও সমাধান করতে পারেন।
  • সর্বশেষ ইউনিটি এলটিএস (Unity LTS) সংস্করণে আপনার সমস্যাগুলোর কোনো উন্নতি করা হয়েছে কিনা তা যাচাই করুন। যদি হয়ে থাকে, তবে সেই সংস্করণটি ব্যবহার করার জন্য আপনার গেমটি আপগ্রেড করুন। (এই সমাধানটি শুধুমাত্র কিছু ডেভেলপারের জন্য সম্ভব হতে পারে।)
  • আপনার কোডে যদি ডিফল্ট অ্যাক্টিভিটির পরিবর্তে কাস্টম Activity ব্যবহার করা হয়, তবে অ্যাক্টিভিটিটি কোনো সমস্যা সৃষ্টি করছে না তা নিশ্চিত করতে জাভা কোডটি পর্যালোচনা করুন।

তৃতীয় পক্ষের SDK

  • যাচাই করুন যে সমস্ত থার্ড-পার্টি লাইব্রেরি হালনাগাদ আছে এবং অ্যান্ড্রয়েডের সর্বশেষ সংস্করণের জন্য সেগুলিতে কোনো ক্র্যাশ বা ANR-এর রিপোর্ট নেই।
  • ইউনিটি ফোরামে গিয়ে দেখুন পরবর্তী কোনো সংস্করণে কোনো ত্রুটি সমাধান করা হয়েছে কিনা, অথবা ইউনিটি বা কমিউনিটির কোনো সদস্যের পক্ষ থেকে কোনো বিকল্প সমাধান দেওয়া হয়েছে কিনা।
  • গুগল প্লে ANR রিপোর্টটি পর্যালোচনা করুন এবং নিশ্চিত করুন যে ত্রুটিটি গুগল দ্বারা ইতোমধ্যেই চিহ্নিত করা হয়নি। গুগল কিছু ANR সম্পর্কে অবগত এবং সেগুলি সমাধান করার জন্য সক্রিয়ভাবে কাজ করছে।

সিস্টেম লাইব্রেরি

সিস্টেম লাইব্রেরিগুলো সাধারণত ডেভেলপারের নিয়ন্ত্রণের বাইরে থাকে, কিন্তু ANR-এর ক্ষেত্রে এগুলোর সংখ্যা উল্লেখযোগ্য নয়। লাইব্রেরি ডেভেলপারের সাথে যোগাযোগ করা বা সমস্যাটি চিহ্নিত করার জন্য লগ যোগ করা ছাড়া, সিস্টেম লাইব্রেরিজনিত ANR-এর সমাধান করা কঠিন।

প্রস্থানের কারণ

ApplicationExitInfo হলো ANR-এর কারণ বোঝার জন্য একটি অ্যান্ড্রয়েড এপিআই। আপনার গেমে যদি ইউনিটি ৬ বা তার পরবর্তী সংস্করণ ব্যবহৃত হয়, তবে আপনি সরাসরি ApplicationExitInfo কল করতে পারেন। ইউনিটির পুরোনো সংস্করণগুলোর জন্য, ইউনিটি থেকে ApplicationExitInfo কল করা সক্ষম করতে আপনাকে নিজস্ব প্লাগইন তৈরি করতে হবে।

Crashlytics-ও ApplicationExitInfo ব্যবহার করে; তবে, আপনার নিজস্ব বাস্তবায়ন আপনাকে আরও সূক্ষ্ম নিয়ন্ত্রণ দেয় এবং আরও প্রাসঙ্গিক তথ্য অন্তর্ভুক্ত করতে সক্ষম করে।