Dodaj funkcje rejestrowania czasu wczytywania

Pamiętaj, że rejestrowanie zdarzeń wczytywania gry jest ważne z 2 powodów:

  1. Aby uniknąć zanieczyszczenia danych o czasie renderowania klatek podczas wczytywania.
  2. Analizowanie czasów wczytywania w celu sprawdzenia, kiedy i gdzie czasy wczytywania są dłuższe niż dopuszczalne.

Zdarzenie wczytywania może mieć powiązane metadane:

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;
}

Wartości w polach, które nie mają związku z Twoimi potrzebami, mogą wynosić 0.

Zdarzenie wczytywania może też mieć powiązaną adnotację. Dane możesz zdefiniować w taki sam sposób jak adnotacje o czasie renderowania klatki, używając co najmniej 1 pola w wiadomości Annotation.

Result<ulong> StartRecordingLoadingTime(LoadingTimeMetadata eventMetadata, TAnnotation annotation);

Ta funkcja rozpoczyna rejestrowanie zdarzenia czasu wczytywania powiązanego z danymi metadanymi i adnotacją oraz wypełnia element Result<ulong>.value, który ma być używany w funkcji StopRecordingLoadingTime().

ErrorCode StopRecordingLoadingTime(ulong handle);

Ta funkcja zatrzymuje rejestrowanie zdarzenia rozpoczętego wcześniej przez StartRecordingLoadingTime(). Zdarzenie jest przesyłane przy kolejnym opróżnieniu sesji.

Wczytuję funkcje grupy

W swojej grze możesz zarejestrować kilka zdarzeń wczytywania w 1 okresie wczytywania dla użytkownika. Przykłady obejmują wczytywanie plików, ładowanie scen, dekompresję i kompilację programu do cieniowania.

Ważne jest, aby poinformować narzędzie Android Performance Tuner, że zdarzenia wczytywania należą do takiej grupy. Dzięki temu może ona dostarczać lepsze statystyki. Aby to zrobić, połącz zdarzenia wczytywania z poniższymi funkcjami uruchamiania i zatrzymywania.

Result<ulong> StartLoadingGroup(LoadingTimeMetadata eventMetadata, TAnnotation annotation);

Ta funkcja uruchamia grupę wczytywania powiązaną z danymi metadanymi i adnotacją oraz wypełnia element Result<ulong>.value, który ma być użyty w funkcji StopLoadingGroup(). Metadane i adnotacja nie są obecnie używane przez backend Google Play, ale tylko adnotację można ustawić na null. Wszystkie kolejne zdarzenia wczytywania są tagowane unikalnym identyfikatorem grupy.

ErrorCode StopLoadingGroup(ulong handle);

Ta funkcja zatrzymuje grupę wczytywania, która została wcześniej uruchomiona przez StartLoadingGroup(). Kolejne zdarzenia wczytywania nie będą miały identyfikatora grupy, dopóki nie zostanie ponownie wywołany StartLoadingGroup().

Rysunek 1. Przykład grupy wczytywania.

Przykłady

Oto kilka przykładów dodania do gry funkcji czasu wczytywania.

Zdarzenia wczytywania pliku

Poniższy przykładowy kod pokazuje, jak rejestrować w grze zdarzenia wczytywania pliku.

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;
        }
    }
}

Zdarzenia wczytywania sceny

Poniższy przykładowy kod pokazuje, jak nagrać zdarzenia wczytywania sceny w grze.

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);
}

Wczytuję funkcje grupy

Poniższy przykładowy kod pokazuje, jak dodać do gry funkcje grupy wczytywania.

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);
}