ניפוי באגים ומקרי ANR

פתרון ANR במשחק Unity הוא תהליך שיטתי:

איור 1. שלבים לפתרון בעיות ANR במשחקי Unity.

שילוב שירותי דיווח

שירותי דיווח כמו תפקוד האפליקציה,‏ Firebase Crashlytics ו-Backtrace (שותף מאומת של Unity) מספקים רישום שגיאות וניתוח של המשחק שלכם בהיקף נרחב. כדאי לשלב ערכות SDK של שירותי דיווח במשחק בשלב מוקדם במחזור הפיתוח. כדאי לנתח איזה שירות דיווח מתאים הכי טוב לצרכים ולתקציב שלכם.

לשירותי דיווח שונים יש דרכים שונות לתיעוד של ANR. כדאי לכלול שירות דיווח שני כדי להגדיל את הסיכוי לקבל נתונים תקפים שיעזרו לכם לקבל החלטה לגבי תיקון של שגיאות ANR.

שילוב של ערכות SDK לדיווח לא משפיע על ביצועי המשחק או על גודל ה-APK.

ניתוח סמלים

מנתחים את הדוחות משירות הדיווח ובודקים אם עקבות המחסנית הם בפורמט שניתן לקריאה על ידי בני אדם. מידע נוסף זמין במאמר בנושא הוספת סמלים לקובצי קריסה ולשגיאות ANR ב-Android במשחקי Unity.

איור 2. ‫Crashlytics מציג מזהה build וסמלי libil2cpp.so חסרים.

איך בודקים את מזהה הגרסה של הסמל

אם מערכת הדיווח מציגה את מזהה ה-Build החסר אבל סמלי ה-Build עדיין קיימים באחסון של מכונת ה-Build, אפשר לבדוק את מזהה ה-Build של הסמלים ואז להעלות אותם לשירות הדיווח. אחרת, צריך ליצור גרסה חדשה כדי להעלות את קובצי הסמלים.

ב-Windows או ב-macOS:

  1. עוברים לתיקיית הסמלים בהתאם לקצה העורפי של הסקריפטים (ראו פתרון):
    1. משתמשים בפקודה הבאה (ב-Windows, משתמשים ב-Cygwin כדי להפעיל את כלי readelf)
    2. השימוש ב-grep הוא אופציונלי לסינון פלט הטקסט
    3. חיפוש מזהה גרסת build
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

בדיקת קוד המשחק

כאשר דוח קריסות מציג פונקציה בספרייה libil2cpp.so, השגיאה התרחשה בקוד C#, שמומר ל-C++‎. הספרייה libil2cpp.so כוללת לא רק את קוד המשחק שלכם, אלא גם תוספים וחבילות.

שם הקובץ ב-C++ זהה לשם האסמבלי שמוגדר בפרויקט Unity. אחרת, שם הקובץ יהיה שם ברירת המחדל של Assembly-C#. לדוגמה, באיור 3 מוצגת השגיאה בקובץ Game.cpp (מסומן בכחול), שהוא השם שמוגדר בקובץ Assembly Definition. ‫Logger הוא שם המחלקה (מסומן באדום) בסקריפט C#, ואחריו שם הפונקציה (מסומן בירוק). לבסוף, השם המלא שהממיר IL2CPP יצר (מסומן בכתום).

איור 3. בודקים את ה-סטאק ביצוע של פרויקט מ-Backtrace.

כדי לבדוק את קוד המשחק:

  • בודקים את פרויקט C# כדי לזהות קוד חשוד. בדרך כלל, חריגים שלא טופלו ב-C#‎ לא גורמים ל-ANR או לקריסת האפליקציה. למרות זאת, חשוב לוודא שהקוד פועל בצורה תקינה במצבים שונים. בודקים אם הקוד משתמש במודול מנוע של צד שלישי, ומנתחים אם שחרור עדכני גרם לשגיאה. בנוסף, כדאי לבדוק אם עדכנתם לאחרונה את Unity או אם השגיאה מתרחשת רק במכשירים ספציפיים.
  • מייצאים את המשחק כפרויקט Android Studio. עם גישה מלאה לקוד המקור של המשחק ב-C# אחרי ההמרה, תוכלו למצוא את הפונקציה שגורמת ל-ANR. קוד C++ נראה שונה מאוד מקוד C# ‎, ובדרך כלל אין בעיה בהמרת הקוד. אם מצאתם משהו, אתם יכולים לשלוח כרטיס תמיכה ל-Unity.
  • בודקים את קוד המקור של המשחק ומוודאים שכל הלוגיקה שמופעלת ב-callbacks‏ OnApplicationFocus() ו-OnApplicationPause() מנוקה בצורה מתאימה.
    • למנוע Unity יש זמן קצוב לתפוגה להשהיית ההרצה שלו. עומס עבודה מוגזם בקריאות החוזרות האלה יכול לגרום לשגיאת ANR.
    • כדי לשפר את ניתוח הנתונים, אפשר להוסיף יומנים או נתיבי ניווט לחלקים בקוד.
  • כדי לבדוק את הביצועים של המשחק, אפשר להשתמש ב-Unity Profiler. פרופיל האפליקציה יכול לעזור לכם לזהות צווארי בקבוק שגורמים ל-ANR.
  • דרך מצוינת לזהות פעולות קלט/פלט ארוכות ב-thread הראשי היא שימוש במצב קפדני.
  • מנתחים את ההיסטוריה של Android Vitals או של שירות דיווח אחר, ובודקים את גרסאות ההפצה של המשחק שבו השגיאה מתרחשת הכי הרבה. בודקים את קוד המקור בהיסטוריית בקרת הגרסאות ומשווים בין שינויי הקוד בין הגרסאות. אם אתם מוצאים משהו חשוד, נסו כל שינוי או תיקון פוטנציאלי בנפרד.
  • בודקים את היסטוריית הדיווח על מקרי ANR ב-Google Play במכשירים ובגרסאות Android שבהם מתרחשים הכי הרבה מקרי ANR. אם המכשירים או הגרסאות מיושנים, סביר להניח שאפשר להתעלם מהם בבטחה, בתנאי שההתעלמות לא משפיעה על הרווחיות של המשחק. חשוב לבדוק את הנתונים בקפידה, כי קבוצה מסוימת של משתמשים לא תוכל יותר לשחק במשחק שלכם. מידע נוסף זמין במאמר בנושא לוח הבקרה של ההפצה.
  • בודקים את קוד המקור של המשחק כדי לוודא שלא מופעל קוד שעלול לגרום לבעיה. לדוגמה, הפונקציה finish עלולה לגרום נזק אם לא משתמשים בה בצורה נכונה. מידע נוסף על פיתוח ל-Android זמין במדריכים למפתחים ל-Android.
  • אחרי שבודקים את הנתונים ומייצאים את גרסת המשחק ל-Android Studio, עובדים עם קוד C ו-C++, ולכן אפשר לנצל באופן מלא כלים מעבר לפתרונות הסטנדרטיים של Unity, כמו Android Memory Profiler,‏ Android CPU Profiler ו-perfetto.

קוד מנוע Unity

כדי לדעת אם מתרחש ANR בצד של מנוע Unity, בודקים אם מופיעים libUnity.so או libMain.so בפרטי ה-stack trace. אם מצאתם אותם, פועלים לפי השלבים הבאים:

  • קודם כל, כדאי לחפש בערוצי הקהילה (Unity Forums, ‏ Unity Discussions, ‏ Stackoverflow).
  • אם לא מצאתם כלום, דווחו על באג כדי לפתור את הבעיה. כדאי לספק דוח קריסות עם סימבולים כדי שמהנדסי המנוע יוכלו להבין את השגיאה ולפתור אותה בצורה טובה יותר.
  • בודקים אם בגרסה האחרונה של Unity LTS יש שיפורים שקשורים לבעיות שלכם. אם כן, צריך לשדרג את המשחק כדי להשתמש בגרסה הזו. (הפתרון הזה אפשרי רק לחלק מהמפתחים).
  • אם הקוד שלכם משתמש ב-Activity בהתאמה אישית במקום בברירת המחדל, כדאי לבדוק את קוד ה-Java כדי לוודא שהפעילות לא גורמת לבעיות.

SDK של צד שלישי

  • מוודאים שכל הספריות של צד שלישי עדכניות ואין דיווחים על קריסות או על ANR בגרסה העדכנית של Android.
  • כדאי להיכנס לפורומים של Unity כדי לבדוק אם שגיאות מסוימות כבר נפתרו בגרסה מאוחרת יותר, או אם Unity או חבר בקהילה סיפקו פתרון עקיף.
  • כדאי לעיין בדוח ה-ANR של Google Play ולוודא ש-Google לא זיהתה את השגיאה הזו כבר. ‫Google מודעת לכמה מקרי ANR ופועלת באופן אקטיבי כדי לפתור אותם.

ספריית מערכת

בדרך כלל למפתחים אין שליטה בספריות מערכת, אבל הן לא מייצגות אחוז משמעותי של ANR. מעבר ליצירת קשר עם מפתח הספרייה או להוספת יומנים כדי לצמצם את הבעיה, קשה לפתור בעיות ANR בספריית המערכת.

סיבות ליציאה

ApplicationExitInfo הוא Android API להבנת הגורמים לשגיאות ANR. אם המשחק שלכם משתמש ב-Unity 6 ואילך, אתם יכולים לקרוא ל-ApplicationExitInfo ישירות. בגרסאות ישנות יותר של Unity, צריך להטמיע פלאגין משלכם כדי להפעיל שיחות ApplicationExitInfo מ-Unity.

‫Crashlytics משתמש גם ב-ApplicationExitInfo, אבל ההטמעה שלכם מאפשרת לכם שליטה מדויקת יותר וכוללת מידע רלוונטי יותר.