Funktionen zur Aufzeichnung der Ladezeit hinzufügen

Es ist aus zwei Gründen wichtig, aufzuzeichnen, wann in Ihrem Spiel Ladevorgänge ausgeführt werden:

  1. So vermeiden Sie, dass Ihre Daten zur Frame-Zeit während des Ladens verunreinigt werden.
  2. Ladezeiten analysieren, um herauszufinden, wann und wo sie länger als akzeptabel sind.

Ein Ladevorgang kann mit Metadaten verknüpft sein:

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

Alle Felder, die für Ihre Anforderungen nicht relevant sind, können null sein.

Ein Ladevorgang kann auch eine zugehörige Anmerkung haben. Sie können sie auf dieselbe Weise wie Anmerkungen zur Frame-Zeit definieren, indem Sie ein oder mehrere Felder in der Annotation-Nachricht verwenden.

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

Mit dieser Funktion wird die Aufzeichnung eines Ladezeitereignisses gestartet, das mit den angegebenen Metadaten und der Annotation verknüpft ist. Außerdem wird ein Result<ulong>.value ausgefüllt, das in der Funktion StopRecordingLoadingTime() verwendet werden kann.

ErrorCode StopRecordingLoadingTime(ulong handle);

Mit dieser Funktion wird die Aufzeichnung eines Ereignisses beendet, die zuvor mit StartRecordingLoadingTime() gestartet wurde. Das Ereignis wird beim nächsten Sitzungs-Flush hochgeladen.

Gruppenfunktionen werden geladen

In Ihrem Spiel können Sie mehrere Ladeereignisse für einen einzelnen Ladezeitraum aufzeichnen, der für den Nutzer sichtbar ist. Beispiele sind das Laden von Dateien, das Laden von Szenen, die Dekomprimierung und die Shader-Kompilierung.

Es ist wichtig, den Android Performance Tuner darüber zu informieren, dass Ladevorgänge Teil einer solchen Gruppe sind, damit er bessere Statistiken liefern kann. Dazu müssen Sie die Ladeereignisse mit den folgenden Start- und Stoppfunktionen in Klammern setzen.

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

Mit dieser Funktion wird eine Ladegruppe gestartet, die den angegebenen Metadaten und Anmerkungen zugeordnet ist, und ein Result<ulong>.value wird ausgefüllt, das in der Funktion StopLoadingGroup() verwendet werden soll. Die Metadaten und die Anmerkung werden derzeit nicht vom Play-Backend verwendet. Nur die Anmerkung kann auf null festgelegt werden. Alle nachfolgenden Ladeereignisse werden mit einer eindeutigen Gruppen-ID getaggt.

ErrorCode StopLoadingGroup(ulong handle);

Mit dieser Funktion wird eine Ladegruppe beendet, die zuvor mit StartLoadingGroup() gestartet wurde. Nachfolgende Ladevorgänge haben erst dann wieder eine Gruppen-ID, wenn StartLoadingGroup() noch einmal aufgerufen wird.

Abbildung 1. Beispiel für die Ladegruppe

Beispiele

Hier sind einige Beispiele dafür, wie Sie Funktionen für die Ladezeit in Ihr Spiel einfügen können.

Ereignisse zum Laden von Dateien

Das folgende Codebeispiel zeigt, wie Sie das Laden von Dateien in Ihrem Spiel aufzeichnen.

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

Ereignisse zum Laden von Szenen

Das folgende Codebeispiel zeigt, wie Sie das Laden von Szenen in Ihrem Spiel aufzeichnen.

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

Gruppenfunktionen werden geladen

Das folgende Codebeispiel zeigt, wie Sie Ihrem Spiel Funktionen für Ladegruppen hinzufügen.

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