Exemple #1
0
        private List <BundleInfo> GetDownloadListByAll()
        {
            List <PatchBundle> downloadList = new List <PatchBundle>(1000);

            foreach (var patchBundle in LocalPatchManifest.BundleList)
            {
                // 忽略缓存文件
                if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
                {
                    continue;
                }

                // 忽略APP资源
                // 注意:如果是APP资源并且哈希值相同,则不需要下载
                if (AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
                {
                    if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
                    {
                        continue;
                    }
                }

                downloadList.Add(patchBundle);
            }

            return(ConvertToDownloadList(downloadList));
        }
Exemple #2
0
        private List <BundleInfo> GetDownloadListByPaths(AssetInfo[] assetInfos)
        {
            // 获取资源对象的资源包和所有依赖资源包
            List <PatchBundle> checkList = new List <PatchBundle>();

            foreach (var assetInfo in assetInfos)
            {
                if (assetInfo.IsInvalid)
                {
                    YooLogger.Warning(assetInfo.Error);
                    continue;
                }

                string mainBundleName = LocalPatchManifest.GetBundleName(assetInfo.AssetPath);
                if (LocalPatchManifest.Bundles.TryGetValue(mainBundleName, out PatchBundle mainBundle))
                {
                    if (checkList.Contains(mainBundle) == false)
                    {
                        checkList.Add(mainBundle);
                    }
                }

                string[] dependBundleNames = LocalPatchManifest.GetAllDependencies(assetInfo.AssetPath);
                foreach (var dependBundleName in dependBundleNames)
                {
                    if (LocalPatchManifest.Bundles.TryGetValue(dependBundleName, out PatchBundle dependBundle))
                    {
                        if (checkList.Contains(dependBundle) == false)
                        {
                            checkList.Add(dependBundle);
                        }
                    }
                }
            }

            List <PatchBundle> downloadList = new List <PatchBundle>(1000);

            foreach (var patchBundle in checkList)
            {
                // 忽略缓存文件
                if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
                {
                    continue;
                }

                // 忽略APP资源
                // 注意:如果是APP资源并且哈希值相同,则不需要下载
                if (AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
                {
                    if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
                    {
                        continue;
                    }
                }

                downloadList.Add(patchBundle);
            }

            return(ConvertToDownloadList(downloadList));
        }
Exemple #3
0
        private void VerifyInThread(object infoObj)
        {
            ThreadInfo info = (ThreadInfo)infoObj;

            info.Result = DownloadSystem.CheckContentIntegrity(info.FilePath, info.Bundle.SizeBytes, info.Bundle.CRC);
            _syncContext.Post(VerifyCallback, info);
        }
Exemple #4
0
        private BundleInfo CreateBundleInfo(string bundleName)
        {
            if (LocalPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle patchBundle))
            {
                // 查询沙盒资源
                if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
                {
                    BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromCache);
                    return(bundleInfo);
                }

                // 查询APP资源
                if (AppPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle appPatchBundle))
                {
                    if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
                    {
                        BundleInfo bundleInfo = new BundleInfo(appPatchBundle, BundleInfo.ELoadMode.LoadFromStreaming);
                        return(bundleInfo);
                    }
                }

                // 从服务端下载
                return(ConvertToDownloadInfo(patchBundle));
            }
            else
            {
                throw new Exception("Should never get here !");
            }
        }
Exemple #5
0
        internal static void InternalUpdate()
        {
            // 更新异步操作系统
            OperationSystem.Update();

            // 更新下载管理系统
            DownloadSystem.Update();

            // 更新资源系统
            AssetSystem.Update();
        }
Exemple #6
0
        private void VerifyCallback(object obj)
        {
            ThreadInfo info = (ThreadInfo)obj;

            if (info.Result)
            {
                _verifySuccessCount++;
                DownloadSystem.CacheVerifyFile(info.Bundle.Hash, info.Bundle.BundleName);
            }
            else
            {
                _verifyFailCount++;
                YooLogger.Warning($"Failed to verify file : {info.FilePath}");
                if (File.Exists(info.FilePath))
                {
                    File.Delete(info.FilePath);
                }
            }
            _verifyingList.Remove(info.Bundle);
        }
Exemple #7
0
        private List <BundleInfo> GetDownloadListByTags(string[] tags)
        {
            List <PatchBundle> downloadList = new List <PatchBundle>(1000);

            foreach (var patchBundle in LocalPatchManifest.BundleList)
            {
                // 忽略缓存文件
                if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
                {
                    continue;
                }

                // 忽略APP资源
                // 注意:如果是APP资源并且哈希值相同,则不需要下载
                if (AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
                {
                    if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
                    {
                        continue;
                    }
                }

                // 如果是纯内置资源,则统一下载
                // 注意:可能是新增的或者变化的内置资源
                // 注意:可能是由热更资源转换的内置资源
                if (patchBundle.IsPureBuildin())
                {
                    downloadList.Add(patchBundle);
                }
                else
                {
                    // 查询DLC资源
                    if (patchBundle.HasTag(tags))
                    {
                        downloadList.Add(patchBundle);
                    }
                }
            }

            return(ConvertToDownloadList(downloadList));
        }
Exemple #8
0
        /// <summary>
        /// 获取下载列表
        /// </summary>
        private List <BundleInfo> GetDownloadList()
        {
            List <PatchBundle> downloadList = new List <PatchBundle>(1000);

            foreach (var patchBundle in _remotePatchManifest.BundleList)
            {
                // 忽略缓存文件
                if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
                {
                    continue;
                }

                // 忽略APP资源
                // 注意:如果是APP资源并且哈希值相同,则不需要下载
                if (_impl.AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
                {
                    if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
                    {
                        continue;
                    }
                }

                // 注意:通过比对文件大小做快速的文件校验!
                // 注意:在初始化的时候会去做最终校验!
                string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.Hash);
                if (File.Exists(filePath))
                {
                    long fileSize = FileUtility.GetFileSize(filePath);
                    if (fileSize == patchBundle.SizeBytes)
                    {
                        continue;
                    }
                }

                downloadList.Add(patchBundle);
            }

            return(_impl.ConvertToDownloadList(downloadList));
        }
Exemple #9
0
        private void InitVerifyingCache()
        {
            // 遍历所有文件然后验证并缓存合法文件
            foreach (var patchBundle in _impl.LocalPatchManifest.BundleList)
            {
                // 忽略缓存文件
                if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
                {
                    continue;
                }

                // 忽略APP资源
                // 注意:如果是APP资源并且哈希值相同,则不需要下载
                if (_impl.AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
                {
                    if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
                    {
                        continue;
                    }
                }

                // 查看文件是否存在
                string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.Hash);
                if (File.Exists(filePath) == false)
                {
                    continue;
                }

                _waitingList.Add(patchBundle);
            }

            // 设置同时验证的最大数
            ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
            YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
            _verifyMaxNum     = Math.Min(workerThreads, ioThreads);
            _verifyTotalCount = _waitingList.Count;
        }
Exemple #10
0
        /// <summary>
        /// 异步初始化
        /// </summary>
        public static InitializationOperation InitializeAsync(InitializeParameters parameters)
        {
            if (parameters == null)
            {
                throw new Exception($"YooAsset create parameters is null.");
            }

            if (parameters.LocationServices == null)
            {
                throw new Exception($"{nameof(IBundleServices)} is null.");
            }
            else
            {
                _locationServices = parameters.LocationServices;
            }

#if !UNITY_EDITOR
            if (parameters is EditorSimulateModeParameters)
            {
                throw new Exception($"Editor simulate mode only support unity editor.");
            }
#endif

            // 创建驱动器
            if (_isInitialize == false)
            {
                _isInitialize = true;
                UnityEngine.GameObject driverGo = new UnityEngine.GameObject("[YooAsset]");
                driverGo.AddComponent <YooAssetDriver>();
                UnityEngine.Object.DontDestroyOnLoad(driverGo);
            }
            else
            {
                throw new Exception("YooAsset is initialized yet.");
            }

            // 检测参数范围
            if (parameters.AssetLoadingMaxNumber < 1)
            {
                parameters.AssetLoadingMaxNumber = 1;
                YooLogger.Warning($"{nameof(parameters.AssetLoadingMaxNumber)} minimum value is 1");
            }
            if (parameters.OperationSystemMaxTimeSlice < 30)
            {
                parameters.OperationSystemMaxTimeSlice = 30;
                YooLogger.Warning($"{nameof(parameters.OperationSystemMaxTimeSlice)} minimum value is 30 milliseconds");
            }

            // 鉴定运行模式
            if (parameters is EditorSimulateModeParameters)
            {
                _playMode = EPlayMode.EditorSimulateMode;
            }
            else if (parameters is OfflinePlayModeParameters)
            {
                _playMode = EPlayMode.OfflinePlayMode;
            }
            else if (parameters is HostPlayModeParameters)
            {
                _playMode = EPlayMode.HostPlayMode;
            }
            else
            {
                throw new NotImplementedException();
            }

            // 初始化异步操作系统
            OperationSystem.Initialize(parameters.OperationSystemMaxTimeSlice);

            // 初始化下载系统
            if (_playMode == EPlayMode.HostPlayMode)
            {
#if UNITY_WEBGL
                throw new Exception($"{EPlayMode.HostPlayMode} not supports WebGL platform !");
#else
                var hostPlayModeParameters = parameters as HostPlayModeParameters;
                DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize);
#endif
            }

            // 初始化资源系统
            InitializationOperation initializeOperation;
            if (_playMode == EPlayMode.EditorSimulateMode)
            {
                _editorSimulateModeImpl = new EditorSimulateModeImpl();
                _bundleServices         = _editorSimulateModeImpl;
                AssetSystem.Initialize(true, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices);
                var editorSimulateModeParameters = parameters as EditorSimulateModeParameters;
                initializeOperation = _editorSimulateModeImpl.InitializeAsync(
                    editorSimulateModeParameters.LocationToLower,
                    editorSimulateModeParameters.SimulatePatchManifestPath);
            }
            else if (_playMode == EPlayMode.OfflinePlayMode)
            {
                _offlinePlayModeImpl = new OfflinePlayModeImpl();
                _bundleServices      = _offlinePlayModeImpl;
                AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices);
                initializeOperation = _offlinePlayModeImpl.InitializeAsync(parameters.LocationToLower);
            }
            else if (_playMode == EPlayMode.HostPlayMode)
            {
                _hostPlayModeImpl = new HostPlayModeImpl();
                _bundleServices   = _hostPlayModeImpl;
                AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices);
                var hostPlayModeParameters = parameters as HostPlayModeParameters;
                initializeOperation = _hostPlayModeImpl.InitializeAsync(
                    hostPlayModeParameters.LocationToLower,
                    hostPlayModeParameters.ClearCacheWhenDirty,
                    hostPlayModeParameters.DefaultHostServer,
                    hostPlayModeParameters.FallbackHostServer);
            }
            else
            {
                throw new NotImplementedException();
            }

            // 监听初始化结果
            initializeOperation.Completed += InitializeOperation_Completed;
            return(initializeOperation);
        }
 void OnApplicationQuit()
 {
     DownloadSystem.DestroyAll();
 }
Exemple #12
0
        internal override void Update()
        {
            if (_steps == ESteps.None || _steps == ESteps.Done)
            {
                return;
            }

            if (_steps == ESteps.Check)
            {
                if (_downloadList == null)
                {
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Failed;
                    Error  = "Download list is null.";
                }
                else
                {
                    _steps = ESteps.Loading;
                }
            }

            if (_steps == ESteps.Loading)
            {
                // 检测下载器结果
                _removeList.Clear();
                long downloadBytes = CurrentDownloadBytes;
                foreach (var downloader in _downloaders)
                {
                    downloadBytes += (long)downloader.DownloadedBytes;
                    if (downloader.IsDone() == false)
                    {
                        continue;
                    }

                    BundleInfo bundleInfo = downloader.GetBundleInfo();

                    // 检测是否下载失败
                    if (downloader.HasError())
                    {
                        _removeList.Add(downloader);
                        _loadFailedList.Add(bundleInfo);
                        continue;
                    }

                    // 下载成功
                    _removeList.Add(downloader);
                    CurrentDownloadCount++;
                    CurrentDownloadBytes += bundleInfo.SizeBytes;
                }

                // 移除已经完成的下载器(无论成功或失败)
                foreach (var loader in _removeList)
                {
                    _downloaders.Remove(loader);
                }

                // 如果下载进度发生变化
                if (_lastDownloadBytes != downloadBytes || _lastDownloadCount != CurrentDownloadCount)
                {
                    _lastDownloadBytes = downloadBytes;
                    _lastDownloadCount = CurrentDownloadCount;
                    Progress           = (float)_lastDownloadBytes / TotalDownloadBytes;
                    OnDownloadProgressCallback?.Invoke(TotalDownloadCount, _lastDownloadCount, TotalDownloadBytes, _lastDownloadBytes);
                }

                // 动态创建新的下载器到最大数量限制
                // 注意:如果期间有下载失败的文件,暂停动态创建下载器
                if (_downloadList.Count > 0 && _loadFailedList.Count == 0)
                {
                    if (_isPause)
                    {
                        return;
                    }

                    if (_downloaders.Count < _downloadingMaxNumber)
                    {
                        int index     = _downloadList.Count - 1;
                        var operation = DownloadSystem.BeginDownload(_downloadList[index], _failedTryAgain);
                        _downloaders.Add(operation);
                        _downloadList.RemoveAt(index);
                    }
                }

                // 下载结算
                if (_downloaders.Count == 0)
                {
                    if (_loadFailedList.Count > 0)
                    {
                        string fileName = _loadFailedList[0].BundleName;
                        Error  = $"Failed to download file : {fileName}";
                        _steps = ESteps.Done;
                        Status = EOperationStatus.Failed;
                        OnDownloadFileFailedCallback?.Invoke(fileName);
                        OnDownloadOverCallback?.Invoke(false);
                    }
                    else
                    {
                        // 结算成功
                        _steps = ESteps.Done;
                        Status = EOperationStatus.Succeed;
                        OnDownloadOverCallback?.Invoke(true);
                    }
                }
            }
        }
        internal override void Update()
        {
            if (_steps == ESteps.None || _steps == ESteps.Done)
            {
                return;
            }

            // 1. 准备工作
            if (_steps == ESteps.Prepare)
            {
                if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.None)
                {
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Failed;
                    Error  = $"Bundle info is invalid : {_bundleInfo.BundleName}";
                }
                else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
                {
                    _steps = ESteps.DownloadFromWeb;
                }
                else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
                {
                    _steps = ESteps.DownloadFromApk;
                }
                else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
                {
                    _steps = ESteps.CheckAndCopyFile;
                }
                else
                {
                    throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
                }
            }

            // 2. 从服务器下载
            if (_steps == ESteps.DownloadFromWeb)
            {
                int failedTryAgain = int.MaxValue;
                _downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain);
                _steps      = ESteps.CheckDownloadFromWeb;
            }

            // 3. 检测服务器下载结果
            if (_steps == ESteps.CheckDownloadFromWeb)
            {
                Progress = _downloader.DownloadProgress;
                if (_downloader.IsDone() == false)
                {
                    return;
                }

                if (_downloader.HasError())
                {
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Failed;
                    Error  = _downloader.GetLastError();
                }
                else
                {
                    _steps = ESteps.CheckAndCopyFile;
                }
            }

            // 4. 从APK拷贝文件
            if (_steps == ESteps.DownloadFromApk)
            {
                string downloadURL = PathHelper.ConvertToWWWPath(_bundleInfo.GetStreamingLoadPath());
                _fileRequester = new UnityWebFileRequester();
                _fileRequester.SendRequest(downloadURL, GetCachePath());
                _steps = ESteps.CheckDownloadFromApk;
            }

            // 5. 检测APK拷贝文件结果
            if (_steps == ESteps.CheckDownloadFromApk)
            {
                Progress = _fileRequester.Progress();
                if (_fileRequester.IsDone() == false)
                {
                    return;
                }

                if (_fileRequester.HasError())
                {
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Failed;
                    Error  = _fileRequester.GetError();
                }
                else
                {
                    _steps = ESteps.CheckAndCopyFile;
                }
                _fileRequester.Dispose();
            }

            // 6. 检测并拷贝原生文件
            if (_steps == ESteps.CheckAndCopyFile)
            {
                // 如果不需要保存文件
                if (string.IsNullOrEmpty(CopyPath))
                {
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Succeed;
                    return;
                }

                // 如果原生文件已经存在,则验证其完整性
                if (File.Exists(CopyPath))
                {
                    bool result = DownloadSystem.CheckContentIntegrity(CopyPath, _bundleInfo.SizeBytes, _bundleInfo.CRC);
                    if (result)
                    {
                        _steps = ESteps.Done;
                        Status = EOperationStatus.Succeed;
                        return;
                    }
                    else
                    {
                        File.Delete(CopyPath);
                    }
                }

                try
                {
                    FileUtility.CreateFileDirectory(CopyPath);
                    File.Copy(GetCachePath(), CopyPath, true);
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Succeed;
                }
                catch (System.Exception e)
                {
                    _steps = ESteps.Done;
                    Status = EOperationStatus.Failed;
                    Error  = e.ToString();
                }
            }
        }
Exemple #14
0
            private void ThreadRun()
            {
                long fileTotalSize = _fileSize;

                FileStream      fileStream     = null;
                HttpWebResponse webResponse    = null;
                Stream          responseStream = null;

                try
                {
                    // 创建文件流
                    fileStream = new FileStream(_savePath, FileMode.OpenOrCreate, FileAccess.Write);
                    long fileLength = fileStream.Length;

                    // 创建HTTP下载请求
                    HttpWebRequest webRequest = WebRequest.Create(_url) as HttpWebRequest;
                    webRequest.Timeout         = _timeout * 1000;
                    webRequest.ProtocolVersion = HttpVersion.Version10;
                    if (fileLength > 0)
                    {
                        // 注意:设置远端请求文件的起始位置
                        webRequest.AddRange(fileLength);
                        // 注意:设置本地文件流的起始位置
                        fileStream.Seek(fileLength, SeekOrigin.Begin);
                    }

                    // 读取下载数据并保存到文件
                    webResponse    = webRequest.GetResponse() as HttpWebResponse;
                    responseStream = webResponse.GetResponseStream();
                    byte[] buffer = new byte[BufferSize];
                    while (_running)
                    {
                        int length = responseStream.Read(buffer, 0, buffer.Length);
                        if (length <= 0)
                        {
                            break;
                        }

                        fileStream.Write(buffer, 0, length);

                        // 计算下载进度
                        // 注意:原子操作保证数据安全
                        fileLength += length;
                        float progress = fileLength / fileTotalSize;
                        DownloadProgress = progress;
                        DownloadedBytes  = (ulong)fileLength;
                    }
                }
                catch (Exception e)
                {
                    Error = e.Message;
                }
                finally
                {
                    if (responseStream != null)
                    {
                        responseStream.Close();
                        responseStream.Dispose();
                    }

                    if (webResponse != null)
                    {
                        webResponse.Close();
                        webResponse.Dispose();
                    }

                    if (fileStream != null)
                    {
                        fileStream.Flush();
                        fileStream.Close();
                    }

                    // 验证下载文件完整性
                    if (DownloadedBytes == (ulong)_fileSize)
                    {
                        bool verfiyResult = DownloadSystem.CheckContentIntegrity(_savePath, _fileSize, _fileCRC);
                        if (verfiyResult == false)
                        {
                            Error = $"Verify download content failed : {_fileHash}";
                            if (File.Exists(_savePath))
                            {
                                File.Delete(_savePath);
                            }
                        }
                    }
                    else
                    {
                        Error = $"Download content is incomplete : {_fileHash}";
                    }

                    IsDone = true;
                }
            }
Exemple #15
0
        public override void Update()
        {
            if (_steps == ESteps.None)
            {
                return;
            }
            if (IsDone())
            {
                return;
            }

            if (_steps == ESteps.CreateDownload)
            {
                // 重置变量
                _downloadProgress = 0f;
                _downloadedBytes  = 0;
                _tryAgainTimer    = 0f;

                _requestURL       = GetRequestURL();
                _threadDownloader = new ThreadDownloader();
                _threadDownloader.Run(_requestURL, _bundleInfo.GetCacheLoadPath(), _bundleInfo.Hash, _bundleInfo.CRC, _bundleInfo.SizeBytes, _timeout);
                _steps = ESteps.CheckDownload;
            }

            if (_steps == ESteps.CheckDownload)
            {
                _downloadProgress = _threadDownloader.DownloadProgress;
                _downloadedBytes  = _threadDownloader.DownloadedBytes;
                if (_threadDownloader.IsDone == false)
                {
                    return;
                }

                if (_threadDownloader.HasError())
                {
                    _lastError = _threadDownloader.Error;

                    // 失败后重新尝试
                    if (_failedTryAgain > 0)
                    {
                        ReportWarning();
                        _steps = ESteps.TryAgain;
                    }
                    else
                    {
                        ReportError();
                        _steps = ESteps.Failed;
                    }
                }
                else
                {
                    DownloadSystem.CacheVerifyFile(_bundleInfo.Hash, _bundleInfo.BundleName);
                    _steps = ESteps.Succeed;
                }
            }

            // 重新尝试下载
            if (_steps == ESteps.TryAgain)
            {
                _tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
                if (_tryAgainTimer > 1f)
                {
                    _failedTryAgain--;
                    _steps = ESteps.CreateDownload;
                    YooLogger.Warning($"Try again download : {_requestURL}");
                }
            }
        }
        public override void Update()
        {
            if (_steps == ESteps.None)
            {
                return;
            }
            if (IsDone())
            {
                return;
            }

            // 创建下载器
            if (_steps == ESteps.CreateDownload)
            {
                // 重置变量
                _downloadProgress       = 0f;
                _downloadedBytes        = 0;
                _isAbort                = false;
                _latestDownloadBytes    = 0;
                _latestDownloadRealtime = Time.realtimeSinceStartup;
                _tryAgainTimer          = 0f;

                _requestURL = GetRequestURL();
                _webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
                DownloadHandlerFile handler = new DownloadHandlerFile(_bundleInfo.GetCacheLoadPath());
                handler.removeFileOnAbort   = true;
                _webRequest.downloadHandler = handler;
                _webRequest.disposeDownloadHandlerOnDispose = true;
                _operationHandle = _webRequest.SendWebRequest();
                _steps           = ESteps.CheckDownload;
            }

            // 检测下载结果
            if (_steps == ESteps.CheckDownload)
            {
                _downloadProgress = _webRequest.downloadProgress;
                _downloadedBytes  = _webRequest.downloadedBytes;
                if (_operationHandle.isDone == false)
                {
                    CheckTimeout();
                    return;
                }

                // 检查网络错误
                bool hasError = false;
#if UNITY_2020_3_OR_NEWER
                if (_webRequest.result != UnityWebRequest.Result.Success)
                {
                    hasError   = true;
                    _lastError = _webRequest.error;
                }
#else
                if (_webRequest.isNetworkError || _webRequest.isHttpError)
                {
                    hasError   = true;
                    _lastError = _webRequest.error;
                }
#endif

                // 检查文件完整性
                if (hasError == false)
                {
                    // 注意:如果文件验证失败需要删除文件
                    if (DownloadSystem.CheckContentIntegrity(_bundleInfo) == false)
                    {
                        hasError   = true;
                        _lastError = $"Verification failed";
                    }
                }

                if (hasError == false)
                {
                    _steps = ESteps.Succeed;
                    DownloadSystem.CacheVerifyFile(_bundleInfo.Hash, _bundleInfo.BundleName);
                }
                else
                {
                    string cacheFilePath = _bundleInfo.GetCacheLoadPath();
                    if (File.Exists(cacheFilePath))
                    {
                        File.Delete(cacheFilePath);
                    }

                    // 失败后重新尝试
                    if (_failedTryAgain > 0)
                    {
                        ReportWarning();
                        _steps = ESteps.TryAgain;
                    }
                    else
                    {
                        ReportError();
                        _steps = ESteps.Failed;
                    }
                }

                // 释放下载器
                DisposeWebRequest();
            }

            // 重新尝试下载
            if (_steps == ESteps.TryAgain)
            {
                _tryAgainTimer += Time.unscaledDeltaTime;
                if (_tryAgainTimer > 1f)
                {
                    _failedTryAgain--;
                    _steps = ESteps.CreateDownload;
                    YooLogger.Warning($"Try again download : {_requestURL}");
                }
            }
        }
Exemple #17
0
        /// <summary>
        /// 轮询更新
        /// </summary>
        public override void Update()
        {
            if (_steps == ESteps.Done)
            {
                return;
            }

            if (_steps == ESteps.None)
            {
                if (MainBundleInfo.IsInvalid)
                {
                    _steps    = ESteps.Done;
                    Status    = EStatus.Failed;
                    LastError = $"The bundle info is invalid : {MainBundleInfo.BundleName}";
                    YooLogger.Error(LastError);
                    return;
                }

                if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
                {
                    _steps        = ESteps.Download;
                    _fileLoadPath = MainBundleInfo.GetCacheLoadPath();
                }
                else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
                {
                    _steps        = ESteps.LoadFile;
                    _fileLoadPath = MainBundleInfo.GetStreamingLoadPath();
                }
                else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
                {
                    _steps        = ESteps.LoadFile;
                    _fileLoadPath = MainBundleInfo.GetCacheLoadPath();
                }
                else
                {
                    throw new System.NotImplementedException(MainBundleInfo.LoadMode.ToString());
                }
            }

            // 1. 从服务器下载
            if (_steps == ESteps.Download)
            {
                int failedTryAgain = int.MaxValue;
                _downloader = DownloadSystem.BeginDownload(MainBundleInfo, failedTryAgain);
                _steps      = ESteps.CheckDownload;
            }

            // 2. 检测服务器下载结果
            if (_steps == ESteps.CheckDownload)
            {
                if (_downloader.IsDone() == false)
                {
                    return;
                }

                if (_downloader.HasError())
                {
                    _steps    = ESteps.Done;
                    Status    = EStatus.Failed;
                    LastError = _downloader.GetLastError();
                }
                else
                {
                    _steps = ESteps.LoadFile;
                }
            }

            // 3. 加载AssetBundle
            if (_steps == ESteps.LoadFile)
            {
#if UNITY_EDITOR
                // 注意:Unity2017.4编辑器模式下,如果AssetBundle文件不存在会导致编辑器崩溃,这里做了预判。
                if (System.IO.File.Exists(_fileLoadPath) == false)
                {
                    _steps    = ESteps.Done;
                    Status    = EStatus.Failed;
                    LastError = $"Not found assetBundle file : {_fileLoadPath}";
                    YooLogger.Error(LastError);
                    return;
                }
#endif

                // Load assetBundle file
                if (MainBundleInfo.IsEncrypted)
                {
                    if (AssetSystem.DecryptionServices == null)
                    {
                        throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.BundleName}");
                    }

                    ulong offset = AssetSystem.DecryptionServices.GetFileOffset();
                    if (_isWaitForAsyncComplete)
                    {
                        CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset);
                    }
                    else
                    {
                        _cacheRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
                    }
                }
                else
                {
                    if (_isWaitForAsyncComplete)
                    {
                        CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath);
                    }
                    else
                    {
                        _cacheRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath);
                    }
                }
                _steps = ESteps.CheckFile;
            }

            // 4. 检测AssetBundle加载结果
            if (_steps == ESteps.CheckFile)
            {
                if (_cacheRequest != null)
                {
                    if (_isWaitForAsyncComplete)
                    {
                        // 强制挂起主线程(注意:该操作会很耗时)
                        YooLogger.Warning("Suspend the main thread to load unity bundle.");
                        CacheBundle = _cacheRequest.assetBundle;
                    }
                    else
                    {
                        if (_cacheRequest.isDone == false)
                        {
                            return;
                        }
                        CacheBundle = _cacheRequest.assetBundle;
                    }
                }

                // Check error
                if (CacheBundle == null)
                {
                    _steps    = ESteps.Done;
                    Status    = EStatus.Failed;
                    LastError = $"Failed to load assetBundle : {MainBundleInfo.BundleName}";
                    YooLogger.Error(LastError);
                }
                else
                {
                    _steps = ESteps.Done;
                    Status = EStatus.Succeed;
                }
            }
        }