סשן משחק איטי הוא סשן שבו חלק משמעותי מהפריימים (לדוגמה, יותר מ-25% מהפריימים) לא עומדים ביעד של זמן הפריים – למשל, 50 אלפיות השנייה לכל פריים (שווה ל-20 FPS) או 34 אלפיות השנייה לכל פריים (שווה ל-30 FPS). מעקב אחר הביצועים של קצב הפריימים וביצוע אופטימיזציה שלהם הם קריטיים, כי פריימים שהושמטו או פריימים עם השהיה משפיעים ישירות על מידת החלקות וההיענות של המשחק בעיני השחקנים.
ב-Android, שיעורי הפריימים בסשן נמדדים באמצעות נתונים מ-SurfaceFlinger על סמך מרווח הזמן בין פריימים שמוצגים במשטחים שבבעלות המשחק (כולל משטחים של ערכת הכלים של OpenGL, Vulkan וממשק המשתמש של Android). אם האפליקציה שלך משתמשת בערכת הכלים לבניית ממשק משתמש שמבוססת על View, שבה החלק של האפליקציה שגלוי למשתמש נמשך מ-Canvas או מההיררכיה של View, כדאי לעיין במאמר בנושא רינדור איטי.
איך מודדים FPS ומזהים פריימים איטיים
הפקודה dumpsys surfaceflinger timestats ב-Android מספקת את קצב הפריימים הממוצע ואת ההיסטוגרמה של התזמון present to present לכל השכבות שעוברות רינדור. הזמן present to present של פריים הוא המרווח בין הפריים הנוכחי לבין הפריים הקודם שמוצג. כך משתמשים בפקודה כדי לאסוף את נתוני ה-FPS של המשחק:
מריצים את הפקודה עם הדגלים
enableו-clearכדי להתחיל ללכוד מידע:adb shell dumpsys SurfaceFlinger --timestats -clear -enableכשמשחקים במשחק מספיק זמן, מריצים שוב את הפקודה עם הדגל
dumpכדי להעביר מידע:adb shell dumpsys SurfaceFlinger --timestats -dumpהמידע שמופיע בקובץ ה-dump כולל את המסגרות הכוללות והיסטוגרמה של presentToPresent לכל השכבות שעברו רינדור על ידי SurfaceFlinger. צריך למצוא את הקטע במשחק באמצעות סינון לפי
layerName:layerName = SurfaceView[com.google.test/com.devrel.MainActivity]@0(BLAST)#132833אפשר לחשב את קצב הפריימים האיטי של הסשן על סמך המידע של כל שכבה.
לדוגמה, אחוז הפריימים האיטיים של 20 FPS = (סכום הערכים מ-54 אלפיות השנייה עד 1,000 אלפיות השנייה) חלקי totalFrames כפול 100
totalFrames = 274 ... presentToPresent histogram is as below: 0ms=0 1ms=0 2ms=0 3ms=0 4ms=0 5ms=0 6ms=0 7ms=0 8ms=0 9ms=0 10ms=0 11ms=0 12ms=0 13ms=0 14ms=0 15ms=0 16ms=1 17ms=0 18ms=0 19ms=0 20ms=0 21ms=0 22ms=0 23ms=0 24ms=0 25ms=0 26ms=0 27ms=0 28ms=0 29ms=0 30ms=0 31ms=0 32ms=0 33ms=269 34ms=0 36ms=0 38ms=0 40ms=0 42ms=0 44ms=0 46ms=0 48ms=0 50ms=1 54ms=0 58ms=0 62ms=0 66ms=0 70ms=1 74ms=0 78ms=0 82ms=0 86ms=0 90ms=0 94ms=0 98ms=0 102ms=0 106ms=0 110ms=0 114ms=0 118ms=0 122ms=0 126ms=0 130ms=0 134ms=0 138ms=0 142ms=0 146ms=0 150ms=0 200ms=0 250ms=0 300ms=0 350ms=0 400ms=0 450ms=0 500ms=0 550ms=0 600ms=0 650ms=0 700ms=0 750ms=0 800ms=0 850ms=0 900ms=0 950ms=0 1000ms=0ה-FPS הממוצע של כל שכבה מוצג גם ב-dump:
... averageFPS = 30.179 ...אחרי איסוף כל המידע, צריך להשבית את timestats באמצעות הדגל
disable:adb shell dumpsys SurfaceFlinger --timestats -disable
סיבות לפריימים איטיים ופתרונות
יכולות להיות הרבה סיבות לכך שפריים יוצג או יעבור רינדור למשך זמן ארוך יותר על המסך מהיעד שהוגדר על ידי המפתח. יכול להיות שהמשחק מוגבל על ידי יחידת העיבוד המרכזית (CPU) או על ידי ה-GPU. או שהמכשיר מתחמם יותר מדי ומפעיל מצב תרמי מוגבל. או שיש חוסר התאמה בין קצב הפריימים של המשחק לבין קצב הרענון של התצוגה במכשיר.
כדי לפתור את הבעיות האלה ולשפר את הביצועים של המשחק, אפשר להשתמש ב-Android Frame Pacing (Swappy), ב-Vulkan וב-ADPF.
מה זה Swappy
Frame Pacing library ל-Android, שנקראת גם Swappy, היא חלק מספריות AGDK. Swappy עוזר למשחקי OpenGL ו-Vulkan להשיג רינדור חלק וקצב פריימים נכון ב-Android.
קצב התקדמות הפריים הוא הסנכרון של הלוגיקה של המשחק ושל לולאת העיבוד שלו עם מערכת המשנה של התצוגה של מערכת ההפעלה ועם חומרת התצוגה הבסיסית. מערכת המשנה של התצוגה ב-Android תוכננה כך שלא יופיעו בה פריטי מידע חזותיים לא רצויים (שנקראים קריעה) שיכולים להופיע כשחומרת התצוגה עוברת למסגרת חדשה באמצע עדכון. כדי למנוע את הארטיפקטים האלה, מערכת המשנה של התצוגה:
- מאגרים באופן פנימי פריימים קודמים
- זיהוי של שליחת פריים באיחור
- חזרה על הצגת פריימים קודמים כשמזוהים פריימים מאוחרים
כך חברת Mir 2 השתמשה ב-Swappy כדי להקטין את שיעור הסשנים האיטיים מ-40% ל-10%
איך משתמשים ב-Swappy בפרויקטים מקוריים
כדי לשלב את ספריית Android Frame Pacing במשחק, אפשר לעיין במדריכים הבאים:
- איך משלבים את Android Frame Pacing במעבד ה-OpenGL
- שילוב של Android Frame Pacing במעבד התצוגה של Vulkan
איך משתמשים ב-Swappy במנוע המשחקים של Unity
Unity שילבה את Android Frame Pacing במנוע שלה. כדי להפעיל את התכונה הזו ב-Unity 2019.2 ואילך, מסמנים את תיבת הסימון 'קצב פריימים אופטימלי' בקטע Project Settings > Player > Settings (הגדרות הפרויקט > המשחק > הגדרות) עבור Android > Resolution and Presentation (Android > רזולוציה והצגה):
אפשרות אחרת היא להפעיל באופן פרוגרמטי את האפשרות 'התאמה אופטימלית של קצב הפריימים' בקוד הלוגיקה כדי לאפשר ל-Unity לחלק את הפריימים באופן שווה, וכך ליצור משחק חלק יותר.
איך משתמשים ב-Swappy במנוע המשחקים Unreal
ב-Unreal מגרסה 4.25 ואילך משולבת ספריית Android Frame Pacing, שהיא חלק מ-Android Game Development Kit. במאמר בנושא התאמת קצב הפריימים בנייד מוסבר איך להפעיל את ספריית התאמת קצב הפריימים של Android ואיך לשלוט בהתאמת קצב הפריימים מקוד C++.
מה זה Vulkan
Vulkan הוא ממשק API מודרני לגרפיקה תלת-ממדית שפועל בפלטפורמות שונות ומיועד לצמצום ההפשטה בין חומרת הגרפיקה של המכשיר לבין המשחק. Vulkan הוא ממשק ה-API הגרפי ברמה נמוכה העיקרי ב-Android, והוא מחליף את OpenGL ES. OpenGL ES עדיין נתמך ב-Android, אבל הוא כבר לא נמצא בפיתוח פעיל של תכונות.
ל-Vulkan יש את היתרונות הבאים לעומת OpenGL ES:
- ארכיטקטורה יעילה יותר עם תקורה נמוכה יותר של המעבד (CPU) במנהל ההתקן של הגרפיקה
- אסטרטגיות אופטימיזציה חדשות לשיפור הביצועים של המעבד
- תכונות גרפיות חדשות שלא זמינות ב-OpenGL ES, כמו ממשקי API ללא קשירה ומעקב אחר קרניים
איך משתמשים ב-Vulkan בפרויקטים מקוריים של Android
בשיעור Codelab בנושא תחילת העבודה עם Vulkan ב-Android מוסבר איך להגדיר את פייפליין העיבוד של Vulkan, ואז לעבד משולש מסתובב עם טקסטורה על המסך. ב-Codelab הזה מוסבר איך לעבד את הגרפיקה של המשחק.
איך משתמשים ב-Vulkan במנוע המשחקים Unity
כדי להפעיל בחירה אוטומטית של מכשירים ב-Unity, פועלים לפי השלבים להגדרת Auto Graphics API.
לחלופין, אפשר להפעיל את Vulkan באופן ידני על ידי השבתת Auto Graphics API והעברת Vulkan למקום הראשון ברשימה Graphics APIs. אם אתם משתמשים ב-Unity בגרסה 2021.1 או בגרסה קודמת, זו הדרך היחידה להשתמש ב-Vulkan.
אפשר להשתמש ב-VkQuality Unity engine plugin כדי לספק המלצות בזמן ההפעלה לגבי ה-API של הגרפיקה שבו המשחק צריך להשתמש במכשירים ספציפיים.
איך משתמשים ב-Vulkan במנוע המשחקים Unreal
כדי להפעיל את ממשק ה-API של Vulkan לגרפיקה, עוברים אל Project Settings > Platforms > Android > Build ובוחרים באפשרות Support Vulkan. כשבוחרים גם באפשרות Support Vulkan וגם באפשרות Support OpenGL ES3.2, Unreal משתמש ב-Vulkan כברירת מחדל. אם המכשיר לא תומך ב-Vulkan, Unreal חוזר ל-OpenGL ES 3.2.
אם אתם משתמשים בתכונות ספציפיות של Vulkan שידוע שהן מתנהגות בצורה לא טובה במכשירים מסוימים, אתם יכולים להתאים אישית את קובץ BaseDeviceProfile.ini כדי להחריג את המכשירים האלה. במאמר התאמה אישית של פרופילי מכשירים ומדרגיות ב-Android מוסבר איך להתאים אישית את BaseDeviceProfile.ini. יכול להיות שמנהלי התקנים חדשים יתקנו בעיות במכשירים שכבר ידועות, לכן חשוב לעדכן את הקובץ BaseDeviceProfile.ini כדי לקבל את כל האופטימיזציות.
מה זה ADPF
Android Dynamic Performance Framework (ADPF) מבצע אופטימיזציה למשחקים על סמך התכונות הדינמיות לניהול טמפרטורה, מעבד ויחידת GPU ב-Android. התכונות מיועדות בעיקר למשחקים, אבל אפשר להשתמש בהן גם באפליקציות אחרות שדורשות ביצועים גבוהים.
ADPF הוא קבוצה של ממשקי API שמאפשרים למשחקים ולאפליקציות עתירות ביצועים ליצור אינטראקציה ישירה יותר עם מערכות החשמל והתרמיות של מכשירי Android. בעזרת ממשקי ה-API האלה, אפשר לעקוב אחרי ההתנהגות הדינמית במערכות Android ולבצע אופטימיזציה של ביצועי המשחק ברמה יציבה שלא גורמת להתחממות יתר של המכשירים.
אלה התכונות העיקריות של ADPF:
- Thermal API: מעקב אחרי מצב הטמפרטורה של המכשיר כדי שהאפליקציה תוכל להתאים באופן יזום את עומס העבודה לפני שהוא יהפוך לבלתי נסבל.
- CPU Performance Hint API: מספק רמזים לשיפור הביצועים שמאפשרים ל-Android לבחור את הגדרות הביצועים הנכונות (למשל, נקודת הפעלה או ליבה של ה-CPU) עבור עומס העבודה.
- Game Mode API ו-Game State API: מאפשרים לבצע אופטימיזציה של המשחק על ידי מתן עדיפות לביצועים או למאפיינים של חיי הסוללה, על סמך ההגדרות של המשתמש וההגדרות הספציפיות של המשחק.
- מצב ביצועים קבוע: הפעלת מצב ביצועים קבוע במכשיר במהלך השוואה בין ביצועים כדי לקבל מדידות שלא משתנות בגלל תזמון דינמי של מעבד מרכזי.
- מצב חיסכון באנרגיה: מציין לסשן שאפשר לתזמן את השרשורים בסשן של רמזים לשיפור הביצועים בצורה בטוחה, כך שתינתן עדיפות לחיסכון באנרגיה על פני ביצועים. זמין ב-Android 15 (רמת API 35).
איך משתמשים ב-ADPF בפרויקטים מקוריים של Android
ב-codelab Integrating Adaptability Features Into Your Native Game (שילוב תכונות של התאמה במשחק מקורי) מוסבר איך לשלב תכונות של ADPF במשחק, עם שלבים שאפשר לפעול לפיהם בקצב שלכם. בסוף ה-codelab, תהיה לכם אפשרות לשלב את התכונות הבאות:
- Thermal API: האזנה לנתוני הטמפרטורה של המכשיר ותגובה לפני שהמכשיר עובר למצב של ויסות תרמי.
- Game Mode API: מאפשר להבין את העדפות האופטימיזציה של השחקנים (למקסם את הביצועים או לשמור על הסוללה) ולבצע התאמות בהתאם.
- Game State API: מאפשר למערכת לדעת מה מצב המשחק (טעינה, הפעלה, ממשק משתמש וכו'), והמערכת יכולה להתאים את המשאבים בהתאם (שיפור קלט/פלט, או CPU, GPU וכו').
- Performance Hint API: מאפשר למערכת לדעת מה מודל ה-threading ועומס העבודה שלכם, כדי שהמערכת תוכל להקצות משאבים בהתאם.
איך משתמשים ב-ADPF במנוע המשחקים של Unity
Unity's Adaptive Performance הוא כלי למפתחי משחקים שרוצים לבצע אופטימיזציה של המשחקים שלהם במכשירים ניידים, במיוחד עבור המערכת האקולוגית המגוונת של Android. התכונה 'ביצועים דינמיים' מאפשרת למשחק להתאים את עצמו לביצועים ולמאפיינים התרמיים של המכשיר בזמן אמת, וכך להבטיח חוויית משחק חלקה ויעילה.
הספק Adaptive Performance Android מנחה אתכם בשלבים להטמעת ADPF ב-Unity.
איך משתמשים ב-ADPF במנוע המשחק Unreal
- הורדת הפלאגין
- מעתיקים את הפלאגין לתיקיית הפלאגינים של הפרויקט
- הפעלת התוסף ADPF Unreal Engine בעורך Unreal
- הפעלה מחדש של Unreal Editor
- בונים ומבשלים את המשחק
התוסף Android Dynamic Performance Framework (ADPF) ל-Unreal Engine מספק ביצועים יציבים ומונע ויסות תרמי. מורידים את הפלאגין מ-GitHub. התוסף הזה משנה תכונות על ידי הגדרת ערכי קונסולה של Unreal.