Ajouter des fonctions d'enregistrement du temps de chargement

Il est important d'enregistrer les périodes où votre jeu effectue des chargements pour deux raisons :

  1. Pour éviter de contaminer vos données de temps de rendu pendant les chargements
  2. Pour analyser les temps de chargement et déterminer dans quels cas ils dépassent les limites acceptables

Un événement de chargement peut être associé à différentes métadonnées :

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

Vous pouvez affecter une valeur nulle à tous les champs qui ne sont pas adaptés à vos besoins.

Un événement de chargement peut également être associé à une annotation. Vous pouvez la définir de la même manière que les annotations de temps de rendu, à l'aide d'un ou de plusieurs champs dans le message Annotation.

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

Cette fonction enregistre un événement de temps de chargement associé aux métadonnées et à l'annotation données, puis remplit le paramètre Result<ulong>.value à utiliser dans la fonction StopRecordingLoadingTime().

ErrorCode StopRecordingLoadingTime(ulong handle);

Cette fonction met fin à l'enregistrement d'un événement démarré par StartRecordingLoadingTime(). L'événement est importé lors du vidage provoqué par la session suivante.

Fonctions pour les groupes de chargement

Dans votre jeu, vous pouvez enregistrer plusieurs événements de chargement pour une seule période de chargement visible par l'utilisateur, tels que des événements de chargement de fichiers, de chargement de scènes, de décompression et de compilation de nuanceurs.

Il est important d'informer Android Performance Tuner que les événements de chargement font partie d'un tel groupe afin de permettre à cet outil d'offrir des informations plus précises sur les performances. Pour ce faire, insérez vos événements de chargement entre les fonctions de démarrage et d'arrêt ci-dessous.

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

Cette fonction lance un groupe de chargement associé aux métadonnées et à l'annotation fournies, et renseigne le champ Result<ulong>.value à utiliser dans la fonction StopLoadingGroup(). Les métadonnées et l'annotation ne sont actuellement pas utilisées par le backend Play, mais seule l'annotation peut être définie sur null. Tous les événements de chargement suivants sont associés à un même identifiant de groupe.

ErrorCode StopLoadingGroup(ulong handle);

Cette fonction arrête un groupe de chargement démarré par StartLoadingGroup(). Les événements de chargement ultérieurs n'auront pas d'identifiant de groupe tant que StartLoadingGroup() ne sera pas rappelé.

Figure 1. Exemple de groupe de chargement.

Exemples

Voici quelques exemples illustrant comment ajouter des fonctions de temps de chargement à votre jeu.

Événements de chargement de fichiers

L'exemple de code suivant montre comment enregistrer des événements de chargement de fichiers dans votre jeu.

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

Événements de chargement de scènes

L'exemple de code suivant montre comment enregistrer des événements de chargement de scène dans votre jeu.

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

Fonctions pour les groupes de chargement

L'exemple de code suivant montre comment ajouter des fonctions pour les groupes de chargement à votre jeu.

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