חשוב לתעד מתי המשחק מבצע אירועי טעינה, משתי סיבות:
- כדי למנוע זיהום של נתוני זמן המסגרת במהלך הטעינה.
- כדי לנתח את זמני הטעינה ולראות מתי והיכן זמני הטעינה ארוכים יותר מהזמן המקובל.
לאירוע טעינה יכולים להיות משויכים מטא-נתונים:
public class LoadingTimeMetadata
{
public enum LoadingState
{
Unknown = 0,
/// <summary>
/// The first time the game is run.
/// </summary>
FirstRun = 1,
/// <summary>
/// App is not backgrounded.
/// </summary>
ColdStart = 2,
/// <summary>
/// App is backgrounded.
/// </summary>
WarmStart = 3,
/// <summary>
/// App is backgrounded, least work needed.
/// </summary>
HotStart = 4,
/// <summary>
/// Asset loading between levels.
/// </summary>
InterLevel = 5
}
public LoadingState state;
public enum LoadingSource
{
UnknownSource = 0,
/// <summary>
/// Uncompressing data.
/// </summary>
Memory = 1,
/// <summary>
/// Reading assets from APK bundle.
/// </summary>
Apk = 2,
/// <summary>
/// Reading assets from device storage.
/// </summary>
DeviceStorage = 3,
/// <summary>
/// Reading assets from external storage, e.g. SD card.
/// </summary>
ExternalStorage = 4,
/// <summary>
/// Loading assets from the network.
/// </summary>
Network = 5,
/// <summary>
/// Shader compilation.
/// </summary>
ShaderCompilation = 6,
/// <summary>
/// Time spent between process starting and onCreate.
/// </summary>
PreActivity = 7,
/// <summary>
/// Total time spent between process starting and first render frame.
/// </summary>
FirstTouchToFirstFrame = 8,
/// <summary>
/// Time from start to end of a group of events.
/// </summary>
TotalUserWaitForGroup = 9
}
public LoadingSource source;
/// <summary>
/// 0 = no compression, 100 = max compression
/// </summary>
public int compression_level;
public enum NetworkConnectivity
{
Unknown = 0,
Wifi = 1,
CellularNetwork = 2
}
public NetworkConnectivity network_connectivity;
/// <summary>
/// Bandwidth in bits per second.
/// </summary>
public ulong network_transfer_speed_bps;
/// <summary>
/// Latency in nanoseconds.
/// </summary>
public ulong network_latency_ns;
}
אם יש שדות שלא רלוונטיים לצרכים שלכם, אפשר להזין בהם אפס.
אירוע טעינה יכול לכלול גם הערה משויכת. אפשר להגדיר אותן באותו אופן כמו הערות של זמן מסגרת, באמצעות שדה אחד או יותר בהודעה Annotation
.
Result<ulong> StartRecordingLoadingTime(LoadingTimeMetadata eventMetadata,
TAnnotation
annotation);
הפונקציה הזו מתחילה להקליט אירוע של זמן טעינה שמשויך למטא-נתונים ולהערה שצוינו, וממלאת את הערך Result<ulong>.value
כדי להשתמש בו בפונקציה StopRecordingLoadingTime()
.
ErrorCode StopRecordingLoadingTime(ulong handle);
הפונקציה הזו מפסיקה הקלטה של אירוע שהתחילה קודם על ידי StartRecordingLoadingTime()
. האירוע מועלה בניקוי המטמון של הסשן הבא.
טעינת פונקציות של קבוצות
יכול להיות שבמשחק שלכם מתועדים כמה אירועי טעינה לתקופת טעינה אחת שמוצגת למשתמש. דוגמאות: טעינת קבצים, טעינת סצנות, פתיחת דחיסה והידור של הצללה.
חשוב להודיע לכלי Android Performance Tuner שאירועי טעינה הם חלק מקבוצה כזו, כדי שהכלי יוכל לספק תובנות טובות יותר. כדי לעשות את זה, צריך להוסיף את פונקציות ההתחלה והעצירה הבאות לאירועי הטעינה.
Result<ulong> StartLoadingGroup(LoadingTimeMetadata eventMetadata, TAnnotation
annotation);
הפונקציה הזו מתחילה קבוצת טעינה שמשויכת למטא-נתונים ולביאור שצוינו, וממלאת את Result<ulong>.value
כדי להשתמש בה בפונקציה StopLoadingGroup()
. בשלב הזה, ה-backend של Play לא משתמש במטא-נתונים ובאנוטציה, אבל אפשר להגדיר את האנוטציה לערך null
. כל אירועי הטעינה הבאים מתויגים באמצעות מזהה קבוצה ייחודי.
ErrorCode StopLoadingGroup(ulong handle);
הפונקציה הזו מפסיקה קבוצת טעינה שהופעלה קודם על ידי StartLoadingGroup()
.
לאירועי טעינה הבאים לא יהיה מזהה קבוצה עד שיתבצע קריאה חוזרת ל-StartLoadingGroup()
.
איור 1. דוגמה לקבוצת הטעינה.
דוגמאות
הנה כמה דוגמאות לאופן שבו אפשר להוסיף פונקציות של זמן טעינה למשחק.
אירועים של טעינת קבצים
בדוגמת הקוד הבאה אפשר לראות איך לתעד אירועים של טעינת קבצים במשחק.
public RawImage image;
IEnumerator LoadImageFromStreamingAssets(string imageName)
{
string imagePath = "file://" + Path.Combine(Application.streamingAssetsPath, imageName);
using (var r = UnityWebRequestTexture.GetTexture(imagePath))
{
LoadingTimeMetadata fileLoadingMetadata = new LoadingTimeMetadata()
{
state = LoadingTimeMetadata.LoadingState.InterLevel,
source = LoadingTimeMetadata.LoadingSource.DeviceStorage,
// Fields are zero by default but they could be set as follows
compression_level = 0,
network_connectivity = 0,
network_transfer_speed_bps = 0,
network_latency_ns = 0
};
Annotation annotation = new Annotation()
{
Scene = Scene.MagicalForest
};
// Start recording loading time.
Result<ulong> result = performanceTuner.StartRecordingLoadingTime(fileLoadingMetadata, annotation);
yield return r.SendWebRequest();
// Stop recording loading time.
performanceTuner.StopRecordingLoadingTime(result.value);
if (r.isNetworkError || r.isHttpError)
{
Debug.Log(r.error);
}
else
{
Texture2D tex = DownloadHandlerTexture.GetContent(r);
image.texture = tex;
}
}
}
אירועים של טעינת סצנה
בדוגמת הקוד הבאה אפשר לראות איך לתעד אירועים של טעינת סצנות במשחק.
IEnumerator LoadScene(int sceneIndex)
{
LoadingTimeMetadata metadata = new LoadingTimeMetadata()
{state = LoadingTimeMetadata.LoadingState.InterLevel};
Annotation annotation = new Annotation() {Scene = (Scene) (sceneIndex + 1)};
Result<ulong> result = performanceTuner.StartRecordingLoadingTime(metadata, annotation);
AsyncOperation asyncSceneLoad = SceneManager.LoadSceneAsync(sceneIndex, LoadSceneMode.Single);
while (!asyncSceneLoad.isDone)
{
yield return null;
}
performanceTuner.StopRecordingLoadingTime(result.value);
}
טעינת פונקציות של קבוצות
בדוגמת הקוד הבאה אפשר לראות איך מוסיפים פונקציות של קבוצת טעינה למשחק.
IEnumerator LoadImages()
{
LoadingTimeMetadata groupMetadata = new LoadingTimeMetadata()
{
state = LoadingTimeMetadata.LoadingState.InterLevel,
source = LoadingTimeMetadata.LoadingSource.DeviceStorage,
};
Result<ulong> result = performanceTuner.StartLoadingGroup(groupMetadata, null);
yield return StartCoroutine(LoadImageFromStreamingAssets("image1.jpeg"));
yield return StartCoroutine(LoadImageFromStreamingAssets("image2.jpeg"));
yield return StartCoroutine(LoadImageFromStreamingAssets("image3.jpeg"));
yield return StartCoroutine(LoadImageFromStreamingAssets("image4.jpeg"));
var stopErrorCode = performanceTuner.StopLoadingGroup(0);
}