ZoeAppClass/Assets/Scripts/Addressables/JogosAddressableDownloader.cs

176 lines
5.6 KiB
C#

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
/// <summary>
/// Download sob demanda para os recursos configurados em Assets/Jogos.
/// Compatível com Unity 2019.3 e Addressables 1.1.10.
/// </summary>
public static class JogosAddressableDownloader
{
public static string GetLabelFromTag(string tagGame)
{
if (string.IsNullOrEmpty(tagGame))
return string.Empty;
string normalized = tagGame.Replace("\\", "/").Trim('/');
string[] parts = normalized.Split('/');
string gameFolder = parts.Length > 0 ? parts[0] : normalized;
return "jogo_" + gameFolder.ToLowerInvariant();
}
/// <summary>
/// Verifica se a label existe no catálogo.
/// </summary>
public static IEnumerator ValidateLabel(
string gameLabel,
Action<bool> onCompleted,
Action<string> onError = null)
{
if (string.IsNullOrEmpty(gameLabel))
{
if (onCompleted != null) onCompleted(false);
yield break;
}
AsyncOperationHandle<System.Collections.Generic.IList<UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation>> handle =
Addressables.LoadResourceLocationsAsync(gameLabel);
yield return handle;
if (handle.Status == AsyncOperationStatus.Succeeded)
{
bool exists = handle.Result != null && handle.Result.Count > 0;
if (onCompleted != null) onCompleted(exists);
}
else
{
string error = "Erro ao validar a label Addressable: " + gameLabel;
Debug.LogError(error);
if (onError != null) onError(error);
if (onCompleted != null) onCompleted(false);
}
Addressables.Release(handle);
}
/// <summary>
/// Baixa a label apenas se ela existir. Se não existir, continua sem erro.
/// Isso permite jogos que não possuem uma pasta correspondente em Assets/Jogos.
/// </summary>
public static IEnumerator DownloadGameIfExists(
string tagGame,
Action<float> onProgress = null,
Action<string> onStatus = null,
Action onSuccess = null,
Action<string> onError = null)
{
string gameLabel = GetLabelFromTag(tagGame);
bool labelExists = false;
yield return ValidateLabel(
gameLabel,
delegate(bool exists) { labelExists = exists; },
onError
);
if (!labelExists)
{
Debug.Log("Nenhum conteúdo adicional em Assets/Jogos para a label: " + gameLabel);
if (onProgress != null) onProgress(1f);
if (onStatus != null) onStatus("Sem conteúdo adicional para baixar.");
if (onSuccess != null) onSuccess();
yield break;
}
yield return DownloadGame(gameLabel, onProgress, onStatus, onSuccess, onError);
}
public static IEnumerator DownloadGame(
string gameLabel,
Action<float> onProgress = null,
Action<string> onStatus = null,
Action onSuccess = null,
Action<string> onError = null)
{
if (string.IsNullOrEmpty(gameLabel))
{
string error = "A label do jogo está vazia.";
Debug.LogError(error);
if (onError != null) onError(error);
yield break;
}
if (onStatus != null) onStatus("Verificando conteúdo adicional...");
AsyncOperationHandle<long> sizeHandle =
Addressables.GetDownloadSizeAsync(gameLabel);
yield return sizeHandle;
if (sizeHandle.Status != AsyncOperationStatus.Succeeded)
{
string error = "Não foi possível consultar o tamanho da label: " + gameLabel;
Debug.LogError(error);
if (onError != null) onError(error);
Addressables.Release(sizeHandle);
yield break;
}
long downloadSize = sizeHandle.Result;
Addressables.Release(sizeHandle);
if (downloadSize <= 0)
{
if (onProgress != null) onProgress(1f);
if (onStatus != null) onStatus("Conteúdo adicional já está no cache.");
if (onSuccess != null) onSuccess();
yield break;
}
if (onStatus != null)
onStatus("Baixando recursos do jogo: " + FormatBytes(downloadSize));
AsyncOperationHandle downloadHandle =
Addressables.DownloadDependenciesAsync(gameLabel);
while (!downloadHandle.IsDone)
{
if (onProgress != null)
onProgress(downloadHandle.PercentComplete);
yield return null;
}
if (downloadHandle.Status == AsyncOperationStatus.Succeeded)
{
if (onProgress != null) onProgress(1f);
if (onStatus != null) onStatus("Recursos adicionais baixados.");
if (onSuccess != null) onSuccess();
}
else
{
string error = "Erro ao baixar a label: " + gameLabel;
Debug.LogError(error);
if (onError != null) onError(error);
}
Addressables.Release(downloadHandle);
}
public static string FormatBytes(long bytes)
{
const long kb = 1024L;
const long mb = kb * 1024L;
const long gb = mb * 1024L;
if (bytes >= gb) return (bytes / (float)gb).ToString("0.00") + " GB";
if (bytes >= mb) return (bytes / (float)mb).ToString("0.00") + " MB";
if (bytes >= kb) return (bytes / (float)kb).ToString("0.00") + " KB";
return bytes + " bytes";
}
}