From b90ab01fe96a8697f802afdd088cbd21a5bd0ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= Date: Thu, 10 Jul 2025 10:58:14 +0800 Subject: [PATCH] update file system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 下载器相关逻辑代码重构 --- .../DefaultBuildinFileSystem.cs | 2 +- .../DefaultCacheFileSystem.cs | 21 +- .../Operation/DCFSLoadBundleOperation.cs | 2 - .../internal/DownloadCenterOperation.cs | 42 ++-- .../internal/DownloadHandlerFileRange.cs | 87 -------- .../internal/DownloadHandlerFileRange.cs.meta | 11 - .../internal/DownloadNormalFileOperation.cs | 194 ------------------ .../DownloadPackageBundleOperation.cs | 164 +++++++++++++++ .../DownloadPackageBundleOperation.cs.meta} | 0 .../internal/UnityDownloadFileOperation.cs | 52 +++++ .../UnityDownloadFileOperation.cs.meta} | 2 +- ....cs => UnityDownloadLocalFileOperation.cs} | 123 ++++------- ...> UnityDownloadLocalFileOperation.cs.meta} | 0 .../UnityDownloadNormalFileOperation.cs | 126 ++++++++++++ ... UnityDownloadNormalFileOperation.cs.meta} | 0 ...cs => UnityDownloadResumeFileOperation.cs} | 165 ++++----------- ... UnityDownloadResumeFileOperation.cs.meta} | 0 .../Operation/DWRFSLoadBundleOperation.cs | 11 +- .../Operation/DWSFSLoadBundleOperation.cs | 10 +- .../Operation/FSDownloadFileOperation.cs | 57 ++--- .../Internal/DefaultDownloadFileOperation.cs | 131 ------------ .../Internal/DownloadAssetBundleOperation.cs | 19 +- .../Operation/Internal/DownloadFileWrapper.cs | 71 ------- .../DownloadWebEncryptAssetBundleOperation.cs | 154 +++++++------- .../DownloadWebNormalAssetBundleOperation.cs | 141 ++++++------- .../Operation/DownloaderOperation.cs | 2 +- 26 files changed, 644 insertions(+), 943 deletions(-) delete mode 100644 Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs delete mode 100644 Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs.meta delete mode 100644 Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadNormalFileOperation.cs create mode 100644 Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs rename Assets/YooAsset/Runtime/FileSystem/{Operation/Internal/DefaultDownloadFileOperation.cs.meta => DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs.meta} (100%) create mode 100644 Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs rename Assets/YooAsset/Runtime/FileSystem/{Operation/Internal/DownloadFileWrapper.cs.meta => DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs.meta} (83%) rename Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/{DownloadLocalFileOperation.cs => UnityDownloadLocalFileOperation.cs} (59%) rename Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/{DownloadLocalFileOperation.cs.meta => UnityDownloadLocalFileOperation.cs.meta} (100%) create mode 100644 Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadNormalFileOperation.cs rename Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/{DownloadNormalFileOperation.cs.meta => UnityDownloadNormalFileOperation.cs.meta} (100%) rename Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/{DownloadResumeFileOperation.cs => UnityDownloadResumeFileOperation.cs} (52%) rename Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/{DownloadResumeFileOperation.cs.meta => UnityDownloadResumeFileOperation.cs.meta} (100%) delete mode 100644 Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DefaultDownloadFileOperation.cs delete mode 100644 Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/DefaultBuildinFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/DefaultBuildinFileSystem.cs index 3f833112..61e2800b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/DefaultBuildinFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/DefaultBuildinFileSystem.cs @@ -125,7 +125,7 @@ namespace YooAsset } public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadFileOptions options) { - // 注意:业务层的解压下载器会依赖内置文件系统的下载方法 + // 注意:业务层的解压器会依赖该方法 options.ImportFilePath = GetBuildinFileLoadPath(bundle); return _unpackFileSystem.DownloadFileAsync(bundle, options); } diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/DefaultCacheFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/DefaultCacheFileSystem.cs index 7fb63b83..b14c1cfb 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/DefaultCacheFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/DefaultCacheFileSystem.cs @@ -166,12 +166,23 @@ namespace YooAsset } public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadFileOptions options) { - var downloader = DownloadCenter.DownloadFileAsync(bundle, options); - downloader.Reference(); //增加下载器的引用计数 + // 获取下载地址 + if (string.IsNullOrEmpty(options.ImportFilePath)) + { + // 注意:如果是解压文件系统类,这里会返回本地内置文件的下载路径 + string mainURL = RemoteServices.GetRemoteMainURL(bundle.FileName); + string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName); + options.SetURL(mainURL, fallbackURL); + } + else + { + // 注意:把本地导入文件路径转换为下载器请求地址 + string mainURL = DownloadSystemHelper.ConvertToWWWPath(options.ImportFilePath); + options.SetURL(mainURL, mainURL); + } - // 注意:将下载器进行包裹,可以避免父类任务终止的时候,连带子任务里的下载器也一起被终止! - var wrapper = new DownloadFileWrapper(downloader); - return wrapper; + var downloader = new DownloadPackageBundleOperation(this, bundle, options); + return downloader; } public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) { diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs index d53dd208..22620533 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs @@ -55,7 +55,6 @@ namespace YooAsset if (_steps == ESteps.DownloadFile) { - // 注意:边玩边下下载器引用计数没有Release if (_downloadFileOp == null) { DownloadFileOptions options = new DownloadFileOptions(int.MaxValue, 60); @@ -303,7 +302,6 @@ namespace YooAsset if (_steps == ESteps.DownloadFile) { - // 注意:边玩边下下载器引用计数没有Release if (_downloadFileOp == null) { DownloadFileOptions options = new DownloadFileOptions(int.MaxValue, 60); diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadCenterOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadCenterOperation.cs index 67eda71c..4caa97da 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadCenterOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadCenterOperation.cs @@ -3,10 +3,21 @@ using System.Collections.Generic; namespace YooAsset { + /// + /// 下载器单元测试 + /// 1. 下载失败重试机制 + /// 2. 下载引用计数机制 + /// 3. 最大下载并发机制 + /// 4. 异步下载远端资源 + /// 5. 同步下载远端资源 + /// 6. 异步拷贝本地资源 + /// 7. 同步拷贝本地资源 + /// 9. 断点续传下载器 + /// internal class DownloadCenterOperation : AsyncOperationBase { private readonly DefaultCacheFileSystem _fileSystem; - protected readonly Dictionary _downloaders = new Dictionary(1000); + protected readonly Dictionary _downloaders = new Dictionary(1000); protected readonly List _removeDownloadList = new List(1000); public DownloadCenterOperation(DefaultCacheFileSystem fileSystem) @@ -74,34 +85,21 @@ namespace YooAsset /// /// 创建下载任务 /// - public FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadFileOptions options) + public UnityDownloadFileOperation DownloadFileAsync(PackageBundle bundle, string url, int timeout) { // 查询旧的下载器 if (_downloaders.TryGetValue(bundle.BundleGUID, out var oldDownloader)) { + oldDownloader.Reference(); return oldDownloader; } - // 获取下载地址 - if (string.IsNullOrEmpty(options.ImportFilePath)) - { - // 注意:如果是解压文件系统类,这里会返回本地内置文件的下载路径 - options.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(bundle.FileName); - options.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(bundle.FileName); - } - else - { - // 注意:把本地导入文件路径转换为下载器请求地址 - options.MainURL = DownloadSystemHelper.ConvertToWWWPath(options.ImportFilePath); - options.FallbackURL = options.MainURL; - } - // 创建新的下载器 - DefaultDownloadFileOperation newDownloader; - bool isRequestLocalFile = DownloadSystemHelper.IsRequestLocalFile(options.MainURL); + UnityDownloadFileOperation newDownloader; + bool isRequestLocalFile = DownloadSystemHelper.IsRequestLocalFile(url); if (isRequestLocalFile) { - newDownloader = new DownloadLocalFileOperation(_fileSystem, bundle, options); + newDownloader = new UnityDownloadLocalFileOperation(_fileSystem, bundle, url, timeout); AddChildOperation(newDownloader); _downloaders.Add(bundle.BundleGUID, newDownloader); } @@ -109,17 +107,19 @@ namespace YooAsset { if (bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize) { - newDownloader = new DownloadResumeFileOperation(_fileSystem, bundle, options); + newDownloader = new UnityDownloadResumeFileOperation(_fileSystem, bundle, url, timeout); AddChildOperation(newDownloader); _downloaders.Add(bundle.BundleGUID, newDownloader); } else { - newDownloader = new DownloadNormalFileOperation(_fileSystem, bundle, options); + newDownloader = new UnityDownloadNormalFileOperation(_fileSystem, bundle, url, timeout); AddChildOperation(newDownloader); _downloaders.Add(bundle.BundleGUID, newDownloader); } } + + newDownloader.Reference(); return newDownloader; } diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs deleted file mode 100644 index c2e11f4b..00000000 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.IO; -using UnityEngine; -using UnityEngine.Networking; - -namespace YooAsset -{ - /// - /// 支持Unity2018版本的断点续传下载器 - /// - internal class DownloadHandlerFileRange : DownloadHandlerScript - { - private string _fileSavePath; - private long _fileTotalSize; - private UnityWebRequest _webRequest; - private FileStream _fileStream; - - private long _localFileSize = 0; - private long _curFileSize = 0; - - - public DownloadHandlerFileRange(string fileSavePath, long fileTotalSize, UnityWebRequest webRequest) : base(new byte[1024 * 1024]) - { - _fileSavePath = fileSavePath; - _fileTotalSize = fileTotalSize; - _webRequest = webRequest; - - if (File.Exists(fileSavePath)) - { - FileInfo fileInfo = new FileInfo(fileSavePath); - _localFileSize = fileInfo.Length; - } - - _fileStream = new FileStream(_fileSavePath, FileMode.Append, FileAccess.Write); - _curFileSize = _localFileSize; - } - protected override bool ReceiveData(byte[] data, int dataLength) - { - if (data == null || dataLength == 0 || _webRequest.responseCode >= 400) - return false; - - if (_fileStream == null) - return false; - - _fileStream.Write(data, 0, dataLength); - _curFileSize += dataLength; - return true; - } - - /// - /// UnityWebRequest.downloadHandler.data - /// - protected override byte[] GetData() - { - return null; - } - - /// - /// UnityWebRequest.downloadHandler.text - /// - protected override string GetText() - { - return null; - } - - /// - /// UnityWebRequest.downloadProgress - /// - protected override float GetProgress() - { - return _fileTotalSize == 0 ? 0 : ((float)_curFileSize) / _fileTotalSize; - } - - /// - /// 释放下载句柄 - /// - public void Cleanup() - { - if (_fileStream != null) - { - _fileStream.Flush(); - _fileStream.Dispose(); - _fileStream = null; - } - } - } -} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs.meta b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs.meta deleted file mode 100644 index ff557b1c..00000000 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadHandlerFileRange.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 94254ab8e4496214884c11a891c131c6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadNormalFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadNormalFileOperation.cs deleted file mode 100644 index 4ddf5f74..00000000 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadNormalFileOperation.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System.IO; -using UnityEngine; -using UnityEngine.Networking; - -namespace YooAsset -{ - internal sealed class DownloadNormalFileOperation : DefaultDownloadFileOperation - { - private readonly DefaultCacheFileSystem _fileSystem; - private VerifyTempFileOperation _verifyOperation; - private string _tempFilePath; - private ESteps _steps = ESteps.None; - - internal DownloadNormalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options) - { - _fileSystem = fileSystem; - } - internal override void InternalStart() - { - _tempFilePath = _fileSystem.GetTempFilePath(Bundle); - _steps = ESteps.CheckExists; - } - internal override void InternalUpdate() - { - if (_steps == ESteps.None || _steps == ESteps.Done) - return; - - // 检测文件是否存在 - if (_steps == ESteps.CheckExists) - { - if (_fileSystem.Exists(Bundle)) - { - _steps = ESteps.Done; - Status = EOperationStatus.Succeed; - } - else - { - _steps = ESteps.CreateRequest; - } - } - - // 创建下载器 - if (_steps == ESteps.CreateRequest) - { - FileUtility.CreateFileDirectory(_tempFilePath); - - // 删除临时文件 - if (File.Exists(_tempFilePath)) - File.Delete(_tempFilePath); - - // 获取请求地址 - _requestURL = GetRequestURL(); - - // 重置请求 - ResetRequestFiled(); - - // 创建下载器 - CreateWebRequest(); - - _steps = ESteps.CheckRequest; - } - - // 检测下载结果 - if (_steps == ESteps.CheckRequest) - { - DownloadProgress = _webRequest.downloadProgress; - DownloadedBytes = (long)_webRequest.downloadedBytes; - Progress = DownloadProgress; - if (_webRequest.isDone == false) - { - CheckRequestTimeout(); - return; - } - - // 检查网络错误 - if (CheckRequestResult()) - _steps = ESteps.VerifyTempFile; - else - _steps = ESteps.TryAgain; - - // 注意:最终释放请求器 - DisposeWebRequest(); - } - - // 验证下载文件 - if (_steps == ESteps.VerifyTempFile) - { - var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize); - _verifyOperation = new VerifyTempFileOperation(element); - _verifyOperation.StartOperation(); - AddChildOperation(_verifyOperation); - _steps = ESteps.CheckVerifyTempFile; - } - - // 等待验证完成 - if (_steps == ESteps.CheckVerifyTempFile) - { - if (IsWaitForAsyncComplete) - _verifyOperation.WaitForAsyncComplete(); - - _verifyOperation.UpdateOperation(); - if (_verifyOperation.IsDone == false) - return; - - if (_verifyOperation.Status == EOperationStatus.Succeed) - { - if (_fileSystem.WriteCacheBundleFile(Bundle, _tempFilePath)) - { - _steps = ESteps.Done; - Status = EOperationStatus.Succeed; - } - else - { - _steps = ESteps.Done; - Status = EOperationStatus.Failed; - Error = $"{_fileSystem.GetType().FullName} failed to write file !"; - YooLogger.Error(Error); - } - } - else - { - _steps = ESteps.TryAgain; - Error = _verifyOperation.Error; - } - - // 注意:验证完成后直接删除文件 - if (File.Exists(_tempFilePath)) - File.Delete(_tempFilePath); - } - - // 重新尝试下载 - if (_steps == ESteps.TryAgain) - { - if (FailedTryAgain <= 0) - { - Status = EOperationStatus.Failed; - _steps = ESteps.Done; - YooLogger.Error(Error); - return; - } - - _tryAgainTimer += Time.unscaledDeltaTime; - if (_tryAgainTimer > 1f) - { - FailedTryAgain--; - _steps = ESteps.CreateRequest; - YooLogger.Warning(Error); - } - } - } - internal override void InternalAbort() - { - _steps = ESteps.Done; - DisposeWebRequest(); - } - internal override void InternalWaitForAsyncComplete() - { - while (true) - { - if (ExecuteWhileDone()) - { - //TODO 尝试同步加载远端的资源文件失败 - if (Status == EOperationStatus.Failed) - { - YooLogger.Error($"Try load bundle {Bundle.BundleName} from remote !"); - YooLogger.Error($"The load remote bundle url : {_requestURL}"); - } - - _steps = ESteps.Done; - break; - } - } - } - - private void CreateWebRequest() - { - _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); - DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath); - handler.removeFileOnAbort = true; - _webRequest.downloadHandler = handler; - _webRequest.disposeDownloadHandlerOnDispose = true; - _webRequest.SendWebRequest(); - } - private void DisposeWebRequest() - { - if (_webRequest != null) - { - //注意:引擎底层会自动调用Abort方法 - _webRequest.Dispose(); - _webRequest = null; - } - } - } -} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs new file mode 100644 index 00000000..8ee4f2fd --- /dev/null +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs @@ -0,0 +1,164 @@ +using UnityEngine; + +namespace YooAsset +{ + internal class DownloadPackageBundleOperation : FSDownloadFileOperation + { + protected enum ESteps + { + None, + CheckExists, + CreateRequest, + CheckRequest, + TryAgain, + Done, + } + + // 下载参数 + protected readonly DefaultCacheFileSystem _fileSystem; + protected readonly DownloadFileOptions _options; + private UnityDownloadFileOperation _unityDownloadFileOp; + + protected int _requestCount = 0; + protected float _tryAgainTimer; + protected int _failedTryAgain; + private ESteps _steps = ESteps.None; + + + internal DownloadPackageBundleOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle) + { + _fileSystem = fileSystem; + _options = options; + _failedTryAgain = options.FailedTryAgain; + } + internal override void InternalStart() + { + _steps = ESteps.CheckExists; + } + internal override void InternalUpdate() + { + if (_steps == ESteps.None || _steps == ESteps.Done) + return; + + // 检测文件是否存在 + if (_steps == ESteps.CheckExists) + { + if (_fileSystem.Exists(Bundle)) + { + _steps = ESteps.Done; + Status = EOperationStatus.Succeed; + } + else + { + _steps = ESteps.CreateRequest; + } + } + + // 创建下载器 + if (_steps == ESteps.CreateRequest) + { + if (_options.IsValid() == false) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = "Download file options is invalid !"; + Debug.Log(Error); + return; + } + + string url = GetRequestURL(); + _unityDownloadFileOp = _fileSystem.DownloadCenter.DownloadFileAsync(Bundle, url, _options.Timeout); + _steps = ESteps.CheckRequest; + } + + // 检测下载结果 + if (_steps == ESteps.CheckRequest) + { + if (IsWaitForAsyncComplete) + _unityDownloadFileOp.WaitForAsyncComplete(); + + // 因为并发数量限制,下载器可能被挂起! + if (_unityDownloadFileOp.Status == EOperationStatus.None) + return; + + _unityDownloadFileOp.UpdateOperation(); + Progress = _unityDownloadFileOp.Progress; + DownloadedBytes = _unityDownloadFileOp.DownloadedBytes; + DownloadProgress = _unityDownloadFileOp.DownloadProgress; + if (_unityDownloadFileOp.IsDone == false) + return; + + if (_unityDownloadFileOp.Status == EOperationStatus.Succeed) + { + _steps = ESteps.Done; + Status = EOperationStatus.Succeed; + } + else + { + if (IsWaitForAsyncComplete == false && _failedTryAgain > 0) + { + _steps = ESteps.TryAgain; + YooLogger.Warning($"Failed download : {_unityDownloadFileOp.URL} Try again !"); + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = _unityDownloadFileOp.Error; + YooLogger.Error(Error); + } + } + } + + // 重新尝试下载 + if (_steps == ESteps.TryAgain) + { + _tryAgainTimer += Time.unscaledDeltaTime; + if (_tryAgainTimer > 1f) + { + _tryAgainTimer = 0f; + _failedTryAgain--; + Progress = 0f; + DownloadProgress = 0f; + DownloadedBytes = 0; + _steps = ESteps.CreateRequest; + } + } + } + internal override void InternalWaitForAsyncComplete() + { + while (true) + { + if (ExecuteWhileDone()) + { + _steps = ESteps.Done; + break; + } + } + } + internal override void InternalAbort() + { + // 注意:取消下载任务的时候引用计数减一 + if (_steps != ESteps.Done) + { + if (_unityDownloadFileOp != null) + { + _unityDownloadFileOp.Release(); + } + } + } + + /// + /// 获取网络请求地址 + /// + protected string GetRequestURL() + { + // 轮流返回请求地址 + _requestCount++; + if (_requestCount % 2 == 0) + return _options.FallbackURL; + else + return _options.MainURL; + } + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DefaultDownloadFileOperation.cs.meta b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs.meta similarity index 100% rename from Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DefaultDownloadFileOperation.cs.meta rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs.meta diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs new file mode 100644 index 00000000..a2c80106 --- /dev/null +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs @@ -0,0 +1,52 @@ + +namespace YooAsset +{ + internal abstract class UnityDownloadFileOperation : UnityWebRequestOperation + { + protected enum ESteps + { + None, + CreateRequest, + Download, + CopyLocalFile, + VerifyFile, + Done, + } + + protected readonly DefaultCacheFileSystem _fileSystem; + protected readonly PackageBundle _bundle; + protected readonly string _tempFilePath; + + /// + /// 引用计数 + /// + public int RefCount { private set; get; } + + internal UnityDownloadFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url, int timeout) : base(url, timeout) + { + _fileSystem = fileSystem; + _bundle = bundle; + _tempFilePath = _fileSystem.GetTempFilePath(bundle); + } + internal override string InternalGetDesc() + { + return $"RefCount : {RefCount}"; + } + + /// + /// 减少引用计数 + /// + public void Release() + { + RefCount--; + } + + /// + /// 增加引用计数 + /// + public void Reference() + { + RefCount++; + } + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs.meta b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs.meta similarity index 83% rename from Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs.meta rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs.meta index 0964e08d..eec39b4e 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs.meta +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadFileOperation.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8088863fc7dfbd441bc897380cd7b97f +guid: 40bb5e9391f413c42ae70e48ca90c4b7 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadLocalFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadLocalFileOperation.cs similarity index 59% rename from Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadLocalFileOperation.cs rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadLocalFileOperation.cs index f52906fc..3fece090 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadLocalFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadLocalFileOperation.cs @@ -4,67 +4,41 @@ using UnityEngine.Networking; namespace YooAsset { - internal class DownloadLocalFileOperation : DefaultDownloadFileOperation + internal class UnityDownloadLocalFileOperation : UnityDownloadFileOperation { - private readonly DefaultCacheFileSystem _fileSystem; private VerifyTempFileOperation _verifyOperation; - private string _tempFilePath; private ESteps _steps = ESteps.None; - internal DownloadLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options) + internal UnityDownloadLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url, int timeout = 60) + : base(fileSystem, bundle, url, timeout) { - _fileSystem = fileSystem; } internal override void InternalStart() { - _tempFilePath = _fileSystem.GetTempFilePath(Bundle); - _steps = ESteps.CheckExists; + if (_fileSystem.CopyLocalFileServices != null) + _steps = ESteps.CopyLocalFile; + else + _steps = ESteps.CreateRequest; } internal override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) return; - // 检测文件是否存在 - if (_steps == ESteps.CheckExists) - { - if (_fileSystem.Exists(Bundle)) - { - _steps = ESteps.Done; - Status = EOperationStatus.Succeed; - } - else - { - if (_fileSystem.CopyLocalFileServices != null) - _steps = ESteps.CopyBuildinBundle; - else - _steps = ESteps.CreateRequest; - } - } - // 创建下载器 if (_steps == ESteps.CreateRequest) { FileUtility.CreateFileDirectory(_tempFilePath); - - // 删除临时文件 if (File.Exists(_tempFilePath)) File.Delete(_tempFilePath); - // 获取请求地址 - _requestURL = GetRequestURL(); - - // 重置请求 - ResetRequestFiled(); - - // 创建下载器 + ResetTimeout(); CreateWebRequest(); - - _steps = ESteps.CheckRequest; + _steps = ESteps.Download; } // 检测下载结果 - if (_steps == ESteps.CheckRequest) + if (_steps == ESteps.Download) { DownloadProgress = _webRequest.downloadProgress; DownloadedBytes = (long)_webRequest.downloadedBytes; @@ -77,67 +51,67 @@ namespace YooAsset // 检查网络错误 if (CheckRequestResult()) - _steps = ESteps.VerifyTempFile; + { + _steps = ESteps.VerifyFile; + } else - _steps = ESteps.TryAgain; + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + } // 注意:最终释放请求器 - DisposeWebRequest(); + DisposeRequest(); } // 拷贝内置文件 - if (_steps == ESteps.CopyBuildinBundle) + if (_steps == ESteps.CopyLocalFile) { FileUtility.CreateFileDirectory(_tempFilePath); - - // 删除临时文件 if (File.Exists(_tempFilePath)) File.Delete(_tempFilePath); - // 获取请求地址 - _requestURL = GetRequestURL(); - try { //TODO 团结引擎,在某些机型(红米),拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。 var localFileInfo = new LocalFileInfo(); localFileInfo.PackageName = _fileSystem.PackageName; - localFileInfo.BundleName = Bundle.BundleName; + localFileInfo.BundleName = _bundle.BundleName; localFileInfo.SourceFileURL = _requestURL; _fileSystem.CopyLocalFileServices.CopyFile(localFileInfo, _tempFilePath); if (File.Exists(_tempFilePath)) { DownloadProgress = 1f; - DownloadedBytes = Bundle.FileSize; + DownloadedBytes = _bundle.FileSize; Progress = DownloadProgress; - _steps = ESteps.VerifyTempFile; + _steps = ESteps.VerifyFile; } else { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; Error = $"Failed copy local file : {_requestURL}"; - _steps = ESteps.TryAgain; } } catch (System.Exception ex) { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; Error = $"Failed copy local file : {ex.Message}"; - _steps = ESteps.TryAgain; } } // 验证下载文件 - if (_steps == ESteps.VerifyTempFile) + if (_steps == ESteps.VerifyFile) { - var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize); - _verifyOperation = new VerifyTempFileOperation(element); - _verifyOperation.StartOperation(); - AddChildOperation(_verifyOperation); - _steps = ESteps.CheckVerifyTempFile; - } + if (_verifyOperation == null) + { + var element = new TempFileElement(_tempFilePath, _bundle.FileCRC, _bundle.FileSize); + _verifyOperation = new VerifyTempFileOperation(element); + _verifyOperation.StartOperation(); + AddChildOperation(_verifyOperation); + } - // 等待验证完成 - if (_steps == ESteps.CheckVerifyTempFile) - { if (IsWaitForAsyncComplete) _verifyOperation.WaitForAsyncComplete(); @@ -147,7 +121,7 @@ namespace YooAsset if (_verifyOperation.Status == EOperationStatus.Succeed) { - if (_fileSystem.WriteCacheBundleFile(Bundle, _tempFilePath)) + if (_fileSystem.WriteCacheBundleFile(_bundle, _tempFilePath)) { _steps = ESteps.Done; Status = EOperationStatus.Succeed; @@ -157,12 +131,12 @@ namespace YooAsset _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"{_fileSystem.GetType().FullName} failed to write file !"; - YooLogger.Error(Error); } } else { - _steps = ESteps.TryAgain; + _steps = ESteps.Done; + Status = EOperationStatus.Failed; Error = _verifyOperation.Error; } @@ -170,20 +144,6 @@ namespace YooAsset if (File.Exists(_tempFilePath)) File.Delete(_tempFilePath); } - - // 重新尝试下载 - if (_steps == ESteps.TryAgain) - { - //TODO 拷贝本地文件失败后不再尝试! - Status = EOperationStatus.Failed; - _steps = ESteps.Done; - YooLogger.Error(Error); - } - } - internal override void InternalAbort() - { - _steps = ESteps.Done; - DisposeWebRequest(); } internal override void InternalWaitForAsyncComplete() { @@ -208,14 +168,5 @@ namespace YooAsset _webRequest.disposeDownloadHandlerOnDispose = true; _webRequest.SendWebRequest(); } - private void DisposeWebRequest() - { - if (_webRequest != null) - { - //注意:引擎底层会自动调用Abort方法 - _webRequest.Dispose(); - _webRequest = null; - } - } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadLocalFileOperation.cs.meta b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadLocalFileOperation.cs.meta similarity index 100% rename from Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadLocalFileOperation.cs.meta rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadLocalFileOperation.cs.meta diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadNormalFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadNormalFileOperation.cs new file mode 100644 index 00000000..546a9c2e --- /dev/null +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadNormalFileOperation.cs @@ -0,0 +1,126 @@ +using System.IO; +using UnityEngine; +using UnityEngine.Networking; + +namespace YooAsset +{ + internal sealed class UnityDownloadNormalFileOperation : UnityDownloadFileOperation + { + private VerifyTempFileOperation _verifyOperation; + private ESteps _steps = ESteps.None; + + internal UnityDownloadNormalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url, int timeout = 60) + : base(fileSystem, bundle, url, timeout) + { + } + internal override void InternalStart() + { + _steps = ESteps.CreateRequest; + } + internal override void InternalUpdate() + { + if (_steps == ESteps.None || _steps == ESteps.Done) + return; + + // 创建下载器 + if (_steps == ESteps.CreateRequest) + { + FileUtility.CreateFileDirectory(_tempFilePath); + if (File.Exists(_tempFilePath)) + File.Delete(_tempFilePath); + + ResetTimeout(); + CreateWebRequest(); + _steps = ESteps.Download; + } + + // 检测下载结果 + if (_steps == ESteps.Download) + { + DownloadProgress = _webRequest.downloadProgress; + DownloadedBytes = (long)_webRequest.downloadedBytes; + Progress = DownloadProgress; + if (_webRequest.isDone == false) + { + CheckRequestTimeout(); + return; + } + + // 检查网络错误 + if (CheckRequestResult()) + { + _steps = ESteps.VerifyFile; + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + } + + // 注意:最终释放请求器 + DisposeRequest(); + } + + // 验证下载文件 + if (_steps == ESteps.VerifyFile) + { + if (_verifyOperation == null) + { + var element = new TempFileElement(_tempFilePath, _bundle.FileCRC, _bundle.FileSize); + _verifyOperation = new VerifyTempFileOperation(element); + _verifyOperation.StartOperation(); + AddChildOperation(_verifyOperation); + } + + if (IsWaitForAsyncComplete) + _verifyOperation.WaitForAsyncComplete(); + + _verifyOperation.UpdateOperation(); + if (_verifyOperation.IsDone == false) + return; + + if (_verifyOperation.Status == EOperationStatus.Succeed) + { + if (_fileSystem.WriteCacheBundleFile(_bundle, _tempFilePath)) + { + _steps = ESteps.Done; + Status = EOperationStatus.Succeed; + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"{_fileSystem.GetType().FullName} failed to write file ! {_tempFilePath}"; + } + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = _verifyOperation.Error; + } + + // 注意:验证完成后直接删除文件 + if (File.Exists(_tempFilePath)) + File.Delete(_tempFilePath); + } + } + internal override void InternalWaitForAsyncComplete() + { + if (_steps != ESteps.Done) + { + YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote : {_requestURL} !"); + } + } + + private void CreateWebRequest() + { + _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); + DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath); + handler.removeFileOnAbort = true; + _webRequest.downloadHandler = handler; + _webRequest.disposeDownloadHandlerOnDispose = true; + _webRequest.SendWebRequest(); + } + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadNormalFileOperation.cs.meta b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadNormalFileOperation.cs.meta similarity index 100% rename from Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadNormalFileOperation.cs.meta rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadNormalFileOperation.cs.meta diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadResumeFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadResumeFileOperation.cs similarity index 52% rename from Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadResumeFileOperation.cs rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadResumeFileOperation.cs index c18fe924..9ae3c8bb 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadResumeFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadResumeFileOperation.cs @@ -4,63 +4,38 @@ using UnityEngine.Networking; namespace YooAsset { - internal sealed class DownloadResumeFileOperation : DefaultDownloadFileOperation + internal sealed class UnityDownloadResumeFileOperation : UnityDownloadFileOperation { - private readonly DefaultCacheFileSystem _fileSystem; - private DownloadHandlerFileRange _downloadHandle; private VerifyTempFileOperation _verifyOperation; private long _fileOriginLength = 0; - private string _tempFilePath; private ESteps _steps = ESteps.None; - internal DownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options) + internal UnityDownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url, int timeout = 60) + : base(fileSystem, bundle, url, timeout) { - _fileSystem = fileSystem; } internal override void InternalStart() { - _tempFilePath = _fileSystem.GetTempFilePath(Bundle); - _steps = ESteps.CheckExists; + _steps = ESteps.CreateRequest; } internal override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) return; - // 检测文件是否存在 - if (_steps == ESteps.CheckExists) - { - if (_fileSystem.Exists(Bundle)) - { - _steps = ESteps.Done; - Status = EOperationStatus.Succeed; - } - else - { - _steps = ESteps.CreateRequest; - } - } - // 创建下载器 if (_steps == ESteps.CreateRequest) { FileUtility.CreateFileDirectory(_tempFilePath); - // 获取请求地址 - _requestURL = GetRequestURL(); - - // 重置变量 - ResetRequestFiled(); - // 获取下载起始位置 _fileOriginLength = 0; long fileBeginLength = -1; if (File.Exists(_tempFilePath)) { FileInfo fileInfo = new FileInfo(_tempFilePath); - if (fileInfo.Length >= Bundle.FileSize) + if (fileInfo.Length >= _bundle.FileSize) { - // 删除临时文件 File.Delete(_tempFilePath); } else @@ -71,17 +46,17 @@ namespace YooAsset } } - // 创建下载器 + ResetTimeout(); CreateWebRequest(fileBeginLength); - - _steps = ESteps.CheckRequest; + _steps = ESteps.Download; } // 检测下载结果 - if (_steps == ESteps.CheckRequest) + if (_steps == ESteps.Download) { DownloadProgress = _webRequest.downloadProgress; DownloadedBytes = _fileOriginLength + (long)_webRequest.downloadedBytes; + Progress = DownloadProgress; if (_webRequest.isDone == false) { CheckRequestTimeout(); @@ -90,30 +65,33 @@ namespace YooAsset // 检查网络错误 if (CheckRequestResult()) - _steps = ESteps.VerifyTempFile; + { + _steps = ESteps.VerifyFile; + } else - _steps = ESteps.TryAgain; + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + } // 在遇到特殊错误的时候删除文件 ClearTempFileWhenError(); // 注意:最终释放请求器 - DisposeWebRequest(); + DisposeRequest(); } // 验证下载文件 - if (_steps == ESteps.VerifyTempFile) + if (_steps == ESteps.VerifyFile) { - var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize); - _verifyOperation = new VerifyTempFileOperation(element); - _verifyOperation.StartOperation(); - AddChildOperation(_verifyOperation); - _steps = ESteps.CheckVerifyTempFile; - } + if (_verifyOperation == null) + { + var element = new TempFileElement(_tempFilePath, _bundle.FileCRC, _bundle.FileSize); + _verifyOperation = new VerifyTempFileOperation(element); + _verifyOperation.StartOperation(); + AddChildOperation(_verifyOperation); + } - // 等待验证完成 - if (_steps == ESteps.CheckVerifyTempFile) - { if (IsWaitForAsyncComplete) _verifyOperation.WaitForAsyncComplete(); @@ -123,104 +101,38 @@ namespace YooAsset if (_verifyOperation.Status == EOperationStatus.Succeed) { - if (_fileSystem.WriteCacheBundleFile(Bundle, _tempFilePath)) + if (_fileSystem.WriteCacheBundleFile(_bundle, _tempFilePath)) { - Status = EOperationStatus.Succeed; _steps = ESteps.Done; + Status = EOperationStatus.Succeed; } else { - Error = $"{_fileSystem.GetType().FullName} failed to write file !"; - Status = EOperationStatus.Failed; _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"{_fileSystem.GetType().FullName} failed to write file !"; } } else { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; Error = _verifyOperation.Error; - _steps = ESteps.TryAgain; } // 注意:验证完成后直接删除文件 if (File.Exists(_tempFilePath)) File.Delete(_tempFilePath); } - - // 重新尝试下载 - if (_steps == ESteps.TryAgain) - { - if (FailedTryAgain <= 0) - { - Status = EOperationStatus.Failed; - _steps = ESteps.Done; - YooLogger.Error(Error); - return; - } - - _tryAgainTimer += Time.unscaledDeltaTime; - if (_tryAgainTimer > 1f) - { - FailedTryAgain--; - _steps = ESteps.CreateRequest; - YooLogger.Warning(Error); - } - } - } - internal override void InternalAbort() - { - _steps = ESteps.Done; - DisposeWebRequest(); } internal override void InternalWaitForAsyncComplete() { - while (true) + if (_steps != ESteps.Done) { - if (ExecuteWhileDone()) - { - //TODO 尝试同步加载远端的资源文件失败 - if (Status == EOperationStatus.Failed) - { - YooLogger.Error($"Try load bundle {Bundle.BundleName} from remote !"); - YooLogger.Error($"The load remote bundle url : {_requestURL}"); - } - - _steps = ESteps.Done; - break; - } + YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote : {_requestURL} !"); } } - private void CreateWebRequest(long beginLength) - { - _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); -#if UNITY_2019_4_OR_NEWER - var handler = new DownloadHandlerFile(_tempFilePath, true); - handler.removeFileOnAbort = false; -#else - var handler = new DownloadHandlerFileRange(FileSavePath, Bundle.FileSize, _webRequest); - _downloadHandle = handler; -#endif - _webRequest.downloadHandler = handler; - _webRequest.disposeDownloadHandlerOnDispose = true; - if (beginLength > 0) - _webRequest.SetRequestHeader("Range", $"bytes={beginLength}-"); - _webRequest.SendWebRequest(); - } - private void DisposeWebRequest() - { - if (_downloadHandle != null) - { - _downloadHandle.Cleanup(); - _downloadHandle = null; - } - - if (_webRequest != null) - { - //注意:引擎底层会自动调用Abort方法 - _webRequest.Dispose(); - _webRequest = null; - } - } private void ClearTempFileWhenError() { if (_fileSystem.ResumeDownloadResponseCodes == null) @@ -233,5 +145,16 @@ namespace YooAsset File.Delete(_tempFilePath); } } + private void CreateWebRequest(long fileBeginLength) + { + _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); + var handler = new DownloadHandlerFile(_tempFilePath, true); + handler.removeFileOnAbort = false; + _webRequest.downloadHandler = handler; + _webRequest.disposeDownloadHandlerOnDispose = true; + if (fileBeginLength > 0) + _webRequest.SetRequestHeader("Range", $"bytes={fileBeginLength}-"); + _webRequest.SendWebRequest(); + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadResumeFileOperation.cs.meta b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadResumeFileOperation.cs.meta similarity index 100% rename from Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadResumeFileOperation.cs.meta rename to Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/UnityDownloadResumeFileOperation.cs.meta diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs index de18f0d2..5cc02c5c 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs @@ -34,19 +34,20 @@ namespace YooAsset { if (_downloadAssetBundleOp == null) { + string mainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); + string fallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName); DownloadFileOptions options = new DownloadFileOptions(int.MaxValue, 60); - options.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); - options.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName); - + options.SetURL(mainURL, fallbackURL); + if (_bundle.Encrypted) { - _downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(true, _fileSystem.DecryptionServices, _bundle, options); + _downloadAssetBundleOp = new DownloadEncryptAssetBundleOperation(_bundle, options, true, _fileSystem.DecryptionServices); _downloadAssetBundleOp.StartOperation(); AddChildOperation(_downloadAssetBundleOp); } else { - _downloadAssetBundleOp = new DownloadWebNormalAssetBundleOperation(_fileSystem.DisableUnityWebCache, _bundle, options); + _downloadAssetBundleOp = new DownloadNormalAssetBundleOperation(_bundle, options, _fileSystem.DisableUnityWebCache); _downloadAssetBundleOp.StartOperation(); AddChildOperation(_downloadAssetBundleOp); } diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs index 120601b0..d206113b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs @@ -34,20 +34,20 @@ namespace YooAsset { if (_downloadAssetBundleOp == null) { - DownloadFileOptions options = new DownloadFileOptions(int.MaxValue, 60); string fileLoadPath = _fileSystem.GetWebFileLoadPath(_bundle); - options.MainURL = DownloadSystemHelper.ConvertToWWWPath(fileLoadPath); - options.FallbackURL = options.MainURL; + string mainURL = DownloadSystemHelper.ConvertToWWWPath(fileLoadPath); + DownloadFileOptions options = new DownloadFileOptions(int.MaxValue, 60); + options.SetURL(mainURL, mainURL); if (_bundle.Encrypted) { - _downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(true, _fileSystem.DecryptionServices, _bundle, options); + _downloadAssetBundleOp = new DownloadEncryptAssetBundleOperation(_bundle, options, true, _fileSystem.DecryptionServices); _downloadAssetBundleOp.StartOperation(); AddChildOperation(_downloadAssetBundleOp); } else { - _downloadAssetBundleOp = new DownloadWebNormalAssetBundleOperation(_fileSystem.DisableUnityWebCache, _bundle, options); + _downloadAssetBundleOp = new DownloadNormalAssetBundleOperation(_bundle, options, _fileSystem.DisableUnityWebCache); _downloadAssetBundleOp.StartOperation(); AddChildOperation(_downloadAssetBundleOp); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/FSDownloadFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operation/FSDownloadFileOperation.cs index 9703683c..6ff3c3ed 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/FSDownloadFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operation/FSDownloadFileOperation.cs @@ -16,12 +16,12 @@ namespace YooAsset /// /// 主资源地址 /// - public string MainURL { set; get; } + public string MainURL { private set; get; } /// /// 备用资源地址 /// - public string FallbackURL { set; get; } + public string FallbackURL { private set; get; } /// /// 拷贝的本地文件路径 @@ -33,22 +33,32 @@ namespace YooAsset FailedTryAgain = failedTryAgain; Timeout = timeout; } + + /// + /// 设置下载地址 + /// + public void SetURL(string mainURL, string fallbackURL) + { + MainURL = mainURL; + FallbackURL = fallbackURL; + } + + /// + /// 是否有效 + /// + public bool IsValid() + { + if (string.IsNullOrEmpty(MainURL) || string.IsNullOrEmpty(FallbackURL)) + return false; + + return true; + } } internal abstract class FSDownloadFileOperation : AsyncOperationBase { public PackageBundle Bundle { private set; get; } - /// - /// 引用计数 - /// - public int RefCount { private set; get; } - - /// - /// HTTP返回码 - /// - public long HttpCode { protected set; get; } - /// /// 当前下载的字节数 /// @@ -63,31 +73,8 @@ namespace YooAsset public FSDownloadFileOperation(PackageBundle bundle) { Bundle = bundle; - RefCount = 0; - HttpCode = 0; DownloadedBytes = 0; DownloadProgress = 0; } - - internal override string InternalGetDesc() - { - return $"RefCount : {RefCount}"; - } - - /// - /// 减少引用计数 - /// - public virtual void Release() - { - RefCount--; - } - - /// - /// 增加引用计数 - /// - public virtual void Reference() - { - RefCount++; - } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DefaultDownloadFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DefaultDownloadFileOperation.cs deleted file mode 100644 index c1e19cf9..00000000 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DefaultDownloadFileOperation.cs +++ /dev/null @@ -1,131 +0,0 @@ -using UnityEngine; -using UnityEngine.Networking; - -namespace YooAsset -{ - internal abstract class DefaultDownloadFileOperation : FSDownloadFileOperation - { - protected enum ESteps - { - None, - CheckExists, - CreateRequest, - CheckRequest, - CopyBuildinBundle, - VerifyTempFile, - CheckVerifyTempFile, - TryAgain, - Done, - } - - // 下载参数 - protected readonly DownloadFileOptions Options; - - // 请求相关 - protected UnityWebRequest _webRequest; - protected string _requestURL; - protected int _requestCount = 0; - - // 超时相关 - protected bool _isAbort = false; - protected long _latestDownloadBytes; - protected float _latestDownloadRealtime; - protected float _tryAgainTimer; - - // 失败相关 - protected int FailedTryAgain; - - - internal DefaultDownloadFileOperation(PackageBundle bundle, DownloadFileOptions options) : base(bundle) - { - Options = options; - FailedTryAgain = options.FailedTryAgain; - } - - /// - /// 获取网络请求地址 - /// - protected string GetRequestURL() - { - // 轮流返回请求地址 - _requestCount++; - if (_requestCount % 2 == 0) - return Options.FallbackURL; - else - return Options.MainURL; - } - - /// - /// 重置请求字段 - /// - protected void ResetRequestFiled() - { - // 重置变量 - _isAbort = false; - _latestDownloadBytes = 0; - _latestDownloadRealtime = Time.realtimeSinceStartup; - DownloadProgress = 0f; - DownloadedBytes = 0; - - // 重置计时器 - if (_tryAgainTimer > 0f) - YooLogger.Warning($"Try again download : {_requestURL}"); - _tryAgainTimer = 0f; - } - - /// - /// 检测请求超时 - /// - protected void CheckRequestTimeout() - { - // 注意:在连续时间段内无新增下载数据及判定为超时 - if (_isAbort == false) - { - if (_latestDownloadBytes != DownloadedBytes) - { - _latestDownloadBytes = DownloadedBytes; - _latestDownloadRealtime = UnityEngine.Time.realtimeSinceStartup; - } - - float offset = UnityEngine.Time.realtimeSinceStartup - _latestDownloadRealtime; - if (offset > Options.Timeout) - { - YooLogger.Warning($"Download request timeout : {_requestURL}"); - if (_webRequest != null) - _webRequest.Abort(); - _isAbort = true; - } - } - } - - /// - /// 检测请求结果 - /// - protected bool CheckRequestResult() - { - HttpCode = _webRequest.responseCode; - -#if UNITY_2020_3_OR_NEWER - if (_webRequest.result != UnityWebRequest.Result.Success) - { - Error = _webRequest.error; - return false; - } - else - { - return true; - } -#else - if (_webRequest.isNetworkError || _webRequest.isHttpError) - { - Error = _webRequest.error; - return false; - } - else - { - return true; - } -#endif - } - } -} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadAssetBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadAssetBundleOperation.cs index 29f28362..a66d2fe3 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadAssetBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadAssetBundleOperation.cs @@ -2,12 +2,21 @@ namespace YooAsset { - internal abstract class DownloadAssetBundleOperation : DefaultDownloadFileOperation + internal abstract class DownloadAssetBundleOperation : AsyncOperationBase { - internal DownloadAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options) : base(bundle, options) - { - } - + /// + /// AssetBundle对象 + /// public AssetBundle Result; + + /// + /// 下载进度 + /// + public float DownloadProgress { protected set; get; } = 0; + + /// + /// 下载大小 + /// + public long DownloadedBytes { protected set; get; } = 0; } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs deleted file mode 100644 index 1df1ab0e..00000000 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadFileWrapper.cs +++ /dev/null @@ -1,71 +0,0 @@ - -namespace YooAsset -{ - internal class DownloadFileWrapper : FSDownloadFileOperation - { - private enum ESteps - { - None, - Download, - Done, - } - - private readonly FSDownloadFileOperation _downloadFileOp; - private ESteps _steps = ESteps.None; - - internal DownloadFileWrapper(FSDownloadFileOperation downloadFileOp) : base(downloadFileOp.Bundle) - { - _downloadFileOp = downloadFileOp; - } - internal override void InternalStart() - { - _steps = ESteps.Download; - } - internal override void InternalUpdate() - { - if (_steps == ESteps.None || _steps == ESteps.Done) - return; - - if (_steps == ESteps.Download) - { - if (IsWaitForAsyncComplete) - _downloadFileOp.WaitForAsyncComplete(); - - if (_downloadFileOp.Status == EOperationStatus.None) - return; - - _downloadFileOp.UpdateOperation(); - Progress = _downloadFileOp.Progress; - DownloadedBytes = _downloadFileOp.DownloadedBytes; - DownloadProgress = _downloadFileOp.DownloadProgress; - if (_downloadFileOp.IsDone == false) - return; - - _steps = ESteps.Done; - Status = _downloadFileOp.Status; - Error = _downloadFileOp.Error; - HttpCode = _downloadFileOp.HttpCode; - } - } - internal override void InternalWaitForAsyncComplete() - { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } - } - - public override void Release() - { - _downloadFileOp.Release(); - } - public override void Reference() - { - _downloadFileOp.Reference(); - } - } -} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebEncryptAssetBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebEncryptAssetBundleOperation.cs index 8c0c43c3..18aef86c 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebEncryptAssetBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebEncryptAssetBundleOperation.cs @@ -1,17 +1,33 @@ using UnityEngine; -using UnityEngine.Networking; namespace YooAsset { - internal class DownloadWebEncryptAssetBundleOperation : DownloadAssetBundleOperation + internal class DownloadEncryptAssetBundleOperation : DownloadAssetBundleOperation { + protected enum ESteps + { + None, + CreateRequest, + CheckRequest, + TryAgain, + Done, + } + + private UnityWebDataRequestOperation _unityWebDataRequestOp; + private readonly PackageBundle _bundle; + private readonly DownloadFileOptions _options; private readonly bool _checkTimeout; private readonly IWebDecryptionServices _decryptionServices; - private DownloadHandlerBuffer _downloadhandler; + + protected int _requestCount = 0; + protected float _tryAgainTimer; + protected int _failedTryAgain; private ESteps _steps = ESteps.None; - internal DownloadWebEncryptAssetBundleOperation(bool checkTimeout, IWebDecryptionServices decryptionServices, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options) + internal DownloadEncryptAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options, bool checkTimeout, IWebDecryptionServices decryptionServices) { + _bundle = bundle; + _options = options; _checkTimeout = checkTimeout; _decryptionServices = decryptionServices; } @@ -27,118 +43,87 @@ namespace YooAsset // 创建下载器 if (_steps == ESteps.CreateRequest) { - // 获取请求地址 - _requestURL = GetRequestURL(); - - // 重置变量 - ResetRequestFiled(); - - // 创建下载器 - CreateWebRequest(); + if (_decryptionServices == null) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"The {nameof(IWebDecryptionServices)} is null !"; + YooLogger.Error(Error); + return; + } + string url = GetRequestURL(); + _unityWebDataRequestOp = new UnityWebDataRequestOperation(url, _options.Timeout); + _unityWebDataRequestOp.StartOperation(); + if (_checkTimeout == false) + _unityWebDataRequestOp.DontCheckTimeout(); _steps = ESteps.CheckRequest; } // 检测下载结果 if (_steps == ESteps.CheckRequest) { - DownloadProgress = _webRequest.downloadProgress; - DownloadedBytes = (long)_webRequest.downloadedBytes; - Progress = DownloadProgress; - if (_webRequest.isDone == false) - { - if (_checkTimeout) - CheckRequestTimeout(); + _unityWebDataRequestOp.UpdateOperation(); + Progress = _unityWebDataRequestOp.Progress; + DownloadProgress = _unityWebDataRequestOp.DownloadProgress; + DownloadedBytes = _unityWebDataRequestOp.DownloadedBytes; + if (_unityWebDataRequestOp.IsDone == false) return; - } // 检查网络错误 - if (CheckRequestResult()) + if (_unityWebDataRequestOp.Status == EOperationStatus.Succeed) { - if (_decryptionServices == null) - { - _steps = ESteps.Done; - Status = EOperationStatus.Failed; - Error = $"The {nameof(IWebDecryptionServices)} is null !"; - YooLogger.Error(Error); - return; - } - - var fileData = _downloadhandler.data; - if (fileData == null || fileData.Length == 0) - { - _steps = ESteps.Done; - Status = EOperationStatus.Failed; - Error = $"The download handler data is null or empty !"; - YooLogger.Error(Error); - return; - } - - AssetBundle assetBundle = LoadEncryptedAssetBundle(fileData); + AssetBundle assetBundle = LoadEncryptedAssetBundle(_unityWebDataRequestOp.Result); if (assetBundle == null) { _steps = ESteps.Done; Status = EOperationStatus.Failed; - Error = "Download handler asset bundle object is null !"; + Error = "Failed load encrypted AssetBundle !"; } else { _steps = ESteps.Done; - Result = assetBundle; Status = EOperationStatus.Succeed; + Result = assetBundle; } } else { - _steps = ESteps.TryAgain; + if (_failedTryAgain > 0) + { + _steps = ESteps.TryAgain; + YooLogger.Warning($"Failed download : {_unityWebDataRequestOp.URL} Try again !"); + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = _unityWebDataRequestOp.Error; + YooLogger.Error(Error); + } } - - // 注意:最终释放请求器 - DisposeWebRequest(); } // 重新尝试下载 if (_steps == ESteps.TryAgain) { - if (FailedTryAgain <= 0) - { - Status = EOperationStatus.Failed; - _steps = ESteps.Done; - YooLogger.Error(Error); - return; - } - _tryAgainTimer += Time.unscaledDeltaTime; if (_tryAgainTimer > 1f) { - FailedTryAgain--; + _tryAgainTimer = 0f; + _failedTryAgain--; + Progress = 0f; + DownloadProgress = 0f; + DownloadedBytes = 0; _steps = ESteps.CreateRequest; - YooLogger.Warning(Error); } } } internal override void InternalAbort() { _steps = ESteps.Done; - DisposeWebRequest(); - } - - private void CreateWebRequest() - { - _downloadhandler = new DownloadHandlerBuffer(); - _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); - _webRequest.downloadHandler = _downloadhandler; - _webRequest.disposeDownloadHandlerOnDispose = true; - _webRequest.SendWebRequest(); - } - private void DisposeWebRequest() - { - if (_webRequest != null) - { - //注意:引擎底层会自动调用Abort方法 - _webRequest.Dispose(); - _webRequest = null; - } + if (_unityWebDataRequestOp != null) + _unityWebDataRequestOp.AbortOperation(); } /// @@ -147,11 +132,24 @@ namespace YooAsset private AssetBundle LoadEncryptedAssetBundle(byte[] fileData) { var fileInfo = new WebDecryptFileInfo(); - fileInfo.BundleName = Bundle.BundleName; - fileInfo.FileLoadCRC = Bundle.UnityCRC; + fileInfo.BundleName = _bundle.BundleName; + fileInfo.FileLoadCRC = _bundle.UnityCRC; fileInfo.FileData = fileData; var decryptResult = _decryptionServices.LoadAssetBundle(fileInfo); return decryptResult.Result; } + + /// + /// 获取网络请求地址 + /// + protected string GetRequestURL() + { + // 轮流返回请求地址 + _requestCount++; + if (_requestCount % 2 == 0) + return _options.FallbackURL; + else + return _options.MainURL; + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebNormalAssetBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebNormalAssetBundleOperation.cs index 58425012..7025c318 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebNormalAssetBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operation/Internal/DownloadWebNormalAssetBundleOperation.cs @@ -1,16 +1,33 @@ using UnityEngine; -using UnityEngine.Networking; namespace YooAsset { - internal class DownloadWebNormalAssetBundleOperation : DownloadAssetBundleOperation + internal class DownloadNormalAssetBundleOperation : DownloadAssetBundleOperation { + protected enum ESteps + { + None, + CreateRequest, + CheckRequest, + TryAgain, + Done, + } + + private UnityAssetBundleRequestOperation _unityAssetBundleRequestOp; + private readonly PackageBundle _bundle; + private readonly DownloadFileOptions _options; private readonly bool _disableUnityWebCache; - private DownloadHandlerAssetBundle _downloadhandler; + + protected int _requestCount = 0; + protected float _tryAgainTimer; + protected int _failedTryAgain; private ESteps _steps = ESteps.None; - internal DownloadWebNormalAssetBundleOperation(bool disableUnityWebCache, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options) + + internal DownloadNormalAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options, bool disableUnityWebCache) { + _bundle = bundle; + _options = options; _disableUnityWebCache = disableUnityWebCache; } internal override void InternalStart() @@ -25,120 +42,78 @@ namespace YooAsset // 创建下载器 if (_steps == ESteps.CreateRequest) { - // 获取请求地址 - _requestURL = GetRequestURL(); - - // 重置变量 - ResetRequestFiled(); - - // 创建下载器 - CreateWebRequest(); - + string url = GetRequestURL(); + _unityAssetBundleRequestOp = new UnityAssetBundleRequestOperation(_bundle, _disableUnityWebCache, url, _options.Timeout); + _unityAssetBundleRequestOp.StartOperation(); _steps = ESteps.CheckRequest; } // 检测下载结果 if (_steps == ESteps.CheckRequest) { - DownloadProgress = _webRequest.downloadProgress; - DownloadedBytes = (long)_webRequest.downloadedBytes; - Progress = DownloadProgress; - if (_webRequest.isDone == false) - { - CheckRequestTimeout(); + _unityAssetBundleRequestOp.UpdateOperation(); + Progress = _unityAssetBundleRequestOp.Progress; + DownloadedBytes = _unityAssetBundleRequestOp.DownloadedBytes; + DownloadProgress = _unityAssetBundleRequestOp.DownloadProgress; + if (_unityAssetBundleRequestOp.IsDone == false) return; - } - // 检查网络错误 - if (CheckRequestResult()) + if (_unityAssetBundleRequestOp.Status == EOperationStatus.Succeed) { - AssetBundle assetBundle = _downloadhandler.assetBundle; - if (assetBundle == null) + _steps = ESteps.Done; + Status = EOperationStatus.Succeed; + Result = _unityAssetBundleRequestOp.Result; + } + else + { + if (_failedTryAgain > 0) { - _steps = ESteps.Done; - Status = EOperationStatus.Failed; - Error = "Download handler asset bundle object is null !"; + _steps = ESteps.TryAgain; + YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; - Result = assetBundle; - Status = EOperationStatus.Succeed; + Status = EOperationStatus.Failed; + Error = _unityAssetBundleRequestOp.Error; + YooLogger.Error(Error); } } - else - { - _steps = ESteps.TryAgain; - } - - // 注意:最终释放请求器 - DisposeWebRequest(); } // 重新尝试下载 if (_steps == ESteps.TryAgain) { - if (FailedTryAgain <= 0) - { - Status = EOperationStatus.Failed; - _steps = ESteps.Done; - YooLogger.Error(Error); - return; - } - _tryAgainTimer += Time.unscaledDeltaTime; if (_tryAgainTimer > 1f) { - FailedTryAgain--; + _tryAgainTimer = 0f; + _failedTryAgain--; + Progress = 0f; + DownloadProgress = 0f; + DownloadedBytes = 0; _steps = ESteps.CreateRequest; - YooLogger.Warning(Error); } } } internal override void InternalAbort() { _steps = ESteps.Done; - DisposeWebRequest(); + if (_unityAssetBundleRequestOp != null) + _unityAssetBundleRequestOp.AbortOperation(); } - private void CreateWebRequest() + /// + /// 获取网络请求地址 + /// + protected string GetRequestURL() { - _downloadhandler = CreateWebDownloadHandler(); - _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); - _webRequest.downloadHandler = _downloadhandler; - _webRequest.disposeDownloadHandlerOnDispose = true; - _webRequest.SendWebRequest(); - } - private void DisposeWebRequest() - { - if (_webRequest != null) - { - //注意:引擎底层会自动调用Abort方法 - _webRequest.Dispose(); - _webRequest = null; - } - } - private DownloadHandlerAssetBundle CreateWebDownloadHandler() - { - if (_disableUnityWebCache) - { - var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, Bundle.UnityCRC); -#if UNITY_2020_3_OR_NEWER - downloadhandler.autoLoadAssetBundle = false; -#endif - return downloadhandler; - } + // 轮流返回请求地址 + _requestCount++; + if (_requestCount % 2 == 0) + return _options.FallbackURL; else - { - // 注意:优先从浏览器缓存里获取文件 - // The file hash defining the version of the asset bundle. - Hash128 fileHash = Hash128.Parse(Bundle.FileHash); - var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, fileHash, Bundle.UnityCRC); -#if UNITY_2020_3_OR_NEWER - downloadhandler.autoLoadAssetBundle = false; -#endif - return downloadhandler; - } + return _options.MainURL; } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs index 3433c7f6..12d604e6 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs @@ -366,7 +366,7 @@ namespace YooAsset foreach (var downloader in _downloaders) { - downloader.Release(); + downloader.AbortOperation(); } } }