É importante registrar quando seu jogo está realizando eventos de carregamento por dois motivos:
- Para evitar poluir os dados de tempo para a renderização do frame durante o carregamento.
- Para analisar os tempos de carregamento e saber quando e onde eles são mais longos do que o aceitável.
Um evento de carregamento pode ter metadados associados:
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;
}
Todos os campos que não sejam relevantes para suas necessidades podem ser definidos como zero.
Um evento de carregamento também pode ter uma anotação associada. Você pode defini-la
da mesma maneira que as anotações de tempo para a renderização do frame, usando um ou mais campos na mensagem
Annotation
.
Result<ulong> StartRecordingLoadingTime(LoadingTimeMetadata eventMetadata,
TAnnotation
annotation);
Essa função inicia a gravação de um evento de tempo de carregamento associado aos
metadados e anotações fornecidos e preenche um Result<ulong>.value
para ser usado na função
StopRecordingLoadingTime()
.
ErrorCode StopRecordingLoadingTime(ulong handle);
Essa função interrompe a gravação de um evento iniciada anteriormente por
StartRecordingLoadingTime()
. O upload do evento é feito na próxima limpeza de sessão.
Funções dos grupos de carregamento
No seu jogo, você pode registrar vários eventos de carregamento para um único período de carregamento visto pelo usuário. Alguns exemplos incluem carregamento de arquivos, carregamento de cena, descompactação e compilação do sombreador.
É importante informar ao Android Performance Tuner que os eventos de carregamento fazem parte desse grupo para que ele possa oferecer insights melhores. Coloque os eventos de carregamento entre as seguintes funções start e stop para fazer isso.
Result<ulong> StartLoadingGroup(LoadingTimeMetadata eventMetadata, TAnnotation
annotation);
Essa função inicia um grupo de carregamento associado aos metadados e
anotações fornecidos e preenche um Result<ulong>.value
para ser usado na função
StopLoadingGroup()
. No momento, os metadados e a anotação não são
usados pelo back-end do Play, mas apenas a anotação pode ser definida como null
. Todos os eventos de carregamento subsequentes
vão ter uma tag com um ID de grupo exclusivo.
ErrorCode StopLoadingGroup(ulong handle);
Essa função interrompe um grupo de carregamento iniciado anteriormente por StartLoadingGroup()
.
Os eventos de carregamento subsequentes não terão um ID de grupo até que StartLoadingGroup()
seja chamado novamente.
Figura 1. Exemplo de grupo de carregamento.
Exemplos
Veja alguns exemplos de como adicionar funções de tempo de carregamento ao seu jogo.
Eventos de carregamento de arquivos
O exemplo de código a seguir mostra como gravar eventos de carregamento de arquivo no seu jogo.
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;
}
}
}
Eventos de carregamento de cenas
O exemplo de código a seguir mostra como gravar eventos de carregamento de cena no seu jogo.
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);
}
Funções dos grupos de carregamento
O exemplo de código abaixo mostra como adicionar funções dos grupos de carregamento ao seu jogo.
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);
}