[Desarrollo del juego] [Unity] Capítulo de descarga del paquete de activos (4) Verifique la reanudación del punto de interrupción y comience a descargar el paquete AB

Tabla de contenido

Directorio del marco de empaquetado y carga de recursos.

texto

Antes de descargar el paquete AB, verifique si la descarga del paquete AB se ha interrumpido, como si el usuario canceló el programa, se congeló, etc.

Como se explicó anteriormente, al descargar el paquete AB, primero se descargará a una carpeta temporal y, una vez que todas las descargas se realicen correctamente, se cortarán en el directorio sandbox de persistDataPath.

Mirando hacia atrás en el mecanismo de selección anterior, qué paquetes AB se pueden agregar a la lista de descargas, no hay un juicio sobre el directorio de descarga temporal.

Si los datos del paquete AB se agregan a la lista deben pasar por los siguientes filtros:

  1. Determine si el paquete AB existe en el directorio de zona de pruebas persistente de DataPath. Si existe, demuestra que se ha descargado antes y no es necesario agregarlo a la lista de descargas.

  1. Determine si el paquete AB existe en el directorio StreamingAsset. Si existe, prueba que el paquete AB ya está en el cuerpo del paquete cuando se empaqueta y no es necesario agregarlo a la lista de descargas.

  1. Si el tipo de descarga del paquete AB es una descarga dentro del juego o una descarga mientras se juega, entonces no es necesario descargarlo cuando el juego inicia la actualización en caliente y no es necesario agregarlo a la lista de descargas.

El código para verificar si existe en el directorio de descarga temporal es el siguiente

private IEnumerator CheckTempFileComplete(List<PatchElement> list, bool isPostCheck)
{
    PatchEventDispatcher.SendCheckDownloadedFileMd5();
    var sw = new Stopwatch();
    sw.Start();
    var buf = new byte[10240];
    this.totalDownloadSizeKB = 0;
    this.currentDownloadSizeKB = 0;
    this.currentDownloadCount = 0;
    using (var md5 = System.Security.Cryptography.MD5.Create())
    {
        foreach (var ele in list)
        {
            this.totalDownloadSizeKB += ele.SizeKB;
            string savePath = AssetPathHelper.MakeDownloadTempPath(ele.Name);
            if (!File.Exists(savePath))
            {
                //下载后的检查需要抛出异常,下载前的检查跳过不存在文件
                if (isPostCheck)
                {
                    PatchHelper.Log(ELogLevel.Error, $"[checking md5] file is not existed: {ele.Name}");
                    failedOnCheckDownload = true;
                    yield break;
                }
                else
                {
                    continue;
                }
            }
            
            using (var fs = new FileStream(savePath, FileMode.Open, FileAccess.Read))
            {
                int byteRead;
                md5.Initialize();
                while ((byteRead = fs.Read(buf, 0, buf.Length)) > 0)
                {
                    md5.TransformBlock(buf, 0, byteRead, null, 0);
                    if (sw.ElapsedMilliseconds > 250)
                    {
                        yield return null;
                        sw.Restart();
                    }
                }
                md5.TransformFinalBlock(buf, 0, 0);
                fs.Close();
                string localMd5 = BitConverter.ToString(md5.Hash).Replace("-", "");
                if (string.Equals(ele.MD5, localMd5, StringComparison.OrdinalIgnoreCase))
                {
                    //MotionLog.Log(ELogLevel.Log, StringFormat.Format("skip download existed file: {0}", savePath));
                    ele.SkipDownload = true;
                    this.currentDownloadSizeKB += ele.SizeKB;
                    this.currentDownloadCount++;
                }
                else if (isPostCheck)
                {
                    PatchHelper.Log(ELogLevel.Error, $"Web file md5 verification error : {ele.Name}");
                    PatchHelper.Log(ELogLevel.Error, $"local md5 is : {localMd5}");
                    PatchHelper.Log(ELogLevel.Error, $"md5 in manifest is : {ele.MD5}");
                    PatchEventDispatcher.SendWebFileMD5VerifyFailedMsg(ele.Name);
                    failedOnCheckDownload = true;
                    File.Delete(savePath);
                    yield break;
                }
            }
        }
    }
}

La función del valor booleano isPostCheck es si se trata de una detección secundaria, ignórelo primero

Sigue el proceso

  1. Verifique si el paquete AB existe en la carpeta temporal, omítalo si no existe

  1. Si ya existe, cree el MD5 del archivo de descarga temporal y compárelo con el MD5 en la lista de descargas.

  1. Si la comparación MD5 es consistente, marque los datos del paquete AB como SkipDownload y marque la longitud de los datos descargados para mostrarlos en la interfaz de usuario.

El código actual de nuestro proyecto ha sido cambiado y no entiendo por qué necesitamos usar md5.TransformBlock.

El siguiente es un conjunto de códigos para generar códigos MD5. Cargue el archivo y MD5CryptoServiceProvider generará un hash basado en la secuencia cargada.

readonly MD5CryptoServiceProvider _provider = new MD5CryptoServiceProvider();
public static string StreamMD5()
{
    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        byte[] hashBytes = _provider.ComputeHash(stream);
        return ToString(hashBytes);
    }
}
private static string ToString(byte[] hashBytes)
{
    var sb = new StringBuilder();
    foreach (var t in hashBytes)
    sb.Append(t.ToString("x2"));
    return sb.ToString();
}

Primero, debemos determinar si el archivo existe en el directorio de descarga temporal. Si no, nuestro proyecto

private IEnumerator Download()
{
    // 计算下载文件的总大小
    totalDownloadCount = _patcher.DownloadList.Count;
    if (totalDownloadCount == 0)
    {
        _patcher.SwitchNext();
        yield break;
    }
    //先检查一遍temp目录有没有下载完的, 计算这次实际需要下载的个数和size
    yield return CheckTempFileComplete(_patcher.DownloadList, false);

    // 开始下载列表里的所有资源
    PatchHelper.Log(ELogLevel.Log, $"Begine download web files : {totalDownloadCount-currentDownloadCount}");
    PatchEventDispatcher.SendPatchStatesChangeMsg(EPatchStates.DownloadWebFiles);
    var startTime = Time.realtimeSinceStartup;
    var newDownloaded = new List<PatchElement>(_patcher.DownloadList.Count);
    foreach (var element in _patcher.DownloadList)
    {
        if (element.SkipDownload) continue;
        newDownloaded.Add(element);
    }

    if (useMultiRequest)
    {
        yield return DownloadWithMultiTask(newDownloaded);
    }
    else
    {
        yield return DownloadWithSingleTask(newDownloaded);
    }
    if (failedOnDownload)
    {
        yield break;
    }
    MotionLog.Log(ELogLevel.Log, $"<color=#ff0000>Downloading {newDownloaded.Count} files cost {Time.realtimeSinceStartup-startTime} sec.</color>");
    //全部下载完成后把这次新下载的文件再校验一遍,如果有文件失败就退出
    yield return CheckTempFileComplete(newDownloaded, true);
    if (failedOnCheckDownload)
    {
        yield break;
    }
    
    if (_patcher.MiniAndroid)
    {
        var fileCount = _patcher.DownloadList[0].Version; // tricky storing filecount in field [version]
        var zipFileName = _patcher.DownloadList[0].Name;
        yield return DecompressInitPack(zipFileName, fileCount);
    }
    else
    {
        yield return DeployDownloadFiles();
    }

    // 最后清空下载列表
    _patcher.DownloadList.Clear();
    _patcher.SwitchNext();
}

Supongo que te gusta

Origin blog.csdn.net/liuyongjie1992/article/details/131108859
Recomendado
Clasificación