با استفاده از ویژگی های پیشرفته Crashlytics، خرابی های بازی Unity را درک کنید

۱. مقدمه

در این آزمایشگاه کد، یاد خواهید گرفت که چگونه از ویژگی‌های پیشرفته Crashlytics استفاده کنید که به شما دید بهتری نسبت به خرابی‌ها و شرایطی که ممکن است باعث آنها شده باشد، می‌دهد.

شما قابلیت‌های جدیدی را به یک بازی نمونه، MechaHamster: Level Up with Firebase Edition ، اضافه خواهید کرد. این بازی نمونه، نسخه جدیدی از بازی کلاسیک Firebase، MechaHamster، است که بیشتر قابلیت‌های داخلی Firebase آن حذف شده و به شما این امکان را می‌دهد که کاربردهای جدیدی از Firebase را به جای آنها پیاده‌سازی کنید.

شما یک منوی اشکال‌زدایی به بازی اضافه خواهید کرد. این منوی اشکال‌زدایی، متدهایی را که ایجاد خواهید کرد فراخوانی می‌کند و به شما امکان می‌دهد عملکردهای مختلف Crashlytics را اعمال کنید. این متدها به شما نشان می‌دهند که چگونه گزارش‌های خرابی خودکار خود را با کلیدهای سفارشی، گزارش‌های سفارشی، خطاهای غیرمهلک و موارد دیگر حاشیه‌نویسی کنید.

پس از ساخت بازی، از منوی اشکال‌زدایی (debug) استفاده خواهید کرد و نتایج را بررسی خواهید کرد تا دیدگاه منحصر به فردی را که در مورد نحوه اجرای بازی شما در عمل ارائه می‌دهند، درک کنید.

آنچه یاد خواهید گرفت

  • انواع خطاهایی که به طور خودکار توسط Crashlytics شناسایی می‌شوند.
  • خطاهای اضافی که می‌توانند به طور هدفمند ثبت شوند.
  • چگونه می‌توان اطلاعات بیشتری به این خطاها اضافه کرد تا درک آنها آسان‌تر شود.

آنچه نیاز دارید

  • یونیتی (حداقل نسخه پیشنهادی ۲۰۱۹ به بالا) با یک یا هر دو مورد زیر:
    • پشتیبانی ساخت iOS
    • پشتیبانی از ساخت اندروید
  • (فقط برای اندروید) رابط خط فرمان فایربیس (برای آپلود نمادها برای گزارش‌های خرابی استفاده می‌شود)

۲. محیط توسعه خود را تنظیم کنید

بخش‌های بعدی نحوه دانلود کد Level Up با Firebase و باز کردن آن در Unity را شرح می‌دهند.

توجه داشته باشید که این بازی نمونه Level Up with Firebase توسط چندین آزمایشگاه کد Firebase + Unity دیگر استفاده می‌شود، بنابراین ممکن است قبلاً وظایف این بخش را انجام داده باشید. در این صورت، می‌توانید مستقیماً به آخرین مرحله در این صفحه بروید: "افزودن SDK های Firebase برای Unity".

کد را دانلود کنید

مخزن گیت‌هاب این codelab را از خط فرمان کلون کنید:

git clone https://github.com/firebase/level-up-with-firebase.git

از طرف دیگر، اگر git را نصب ندارید، می‌توانید مخزن را به صورت یک فایل ZIP دانلود کنید .

باز کردن Level Up با Firebase در ویرایشگر Unity

  1. Unity Hub را اجرا کنید و از تب Projects ، روی فلش کشویی کنار Open کلیک کنید.
  2. روی افزودن پروژه از دیسک کلیک کنید.
  3. به پوشه‌ای که کد در آن قرار دارد بروید و سپس روی تأیید کلیک کنید.
  4. در صورت درخواست، نسخه ویرایشگر Unity مورد استفاده و پلتفرم هدف خود (Android یا iOS) را انتخاب کنید.
  5. روی نام پروژه، level-up-with-firebase ، کلیک کنید تا پروژه در ویرایشگر Unity باز شود.
  6. اگر ویرایشگر شما به طور خودکار آن را باز نکرد، MainGameScene در Assets > Hamster در تب Project ویرایشگر Unity باز کنید.
    ff4ea3f3c0d29379.png

برای اطلاعات بیشتر در مورد نصب و استفاده از یونیتی، به «کار در یونیتی» مراجعه کنید.

۳. فایربیس را به پروژه یونیتی خود اضافه کنید

ایجاد یک پروژه فایربیس

  1. با استفاده از حساب گوگل خود وارد کنسول فایربیس شوید.
  2. برای ایجاد یک پروژه جدید، روی دکمه کلیک کنید و سپس نام پروژه را وارد کنید (برای مثال، Mechahamster Codelab ).
  3. روی ادامه کلیک کنید.
  4. در صورت درخواست، شرایط Firebase را مرور و قبول کنید و سپس روی ادامه کلیک کنید.
  5. (اختیاری) دستیار هوش مصنوعی را در کنسول Firebase (با نام "Gemini در Firebase") فعال کنید.
  6. برای این آزمایشگاه کد، برای استفاده بهینه از محصولات Firebase به Google Analytics نیاز دارید، بنابراین گزینه Google Analytics را فعال نگه دارید. برای تنظیم Google Analytics، دستورالعمل‌های روی صفحه را دنبال کنید.
  7. روی ایجاد پروژه کلیک کنید، منتظر بمانید تا پروژه شما آماده شود و سپس روی ادامه کلیک کنید.

برنامه خود را با Firebase ثبت کنید

  1. همچنان در کنسول Firebase ، از مرکز صفحه نمای کلی پروژه، روی آیکون Unity کلیک کنید تا گردش کار راه‌اندازی شود یا اگر قبلاً برنامه‌ای را به پروژه Firebase خود اضافه کرده‌اید، روی Add app کلیک کنید تا گزینه‌های پلتفرم نمایش داده شود.
  2. برای ثبت هر دو هدف ساخت اپل (iOS) و اندروید، انتخاب کنید.
  3. شناسه (شناسه‌های) مخصوص پلتفرم پروژه Unity خود را وارد کنید. برای این codelab، موارد زیر را وارد کنید:
  4. (اختیاری) نام مستعار مخصوص پلتفرم پروژه یونیتی خود را وارد کنید.
  5. روی ثبت برنامه کلیک کنید و سپس به بخش دانلود فایل پیکربندی بروید.

اضافه کردن فایل‌های پیکربندی فایربیس

پس از کلیک روی ثبت برنامه ، از شما خواسته می‌شود دو فایل پیکربندی (یک فایل پیکربندی برای هر هدف ساخت) را دانلود کنید. پروژه Unity شما برای اتصال به Firebase به فراداده Firebase در این فایل‌ها نیاز دارد.

  1. هر دو فایل پیکربندی موجود را دانلود کنید:
    • برای اپل (iOS) : فایل GoogleService-Info.plist را دانلود کنید.
    • برای اندروید : google-services.json را دانلود کنید.
  2. پنجره پروژه Unity خود را باز کنید، سپس هر دو فایل پیکربندی را به پوشه Assets منتقل کنید.
  3. به کنسول Firebase برگردید، در گردش کار تنظیمات، روی Next کلیک کنید و به Add Firebase SDKs for Unity بروید.

اضافه کردن SDK های فایربیس برای یونیتی

  1. در کنسول فایربیس، روی دانلود Firebase Unity SDK کلیک کنید.
  2. SDK را در جایی مناسب از حالت فشرده خارج کنید.
  3. در پروژه یونیتی باز خود، به مسیر Assets > Import Package > Custom Package بروید.
  4. در پنجره‌ی «وارد کردن بسته» ، به پوشه‌ای که SDK از حالت فشرده خارج شده در آن قرار دارد بروید، FirebaseAnalytics.unitypackage را انتخاب کنید و سپس روی «باز کردن» کلیک کنید.
  5. از پنجره‌ی «وارد کردن بسته‌ی یونیتی» که ظاهر می‌شود، روی «وارد کردن» کلیک کنید.
  6. مراحل قبلی را برای وارد کردن FirebaseCrashlytics.unitypackage تکرار کنید.
  7. به کنسول Firebase برگردید و در گردش کار تنظیمات، روی Next کلیک کنید.

برای اطلاعات بیشتر در مورد افزودن SDK های Firebase به پروژه‌های Unity، به گزینه‌های نصب اضافی Unity مراجعه کنید.

۴. Crashlytics را در پروژه Unity خود تنظیم کنید

برای استفاده از Crashlytics در پروژه‌های Unity، باید چند مرحله راه‌اندازی دیگر انجام دهید. البته، باید SDK را مقداردهی اولیه کنید. همچنین، باید نمادهای خود را آپلود کنید تا بتوانید stacktraces نمادین را در کنسول Firebase مشاهده کنید، و باید یک crash آزمایشی را اجباری کنید تا مطمئن شوید Firebase رویدادهای crash شما را دریافت می‌کند.

مقداردهی اولیه Crashlytics SDK

  1. در Assets/Hamster/Scripts/MainGame.cs ، دستورات using زیر را اضافه کنید:
    using Firebase.Crashlytics;
    using Firebase.Extensions;
    
    ماژول اول به شما امکان می‌دهد از متدهای Crashlytics SDK استفاده کنید و ماژول دوم شامل برخی افزونه‌ها برای API وظایف C# است. بدون استفاده از هر دو دستور using ، کد زیر کار نخواهد کرد.
  2. همچنان که در MainGame.cs هستید، با فراخوانی InitializeFirebaseAndStartGame() مقداردهی اولیه Firebase را به متد Start() ‎ موجود اضافه کنید:
    void Start()
    {
      Screen.SetResolution(Screen.width / 2, Screen.height / 2, true);
      InitializeFirebaseAndStartGame();
    }
    
  3. و دوباره، در MainGame.cs ، InitializeFirebaseAndStartGame() را پیدا کنید، یک متغیر app تعریف کنید و سپس پیاده‌سازی متد را به صورت زیر بازنویسی کنید:
    public Firebase.FirebaseApp app = null;
    
    // Begins the firebase initialization process and afterwards, opens the main menu.
    private void InitializeFirebaseAndStartGame()
    {
      Firebase.FirebaseApp.CheckAndFixDependenciesAsync()
      .ContinueWithOnMainThread(
        previousTask => 
        {
          var dependencyStatus = previousTask.Result;
          if (dependencyStatus == Firebase.DependencyStatus.Available) {
            // Create and hold a reference to your FirebaseApp,
            app = Firebase.FirebaseApp.DefaultInstance;
            // Set the recommended Crashlytics uncaught exception behavior.
            Crashlytics.ReportUncaughtExceptionsAsFatal = true;
            InitializeCommonDataAndStartGame();
          } else {
            UnityEngine.Debug.LogError(
              $"Could not resolve all Firebase dependencies: {dependencyStatus}\n" +
              "Firebase Unity SDK is not safe to use here");
          }
        });
    }
    

قرار دادن منطق مقداردهی اولیه در اینجا، از تعامل بازیکن قبل از مقداردهی اولیه وابستگی‌های Firebase جلوگیری می‌کند.

مزایا و اثرات گزارش استثنائات مدیریت نشده به عنوان موارد مهلک در بخش سوالات متداول Crashlytics مورد بحث قرار گرفته است.

پروژه خود را بسازید و نمادها را آپلود کنید

مراحل ساخت و آپلود نمادها برای برنامه‌های iOS و اندروید متفاوت است.

iOS+ (پلتفرم اپل)

  1. از پنجره تنظیمات ساخت (Build Settings )، پروژه خود را به فضای کاری Xcode اکسپورت کنید.
  2. اپلیکیشن خود را بسازید.
    برای پلتفرم‌های اپل، افزونه‌ی Firebase Unity Editor به طور خودکار پروژه‌ی Xcode شما را طوری پیکربندی می‌کند که برای هر ساخت، یک فایل نماد سازگار با Crashlytics تولید و در سرورهای Firebase آپلود کند. این اطلاعات نمادها برای مشاهده‌ی ردپاهای پشته نمادین در داشبورد Crashlytics مورد نیاز است.

اندروید

  1. (فقط در طول راه‌اندازی اولیه، نه برای هر نسخه) نسخه خود را راه‌اندازی کنید:
    1. یک پوشه جدید به نام Builds در ریشه دایرکتوری پروژه خود (یعنی به عنوان یک پوشه خواهر و برادر برای دایرکتوری Assets خود) ایجاد کنید، و سپس یک زیرپوشه به نام Android ایجاد کنید.
    2. در مسیر File > Build Settings > Player Settings > Configuration ، مقدار Scripting Backend را روی IL2CPP تنظیم کنید.
      • IL2CPP عموماً باعث می‌شود که buildها کوچک‌تر و عملکرد بهتری داشته باشند.
      • IL2CPP همچنین تنها گزینه موجود در iOS است و انتخاب آن در اینجا به دو پلتفرم اجازه می‌دهد تا برابری بهتری داشته باشند و تفاوت‌های اشکال‌زدایی بین این دو (اگر تصمیم به ساخت هر دو دارید) ساده‌تر شود.
  2. برنامه خود را بسازید. در File > Build Settings ، موارد زیر را تکمیل کنید:
    1. مطمئن شوید که گزینه‌ی Create symbols.zip تیک خورده باشد (یا اگر منوی کشویی نمایش داده شد، Debugging را انتخاب کنید).
    2. فایل APK خود را مستقیماً از ویرایشگر Unity در زیرپوشه Builds/Android که تازه ساخته‌اید، بسازید.
  3. پس از اتمام ساخت، باید یک فایل نماد سازگار با Crashlytics ایجاد کرده و آن را در سرورهای Firebase بارگذاری کنید. این اطلاعات نمادها برای مشاهده ردیابی‌های پشته نمادین برای خرابی‌های کتابخانه بومی در داشبورد Crashlytics مورد نیاز است.

    با اجرای دستور Firebase CLI زیر، این فایل نمادها را ایجاد و آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
    • FIREBASE_APP_ID : شناسه برنامه اندروید Firebase شما (نه نام بسته شما). این مقدار را در فایل google-services.json که قبلاً دانلود کرده‌اید، پیدا کنید. این مقدار mobilesdk_app_id است.
      مثالی از شناسه برنامه اندروید فایربیس: 1:567383003300:android:17104a2ced0c9b9b
    • PATH/TO/SYMBOLS : مسیر فایل نماد فشرده‌شده‌ای که پس از اتمام ساخت، در دایرکتوری Builds/Android ایجاد شده است (برای مثال: Builds/Android/myapp-1.0-v100.symbols.zip ).

برای اتمام راه‌اندازی، یک کرش آزمایشی را اعمال کنید

برای تکمیل راه‌اندازی Crashlytics و مشاهده داده‌های اولیه در داشبورد Crashlytics کنسول Firebase، باید یک crash آزمایشی را اجباری کنید.

  1. در صحنه اصلی (MainGameScene)، شیء بازی GameObject در ویرایشگر سلسله مراتب (Hierarchy) پیدا کنید، اسکریپت زیر را به آن اضافه کنید و سپس صحنه را ذخیره کنید. این اسکریپت چند ثانیه پس از اجرای برنامه، باعث خرابی آزمایشی (test crash) می‌شود.
    using System;
    using UnityEngine;
    
    public class CrashlyticsTester : MonoBehaviour {
        // Update is called once per frame
        void Update()
        {
            // Tests your Crashlytics implementation by
            // throwing an exception every 60 frames.
            // You should see reports in the Firebase console
            // a few minutes after running your app with this method.
            if(Time.frameCount >0 && (Time.frameCount%60) == 0)
            {
                throw new System.Exception("Test exception; please ignore");
            }
        }
    }
    
  2. برنامه خود را بسازید و پس از اتمام ساخت، اطلاعات نماد را بارگذاری کنید.
    • iOS : افزونه Firebase Unity Editor به طور خودکار پروژه Xcode شما را برای آپلود فایل نماد پیکربندی می‌کند.
    • اندروید : دستور crashlytics:symbols:upload در Firebase CLI را اجرا کنید تا فایل نماد شما آپلود شود.
  3. برنامه خود را اجرا کنید. پس از اجرای برنامه، گزارش دستگاه را مشاهده کنید و منتظر بمانید تا استثنا از CrashlyticsTester فعال شود.
    • iOS : مشاهده گزارش‌ها در پنل پایین Xcode.
    • اندروید : با اجرای دستور زیر در ترمینال، گزارش‌ها را مشاهده کنید: adb logcat .
  4. برای مشاهده‌ی این استثنا به داشبورد Crashlytics مراجعه کنید! آن را در جدول Issues در پایین داشبورد مشاهده خواهید کرد. بعداً در codelab، در مورد نحوه‌ی بررسی این گزارش‌ها اطلاعات بیشتری کسب خواهید کرد.
  5. پس از تأیید آپلود رویداد در Crashlytics، GameObject EmptyObject که آن را به آن پیوست کرده‌اید را انتخاب کنید، فقط مؤلفه CrashlyticsTester را حذف کنید و سپس صحنه را ذخیره کنید تا به حالت اولیه خود بازگردد.

۵. منوی اشکال‌زدایی (Debug Menu) را فعال و بررسی کنید

تا اینجا، شما Crashlytics را به پروژه Unity خود اضافه کرده‌اید، تنظیمات را تمام کرده‌اید و تأیید کرده‌اید که Crashlytics SDK در حال آپلود رویدادها به Firebase است. اکنون منویی در پروژه Unity خود ایجاد خواهید کرد که نحوه استفاده از قابلیت‌های پیشرفته‌تر Crashlytics را در بازی شما نشان می‌دهد. پروژه Level Up with Firebase Unity از قبل یک منوی اشکال‌زدایی پنهان دارد که آن را قابل مشاهده خواهید کرد و قابلیت‌ها را برای آن خواهید نوشت.

منوی اشکال‌زدایی را فعال کنید

دکمه دسترسی به منوی اشکال‌زدایی (Debug Menu) در پروژه Unity شما وجود دارد، اما در حال حاضر فعال نیست. برای دسترسی به آن، باید دکمه را از پیش‌ساخته MainMenu فعال کنید:

  1. در ویرایشگر یونیتی، پیش‌ساخته‌ای با نام MainMenu را باز کنید. ۴۱۴۸۵۳۸cbe9f36c5.png
  2. در سلسله مراتب prefab، زیر-شیء غیرفعال با نام DebugMenuButton را پیدا کنید و سپس آن را انتخاب کنید. ۸۱۶f۸f۹۳۶۶۲۸۰f۶c.png
  3. با علامت زدن کادر موجود در گوشه بالا سمت چپ فیلد متنی حاوی DebugMenuButton ، دکمه DebugMenuButton فعال کنید. 8a8089d2b4886da2.png
  4. پیش‌ساخته را ذخیره کنید.
  5. بازی را یا در ویرایشگر یا روی دستگاه خود اجرا کنید. اکنون باید منو قابل دسترسی باشد.

پیش‌نمایش و درک بدنه‌های متد برای منوی اشکال‌زدایی

بعداً در این آزمایشگاه کد، بدنه‌های متد را برای برخی از متدهای از پیش پیکربندی‌شده‌ی Crashlytics برای اشکال‌زدایی خواهید نوشت. با این حال، در پروژه‌ی Level Up with Firebase Unity، متدها در DebugMenu.cs تعریف و فراخوانی می‌شوند.

اگرچه برخی از این روش‌ها هم متدهای Crashlytics را فراخوانی می‌کنند و هم خطا تولید می‌کنند، اما توانایی Crashlytics در تشخیص این خطاها به فراخوانی اولیه آن متدها بستگی ندارد. بلکه گزارش‌های خرابی تولید شده از تشخیص خودکار خطاها با اطلاعات اضافه شده توسط این متدها بهبود می‌یابند.

DebugMenu.cs را باز کنید و سپس متدهای زیر را پیدا کنید:

روش‌های تولید و حاشیه‌نویسی مشکلات Crashlytics:

  • CrashNow
  • LogNonfatalError
  • LogStringsAndCrashNow
  • SetAndOverwriteCustomKeyThenCrash
  • SetLogsAndKeysBeforeANR

روش‌های ثبت رویدادهای تحلیلی برای کمک به اشکال‌زدایی:

  • LogProgressEventWithStringLiterals
  • LogIntScoreWithBuiltInEventAndParams

در مراحل بعدی این آزمایشگاه کد، شما این روش‌ها را پیاده‌سازی خواهید کرد و یاد خواهید گرفت که چگونه به رسیدگی به موقعیت‌های خاصی که ممکن است در توسعه بازی رخ دهند، کمک می‌کنند.

۶. اطمینان از تحویل گزارش‌های خرابی در حین توسعه

قبل از اینکه شروع به پیاده‌سازی این روش‌های اشکال‌زدایی کنید و ببینید که چگونه بر گزارش‌های خرابی تأثیر می‌گذارند، مطمئن شوید که نحوه گزارش رویدادها به Crashlytics را درک کرده‌اید.

برای پروژه‌های Unity، رویدادهای کرش و استثنا در بازی شما بلافاصله روی دیسک نوشته می‌شوند. برای استثناهای Uncaught که بازی شما را کرش نمی‌کنند (به عنوان مثال، استثناهای C# Uncaught در منطق بازی)، می‌توانید Crashlytics SDK را وادار کنید که آنها را به عنوان رویدادهای مهلک گزارش دهد، با تنظیم ویژگی Crashlytics.ReportUncaughtExceptionsAsFatal به true در جایی که Crashlytics را در پروژه Unity خود مقداردهی اولیه می‌کنید. این رویدادها به صورت بلادرنگ و بدون نیاز به راه‌اندازی مجدد بازی توسط کاربر نهایی به Crashlytics گزارش می‌شوند. توجه داشته باشید که کرش‌های بومی همیشه به عنوان رویدادهای مهلک گزارش می‌شوند و هنگامی که کاربر نهایی بازی را مجدداً راه‌اندازی می‌کند، ارسال می‌شوند.

علاوه بر این، از تفاوت‌های کوچک اما مهم زیر بین نحوه ارسال اطلاعات Crashlytics به Firebase توسط محیط‌های مختلف زمان اجرا آگاه باشید:

شبیه‌ساز iOS:

  • اطلاعات Crashlytics فقط و فقط در صورتی گزارش می‌شود که Xcode را از شبیه‌ساز جدا کنید. اگر Xcode متصل باشد، خطاهای بالادستی را دریافت کرده و از تحویل اطلاعات جلوگیری می‌کند.

دستگاه‌های فیزیکی موبایل (اندروید و iOS):

  • مخصوص اندروید: گزارش‌های ANR فقط در اندروید ۱۱+ گزارش می‌شوند. گزارش‌های ANR و رویدادهای غیرمهم در اجرای بعدی ارائه می‌شوند.

ویرایشگر یونیتی:

کرش کردن بازی خود را با لمس یک دکمه در CrashNow() آزمایش کنید

پس از تنظیم Crashlytics در بازی شما، Crashlytics SDK به طور خودکار کرش‌ها و استثنائات ناشناخته را ثبت کرده و آنها را برای تجزیه و تحلیل در Firebase آپلود می‌کند. و گزارش‌ها در داشبورد Crashlytics در کنسول Firebase نمایش داده می‌شوند.

  1. برای نشان دادن اینکه این واقعاً خودکار است: DebugMenu.cs را باز کنید و سپس متد CrashNow() را به صورت زیر بازنویسی کنید:
    void CrashNow()
    {
        TestCrash();
    }
    
  2. اپلیکیشن خود را بسازید.
  3. (فقط اندروید) نمادهای خود را با اجرای دستور Firebase CLI زیر آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. روی دکمه‌ی Crash Now ضربه بزنید و به مرحله‌ی بعدی این آزمایشگاه کد بروید تا نحوه‌ی مشاهده و تفسیر گزارش خرابی را بیاموزید.

۷. گزارش‌های مشکل (issue reports) را در کنسول فایربیس (Firebase) درک کنید

وقتی صحبت از مشاهده گزارش‌های خرابی می‌شود، باید کمی بیشتر در مورد نحوه استفاده حداکثری از آنها بدانید. هر یک از روش‌هایی که می‌نویسید نحوه اضافه کردن انواع مختلف اطلاعات به گزارش‌های Crashlytics را نشان می‌دهد.

  1. روی دکمه‌ی Crash Now ضربه بزنید و سپس برنامه را مجدداً راه‌اندازی کنید.
  2. به داشبورد Crashlytics بروید. به پایین صفحه بروید تا به جدول مشکلات (Issues) در پایین داشبورد برسید، جایی که Crashlytics رویدادهایی را که همگی علت ریشه‌ای یکسانی دارند، در قالب «مشکلات» گروه‌بندی می‌کند.
  3. روی مشکل جدیدی که در جدول مشکلات (Iss) فهرست شده است کلیک کنید. انجام این کار خلاصه‌ای از رویدادهای مربوط به هر رویداد ارسال شده به Firebase را نمایش می‌دهد.

    شما باید چیزی شبیه به تصویر زیر را ببینید. توجه کنید که چگونه خلاصه رویداد، به طور برجسته، رد پشته فراخوانی که منجر به خرابی شده است را نشان می‌دهد. 40c96abe7f90c3aa.png

فراداده‌های اضافی

یکی دیگر از تب‌های مفید، تب Unity Metadata است. این بخش شما را در مورد ویژگی‌های دستگاهی که رویداد روی آن رخ داده است، از جمله ویژگی‌های فیزیکی، مدل/مشخصات CPU و انواع معیارهای GPU، مطلع می‌کند.

در اینجا مثالی آورده شده است که اطلاعات موجود در این برگه ممکن است مفید باشد:
تصور کنید بازی شما برای رسیدن به ظاهری خاص، از سایه‌زن‌ها (shaders) به شدت استفاده می‌کند، اما همه گوشی‌ها پردازنده‌های گرافیکی (GPU) ندارند که قادر به رندر این ویژگی باشند. اطلاعات موجود در تب Unity Metadata می‌تواند به شما ایده بهتری بدهد که برنامه شما هنگام تصمیم‌گیری در مورد اینکه کدام ویژگی‌ها را به طور خودکار در دسترس قرار دهد یا به طور کامل غیرفعال کند، باید چه سخت‌افزاری را آزمایش کند.

اگرچه ممکن است به دلیل تنوع گسترده دستگاه‌های اندرویدی، هیچ اشکال یا خرابی روی دستگاه شما رخ ندهد، اما این به درک بهتر «نقاط داغ» دستگاه‌های مخاطبان شما کمک می‌کند.

41d8d7feaa87454d.png

۸. پرتاب، گرفتن و ثبت یک استثنا

اغلب اوقات، به عنوان یک توسعه‌دهنده، حتی اگر کد شما به درستی یک استثنای زمان اجرا را دریافت و مدیریت کند، خوب است که توجه داشته باشید که این استثنا رخ داده است و تحت چه شرایطی. Crashlytics.LogException می‌تواند دقیقاً برای همین منظور استفاده شود - ارسال یک رویداد استثنا به Firebase تا بتوانید مشکل را در کنسول Firebase بیشتر اشکال‌زدایی کنید.

  1. در Assets/Hamster/Scripts/States/DebugMenu.cs ، کد زیر را به دستورات using اضافه کنید:
    // Import Firebase
    using Firebase.Crashlytics;
    
  2. همچنان در DebugMenu.cs ، تابع LogNonfatalError() را به صورت زیر بازنویسی کنید:
    void LogNonfatalError()
    {
        try
        {
            throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}");
        }
        catch(System.Exception exception)
        {
            Crashlytics.LogException(exception);
        }
    }
    
  3. اپلیکیشن خود را بسازید.
  4. (فقط اندروید) نمادهای خود را با اجرای دستور Firebase CLI زیر آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  5. روی دکمه‌ی «ثبت خطاهای غیرمهلک» ضربه بزنید و سپس برنامه را مجدداً راه‌اندازی کنید.
  6. به داشبورد Crashlytics بروید، و باید چیزی شبیه به آنچه در آخرین مرحله از این آزمایشگاه کد دیدید، ببینید.
  7. اما این بار، فیلتر نوع رویداد را به خطاهای غیرمهلک محدود کنید تا فقط خطاهای غیرمهلک، مانند خطایی که همین الان ثبت کردید، را مشاهده کنید.
    a39ea8d9944cbbd9.png

۹. برای درک بهتر جریان اجرای برنامه، رشته‌ها را در Crashlytics ثبت کنید

آیا تا به حال سعی کرده‌اید بفهمید که چرا یک خط کد که از مسیرهای مختلف، صدها یا حتی هزاران بار در هر جلسه فراخوانی می‌شود، می‌تواند ناگهان یک استثنا یا خرابی ایجاد کند؟ اگرچه ممکن است خوب باشد که کد را در یک IDE بررسی کنید و مقادیر را با دقت بیشتری بررسی کنید، اما اگر این اتفاق فقط برای درصد بسیار کمی از کاربران شما رخ دهد، چه؟ حتی بدتر از آن، اگر نتوانید این خرابی را تکرار کنید، مهم نیست چه کاری انجام می‌دهید؟

در موقعیت‌هایی مانند این، داشتن کمی پیش‌زمینه می‌تواند تفاوت بزرگی ایجاد کند. با Crashlytics.Log ، شما می‌توانید پیش‌زمینه مورد نیاز خود را بنویسید. این پیام‌ها را به عنوان نشانه‌هایی برای خودتان در آینده در مورد آنچه ممکن است اتفاق بیفتد، در نظر بگیرید.

اگرچه می‌توان از لاگ‌ها به روش‌های بی‌شماری استفاده کرد، اما معمولاً برای ثبت موقعیت‌هایی که ترتیب و/یا عدم وجود تماس‌ها یک بخش حیاتی از اطلاعات است، مفیدترین هستند.

  1. در Assets/Hamster/Scripts/States/DebugMenu.cs ، تابع LogStringsAndCrashNow() را به صورت زیر بازنویسی کنید:
    void LogStringsAndCrashNow()
    {
        Crashlytics.Log($"This is the first of two descriptive strings in {nameof(LogStringsAndCrashNow)}");
        const bool RUN_OPTIONAL_PATH = false;
        if(RUN_OPTIONAL_PATH)
        {
            Crashlytics.Log(" As it stands, this log should not appear in your records because it will never be called.");
        }
        else
        {
            Crashlytics.Log(" A log that will simply inform you which path of logic was taken. Akin to print debugging.");
        }
        Crashlytics.Log($"This is the second of two descriptive strings in {nameof(LogStringsAndCrashNow)}");
        TestCrash();
    }
    
  2. اپلیکیشن خود را بسازید.
  3. (فقط اندروید) نمادهای خود را با اجرای دستور Firebase CLI زیر آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. روی دکمه‌ی Log Strings and Crash Now ضربه بزنید و سپس برنامه را مجدداً راه‌اندازی کنید.
  5. به داشبورد Crashlytics برگردید و روی جدیدترین مشکل فهرست‌شده در جدول مشکلات کلیک کنید. دوباره باید چیزی شبیه به مشکلات قبلی ببینید.
    7aabe103b8589cc7.png
  6. با این حال، اگر روی برگه Logs در خلاصه رویداد کلیک کنید، نمایی مانند این خواهید داشت:
    4e27aa407b7571cf.png

۱۰. نوشتن و بازنویسی یک کلید سفارشی

فرض کنید می‌خواهید خرابی مربوط به متغیرهایی که روی تعداد کمی از مقادیر یا پیکربندی‌ها تنظیم شده‌اند را بهتر درک کنید. شاید خوب باشد که بتوانید بر اساس ترکیبی از متغیرها و مقادیر ممکنی که در هر زمان معین به آنها نگاه می‌کنید، فیلتر کنید.

علاوه بر ثبت رشته‌های دلخواه، Crashlytics نوع دیگری از اشکال‌زدایی را ارائه می‌دهد که در آن دانستن وضعیت دقیق برنامه هنگام خرابی مفید است: کلیدهای سفارشی.

اینها جفت‌های کلید-مقدار هستند که می‌توانید برای یک جلسه تنظیم کنید. برخلاف گزارش‌ها که انباشته می‌شوند و صرفاً افزایشی هستند، کلیدها را می‌توان بازنویسی کرد تا فقط آخرین وضعیت یک متغیر یا شرط را منعکس کنند.

این کلیدها علاوه بر اینکه می‌توانند آخرین وضعیت ثبت‌شده برنامه شما را ثبت کنند، می‌توانند به عنوان فیلترهای قدرتمندی برای مشکلات Crashlytics مورد استفاده قرار گیرند.

  1. در Assets/Hamster/Scripts/States/DebugMenu.cs ، تابع SetAndOverwriteCustomKeyThenCrash() به صورت زیر بازنویسی کنید:
    void SetAndOverwriteCustomKeyThenCrash()
    {
        const string CURRENT_TIME_KEY = "Current Time";
        System.TimeSpan currentTime = System.DateTime.Now.TimeOfDay;
        Crashlytics.SetCustomKey(
            CURRENT_TIME_KEY,
            DayDivision.GetPartOfDay(currentTime).ToString() // Values must be strings
            );
    
        // Time Passes
        currentTime += DayDivision.DURATION_THAT_ENSURES_PHASE_CHANGE;
    
        Crashlytics.SetCustomKey(
            CURRENT_TIME_KEY,
            DayDivision.GetPartOfDay(currentTime).ToString()
            );
        TestCrash();
    }
    
  2. اپلیکیشن خود را بسازید.
  3. (فقط اندروید) نمادهای خود را با اجرای دستور Firebase CLI زیر آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. روی دکمه‌ی «تنظیم کلید سفارشی و کرش» ضربه بزنید و سپس برنامه را مجدداً راه‌اندازی کنید.
  5. به داشبورد Crashlytics برگردید و روی جدیدترین مشکل فهرست‌شده در جدول مشکلات کلیک کنید. دوباره باید چیزی شبیه به مشکلات قبلی ببینید.
  6. اما این بار، روی تب Keys در خلاصه رویداد کلیک کنید تا بتوانید مقدار کلیدها از جمله Current Time را مشاهده کنید:
    7dbe1eb00566af98.png

چرا باید به جای لاگ‌های سفارشی از کلیدهای سفارشی استفاده کنید؟

  • لاگ‌ها در ذخیره داده‌های ترتیبی خوب هستند، اما اگر فقط جدیدترین مقدار را می‌خواهید، کلیدهای سفارشی بهتر هستند.
  • در کنسول فایربیس، می‌توانید به راحتی مشکلات را بر اساس مقادیر کلیدها در کادر جستجوی جدول مشکلات فیلتر کنید.

مشابه لاگ‌ها، کلیدهای سفارشی نیز محدودیت دارند. Crashlytics حداکثر از ۶۴ جفت کلید-مقدار پشتیبانی می‌کند. پس از رسیدن به این آستانه، مقادیر اضافی ذخیره نمی‌شوند. هر جفت کلید-مقدار می‌تواند تا ۱ کیلوبایت حجم داشته باشد.

۱۱. (فقط اندروید) استفاده از کلیدها و گزارش‌های سفارشی برای درک و تشخیص ANR

یکی از دشوارترین دسته از مشکلات برای اشکال‌زدایی توسعه‌دهندگان اندروید، خطای عدم پاسخگویی برنامه (ANR) است. ANRها زمانی رخ می‌دهند که یک برنامه بیش از 5 ثانیه به ورودی پاسخ نمی‌دهد. اگر این اتفاق بیفتد، به این معنی است که برنامه یا متوقف شده یا بسیار کند عمل می‌کند. یک کادر محاوره‌ای به کاربران نشان داده می‌شود و آنها می‌توانند انتخاب کنند که آیا "منتظر" باشند یا "برنامه را ببندند".

ANRها یک تجربه کاربری بد هستند و (همانطور که در لینک ANR بالا ذکر شد) می‌توانند بر قابلیت کشف برنامه شما در فروشگاه Google Play تأثیر بگذارند. به دلیل پیچیدگی آنها، و به این دلیل که اغلب توسط کد چند رشته‌ای با رفتار بسیار متفاوت در مدل‌های مختلف تلفن ایجاد می‌شوند، تولید مجدد ANRها هنگام اشکال‌زدایی اغلب بسیار دشوار است، اگر تقریباً غیرممکن نباشد. به همین دلیل، رویکرد تحلیلی و قیاسی به آنها معمولاً بهترین رویکرد است.

در این روش، ما از ترکیبی از Crashlytics.LogException ، Crashlytics.Log و Crashlytics.SetCustomKey برای تکمیل ثبت خودکار مشکلات و ارائه اطلاعات بیشتر استفاده خواهیم کرد.

  1. در Assets/Hamster/Scripts/States/DebugMenu.cs ، تابع SetLogsAndKeysBeforeANR() به صورت زیر بازنویسی کنید:
    void SetLogsAndKeysBeforeANR()
    {
        System.Action<string,long> WaitAndRecord =
        (string methodName, long targetCallLength)=>
        {
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            const string CURRENT_FUNCTION = "Current Async Function";
    
            // Initialize key and start timing
            Crashlytics.SetCustomKey(CURRENT_FUNCTION, methodName);
            stopWatch.Start();
    
            // The actual (simulated) work being timed.
            BusyWaitSimulator.WaitOnSimulatedBlockingWork(targetCallLength);
    
            // Stop timing
            stopWatch.Stop();
    
            if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.EXTREME_DURATION_MILLIS)
            {
              Crashlytics.Log($"'{methodName}' is long enough to cause an ANR.");
            }
            else if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.SEVERE_DURATION_MILLIS)
            {
              Crashlytics.Log($"'{methodName}' is long enough it may cause an ANR");
            }
        };
    
        WaitAndRecord("DoSafeWork",1000L);
        WaitAndRecord("DoSevereWork",BusyWaitSimulator.SEVERE_DURATION_MILLIS);
        WaitAndRecord("DoExtremeWork",2*BusyWaitSimulator.EXTREME_DURATION_MILLIS);
    }
    
  2. اپلیکیشن خود را بسازید.
  3. با اجرای دستور Firebase CLI زیر، نمادهای خود را آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. روی دکمه‌ای با عنوان Set Logs And Keys → ANR ضربه بزنید و سپس برنامه را مجدداً راه‌اندازی کنید.
  5. به داشبورد Crashlytics برگردید و سپس روی مشکل جدید در جدول Issues کلیک کنید تا خلاصه رویداد را مشاهده کنید. اگر تماس به درستی انجام شده باشد، باید چیزی شبیه به این را ببینید:
    876c3cff7037bd07.png

    همانطور که می‌بینید، فایربیس، انتظار شلوغ روی نخ را به عنوان دلیل اصلی ایجاد ANR توسط برنامه شما مشخص کرد.
  6. اگر به گزارش‌های موجود در برگه «گزارش‌ها» در خلاصه رویداد نگاه کنید، خواهید دید که آخرین روشی که به عنوان کامل ثبت شده است، DoSevereWork است.
    5a4bec1cf06f6984.png

    در مقابل، آخرین متدی که به عنوان شروع ذکر شده است، DoExtremeWork است که نشان می‌دهد ANR در طول این متد رخ داده و بازی قبل از اینکه بتواند DoExtremeWork ثبت کند، بسته شده است.

    89d86d5f598ecf3a.png

چرا این کار را انجام دهیم؟

  • بازتولید ANRها فوق‌العاده دشوار است، بنابراین توانایی کسب اطلاعات غنی در مورد ناحیه کد و معیارها برای یافتن آن به صورت قیاسی فوق‌العاده مهم است.
  • با اطلاعات ذخیره شده در کلیدهای سفارشی، اکنون می‌دانید کدام رشته ناهمگام (async thread) بیشترین زمان اجرا را داشته و کدام یک در معرض خطر تحریک ANRها بوده‌اند. این نوع داده‌های منطقی و عددی مرتبط به شما نشان می‌دهند که بهینه‌سازی در کدام قسمت از کد شما ضروری‌تر است.

۱۲. ترکیب رویدادهای تحلیلی برای غنی‌سازی بیشتر گزارش‌ها

متدهای زیر نیز از منوی اشکال‌زدایی (Debug Menu) قابل فراخوانی هستند، اما به جای اینکه خودشان مشکل ایجاد کنند، از گوگل آنالیتیکس به عنوان منبع دیگری از اطلاعات برای درک بهتر عملکرد بازی شما استفاده می‌کنند.

برخلاف سایر متدهایی که در این آزمایشگاه کد نوشته‌اید، باید از این متدها در ترکیب با متدهای دیگر استفاده کنید. قبل از اجرای یکی از متدهای دیگر، این متدها را (با فشردن دکمه‌ی مربوط به آنها در منوی اشکال‌زدایی) به هر ترتیب دلخواهی که می‌خواهید فراخوانی کنید. سپس، هنگامی که اطلاعات مربوط به مشکل خاص Crashlytics را بررسی می‌کنید، یک گزارش مرتب از رویدادهای Analytics را مشاهده خواهید کرد. این داده‌ها می‌توانند در یک بازی برای درک بهتر ترکیبی از جریان برنامه یا ورودی کاربر، بسته به نحوه‌ی ابزاربندی برنامه‌ی شما، مورد استفاده قرار گیرند.

  1. در Assets/Hamster/Scripts/States/DebugMenu.cs ، پیاده‌سازی‌های موجود متدهای زیر را بازنویسی کنید:
    public void LogProgressEventWithStringLiterals()
    {
          Firebase.Analytics.FirebaseAnalytics.LogEvent("progress", "percent", 0.4f);
    }
    
    public void LogIntScoreWithBuiltInEventAndParams()
    {
          Firebase.Analytics.FirebaseAnalytics
            .LogEvent(
              Firebase.Analytics.FirebaseAnalytics.EventPostScore,
              Firebase.Analytics.FirebaseAnalytics.ParameterScore,
              42
            );
    }
    
  2. بازی خود را بسازید و مستقر کنید، و سپس وارد منوی اشکال‌زدایی (Debug Menu) شوید.
  3. (فقط اندروید) نمادهای خود را با اجرای دستور Firebase CLI زیر آپلود کنید:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. برای فراخوانی توابع فوق، حداقل یکی از دکمه‌های زیر را یک یا چند بار فشار دهید:
    • رویداد رشته‌ای را ثبت کنید
    • رویداد بین المللی ورود
  5. دکمه‌ی «خراب کردن» را فشار دهید.
  6. بازی خود را مجدداً راه اندازی کنید تا رویداد خرابی در Firebase آپلود شود.
  7. وقتی توالی‌های دلخواه مختلفی از رویدادهای Analytics را ثبت می‌کنید و سپس از بازی خود می‌خواهید رویدادی ایجاد کند که Crashlytics از آن گزارش تهیه می‌کند (همانطور که همین الان این کار را کردید)، این رویدادها به برگه Logs در خلاصه رویدادهای Crashlytics به شکل زیر اضافه می‌شوند:
    d3b16d78f76bfb04.png

۱۳. به جلو رفتن

و با این کار، شما باید مبنای نظری بهتری برای تکمیل گزارش‌های خرابی خودکار خود داشته باشید. این اطلاعات جدید به شما امکان می‌دهد از وضعیت فعلی، سوابق رویدادهای گذشته و رویدادهای موجود در گوگل آنالیتیکس برای تجزیه و تحلیل بهتر توالی رویدادها و منطقی که منجر به نتیجه آن شده است، استفاده کنید.

اگر برنامه شما اندروید ۱۱ (سطح API 30) یا بالاتر را هدف قرار می‌دهد، گنجاندن GWP-ASan را در نظر بگیرید، یک ویژگی تخصیص‌دهنده حافظه بومی که برای اشکال‌زدایی از کارافتادگی‌های ناشی از خطاهای حافظه بومی مانند خطاهای use-after-free و heap-buffer-overflow مفید است. برای بهره‌مندی از این ویژگی اشکال‌زدایی، GWP-ASan را به صراحت فعال کنید .

مراحل بعدی

به بخش «سازگاری بازی یونیتی با Remote Config» در codelab بروید، جایی که در مورد استفاده از Remote Config و تست A/B در یونیتی یاد خواهید گرفت.