למרות שלוגיקת המשחק העיקרית ב-Unity כתובה ב-C# (מקומפלת עם IL2CPP), גרסאות build של Android כוללות קוד בייט משמעותי של Java ו-Kotlin (classes.dex) כדי לטפל באירועים במחזור החיים של UnityPlayerActivity, ב-Google Play Services, בחיוב, במודעות ובערכות SDK חברתיות.
הפעלת R8, הכלי שמוגדר כברירת מחדל לצמצום קוד ולאופטימיזציה ב-Android Gradle Plugin (AGP), מסירה מחלקות ושיטות שלא בשימוש ומבצעת אופטימיזציה של בייטקוד. כך לא רק מקטינים את נפח ההורדה של האפליקציה, אלא גם את הזיכרון שבשימוש בזמן הריצה של דפי DEX שממופים בזיכרון (mmap) ואת התקורה של תהליך Java בסיסי, וכך מפחיתים את העומס על הזיכרון הפיזי ואת הסגירות של מנגנון הסגירה של אפליקציות במצב של זיכרון נמוך (LMK). מערכת Google Play עוקבת גם אחרי רמות האופטימיזציה של קובצי ה-DEX במשחק באמצעות המדד אופטימיזציה של קוד DEX בתפקוד האפליקציה.
פעולת ברירת המחדל ותמיכה בגרסאות של Unity
ב-Unity, כיווץ הקוד מושבת כברירת מחדל (false) גם בגרסאות build להפצה וגם בגרסאות build לניפוי באגים כשיוצרים פרויקט חדש.
Unity הציגה לראשונה את R8 כמתג אופציונלי ב-Unity 2020.1.0f1. החל מגרסה Unity 2022.2.0f1 (והיסב בגרסאות מוקדמות יותר ל-Unity 2021.3.41f1 LTS), Unity שדרגה את ה-toolchain המצורף ל-AGP 7.1.2 ואילך, הסירה את התמיכה ב-ProGuard מדור קודם, ומריצה את R8 באופן בלעדי בכל פעם שההקטנה מופעלת.
| גרסת Unity | AGP בחבילה | ברירת המחדל של הגרסה | תמיכה ב-R8 וההגדרות הנדרשות |
|---|---|---|---|
| 2019.4 LTS וגרסאות קודמות | גרסאות קודמות ל-3.4 | מושבת (false) |
לא נתמך (רק ProGuard מדור קודם). |
| 2020.1.0f1 עד 2021.3.40f1 | 3.4 עד 4.0 | מושבת (false) |
אופציונלי (ברירת המחדל היא ProGuard). מפעילים את האפשרויות Minify > Release (הקטנה > גרסה) ו-Use R8 (שימוש ב-R8). |
| 2021.3.41f1 ואילך (2021 LTS) | 7.1 ומעלה | מושבת (false) |
R8 בלבד. מפעילים את האפשרות Minify > Release (הקטנה > גרסה) כדי להריץ את R8 באופן אוטומטי. |
| 2022.2.0f1 עד Unity 6 ואילך | 7.1 עד 8.x | מושבת (false) |
R8 בלבד. מפעילים את האפשרות Minify > Release (הקטנה > גרסה) כדי להריץ את R8 באופן אוטומטי. |
הפעלת R8 בהגדרות הנגן
כדי להפעיל את כיווץ הקוד והאופטימיזציה של R8 בגרסאות build להפצה:
- ב-Unity Editor, פותחים את Edit > Project Settings (עריכה > הגדרות הפרויקט) ובוחרים באפשרות Player (נגן).
- בוחרים בכרטיסייה Android ומרחיבים את הקטע Publishing Settings (הגדרות פרסום) > Build (גרסה).
- בקטע Minify, מגדירים את האפשרויות לגרסת Unity:
- Unity 2021.3.41f1 ואילך ו-2022.2.0f1 ואילך: בוחרים באפשרות Release (גרסה). Unity מפעילה את R8 באופן אוטומטי במהלך המשימה
minifyReleaseWithR8של Gradle. - Unity 2020.1.0f1 עד 2021.3.40f1: בוחרים גם באפשרות Release וגם באפשרות Use R8.
- Unity 2021.3.41f1 ואילך ו-2022.2.0f1 ואילך: בוחרים באפשרות Release (גרסה). Unity מפעילה את R8 באופן אוטומטי במהלך המשימה
אם אתם משתמשים בסקריפטים של C# Editor כדי ליצור אוטומציה של גרסאות build, אתם צריכים להגדיר את המאפיינים האלה דרך PlayerSettings.Android:
using UnityEditor;
public static class AndroidBuildConfig
{
public static void EnableR8ForRelease()
{
PlayerSettings.Android.minifyRelease = true;
// Required only in Unity 2020.1.0f1 to 2021.3.40f1 and 2022.1 or earlier
// (In Unity 2021.3.41f1+ and 2022.2+, R8 is always used when minification is enabled)
#if !UNITY_2022_2_OR_NEWER
PlayerSettings.Android.minifyWithR8 = true;
#endif
}
}
הוספת כללי שמירה ל-JNI ולרפלקציה
למחלקות ולשיטות של Java שמופעלות באופן דינמי מסקריפטים של C# באמצעות AndroidJavaClass או AndroidJavaObject אין אתרי קריאה סטטיים של Java. בלי כללי שמירה מפורשים, יכול להיות ש-R8 יחשיב את המחלקות האלה כלא בשימוש ויסיר אותן או ישנה את השם שלהן.
כדי לשמור על גשרי Java בהתאמה אישית:
- בקטע הגדרות הפרויקט > Player > Android > Publishing Settings > Build, מפעילים את האפשרות Custom Proguard File.
- פותחים את קובץ ה-
Assets/Plugins/Android/proguard-user.txtשנוצר. - מוסיפים כללי
-keepלמחלקות שהגישה אליהן מתבצעת דרך JNI או שנדרשות על ידי פלאגינים של צד שלישי:
# Keep custom Java classes invoked from C# using JNI bridges
-keep class com.example.yourgame.** { *; }
# Keep callback interfaces passed between C# and Java
-keep interface com.example.yourgame.IPluginCallback { *; }
פתרון בעיות נפוצות
בקטע הזה מוסבר איך לפתור בעיות נפוצות שקשורות ל-build ולזמן ריצה כשמשתמשים ב-R8 ב-Unity.
Missing classes detected while running R8 שגיאות ב-build
בגרסאות של Unity שמשתמשות ב-AGP מגרסה 7.0 ואילך (2021.3.41f1+ ו-2022.2+), R8 אוכף בדיקות מחמירות של מחלקות חסרות. אם ה-build נכשל עם השגיאה הזו, צריך לבדוק את קובץ missing_rules.txt שנוצר בספריית הפלט של ה-build (בקטע Library/Bee/Android/Prj/.../build/outputs/mapping/release/missing_rules.txt או Temp/gradleOut/...) ולהוסיף את יחסי התלות או הכללים הנדרשים ל-proguard-user.txt. מידע נוסף על כתיבת כללי שמירה זמין במאמר התאמה אישית של הקוד שרוצים לשמור.
תאימות של מצב מלא של R8 עם פלאגינים של צד שלישי
ב-AGP 8.0 ואילך (Unity 6+), מצב מלא של R8 מופעל כברירת מחדל כדי לבצע אופטימיזציות אגרסיביות יותר. אם פלאגין מדור קודם של Android נכשל בזמן הריצה בגלל בעיות ב-reflection, צריך לעדכן את כללי ProGuard של הפלאגין או להחזיר את R8 למצב תאימות:
- בקטע Publishing Settings > Build (הגדרות פרסום > גרסה), מפעילים את האפשרות Custom Gradle Properties Template (תבנית מותאמת אישית של מאפייני Gradle).
- פותחים את
Assets/Plugins/Android/gradleTemplate.propertiesומוסיפים את המאפיין הבא:
android.enableR8.fullMode=false