diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityAssetBundleRequestOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityAssetBundleRequestOperation.cs new file mode 100644 index 00000000..25d98ebe --- /dev/null +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityAssetBundleRequestOperation.cs @@ -0,0 +1,122 @@ +using UnityEngine.Networking; +using UnityEngine; + +namespace YooAsset +{ + internal class UnityAssetBundleRequestOperation : UnityWebRequestOperation + { + protected enum ESteps + { + None, + CreateRequest, + Download, + Done, + } + + private UnityWebRequestAsyncOperation _requestOperation; + private DownloadHandlerAssetBundle _downloadhandler; + private readonly PackageBundle _packageBundle; + private readonly bool _disableUnityWebCache; + private ESteps _steps = ESteps.None; + + /// + /// 请求结果 + /// + public AssetBundle Result { private set; get; } + + internal UnityAssetBundleRequestOperation(PackageBundle packageBundle, bool disableUnityWebCache, string url, int timeout = 60) : base(url, timeout) + { + _packageBundle = packageBundle; + _disableUnityWebCache = disableUnityWebCache; + } + internal override void InternalStart() + { + _steps = ESteps.CreateRequest; + } + internal override void InternalUpdate() + { + if (_steps == ESteps.None || _steps == ESteps.Done) + return; + + if (_steps == ESteps.CreateRequest) + { + ResetTimeout(); + CreateWebRequest(); + _steps = ESteps.Download; + } + + if (_steps == ESteps.Download) + { + DownloadProgress = _webRequest.downloadProgress; + DownloadedBytes = (long)_webRequest.downloadedBytes; + Progress = _requestOperation.progress; + if (_requestOperation.isDone == false) + { + CheckRequestTimeout(); + return; + } + + if (CheckRequestResult()) + { + AssetBundle assetBundle = _downloadhandler.assetBundle; + if (assetBundle == null) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"URL : {_requestURL} Download handler asset bundle object is null !"; + } + else + { + _steps = ESteps.Done; + Result = assetBundle; + Status = EOperationStatus.Succeed; + } + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + } + + // 注意:最终释放请求器 + DisposeRequest(); + } + } + internal override void InternalAbort() + { + _steps = ESteps.Done; + DisposeRequest(); + } + + private void CreateWebRequest() + { + _downloadhandler = CreateWebDownloadHandler(); + _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); + _webRequest.downloadHandler = _downloadhandler; + _webRequest.disposeDownloadHandlerOnDispose = true; + _requestOperation = _webRequest.SendWebRequest(); + } + private DownloadHandlerAssetBundle CreateWebDownloadHandler() + { + if (_disableUnityWebCache) + { + var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, _packageBundle.UnityCRC); +#if UNITY_2020_3_OR_NEWER + downloadhandler.autoLoadAssetBundle = false; +#endif + return downloadhandler; + } + else + { + // 注意:优先从浏览器缓存里获取文件 + // The file hash defining the version of the asset bundle. + Hash128 fileHash = Hash128.Parse(_packageBundle.FileHash); + var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, fileHash, _packageBundle.UnityCRC); +#if UNITY_2020_3_OR_NEWER + downloadhandler.autoLoadAssetBundle = false; +#endif + return downloadhandler; + } + } + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityAssetBundleRequestOperation.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityAssetBundleRequestOperation.cs.meta new file mode 100644 index 00000000..2f3a8d5a --- /dev/null +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityAssetBundleRequestOperation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e01cc308d7179a34281087fafe455b42 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebDataRequestOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebDataRequestOperation.cs index 3609cbdd..d7635b5e 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebDataRequestOperation.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebDataRequestOperation.cs @@ -5,7 +5,17 @@ namespace YooAsset { internal class UnityWebDataRequestOperation : UnityWebRequestOperation { + protected enum ESteps + { + None, + CreateRequest, + Download, + Done, + } + private UnityWebRequestAsyncOperation _requestOperation; + private bool _checkTimeout = true; + private ESteps _steps = ESteps.None; /// /// 请求结果 @@ -27,27 +37,38 @@ namespace YooAsset if (_steps == ESteps.CreateRequest) { - _latestDownloadBytes = 0; - _latestDownloadRealtime = Time.realtimeSinceStartup; - + ResetTimeout(); CreateWebRequest(); _steps = ESteps.Download; } if (_steps == ESteps.Download) { + DownloadProgress = _webRequest.downloadProgress; + DownloadedBytes = (long)_webRequest.downloadedBytes; Progress = _requestOperation.progress; if (_requestOperation.isDone == false) { - CheckRequestTimeout(); + if (_checkTimeout) + CheckRequestTimeout(); return; } if (CheckRequestResult()) { - _steps = ESteps.Done; - Result = _webRequest.downloadHandler.data; - Status = EOperationStatus.Succeed; + var fileData = _webRequest.downloadHandler.data; + if (fileData == null || fileData.Length == 0) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"URL : {_requestURL} Download handler data is null or empty !"; + } + else + { + _steps = ESteps.Done; + Result = fileData; + Status = EOperationStatus.Succeed; + } } else { @@ -65,6 +86,14 @@ namespace YooAsset DisposeRequest(); } + /// + /// 不检测超时 + /// + public void DontCheckTimeout() + { + _checkTimeout = false; + } + private void CreateWebRequest() { _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebFileRequestOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebFileRequestOperation.cs index 2ecffca7..d81d2c7b 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebFileRequestOperation.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebFileRequestOperation.cs @@ -5,8 +5,18 @@ namespace YooAsset { internal class UnityWebFileRequestOperation : UnityWebRequestOperation { + protected enum ESteps + { + None, + CreateRequest, + Download, + Done, + } + private UnityWebRequestAsyncOperation _requestOperation; private readonly string _fileSavePath; + private ESteps _steps = ESteps.None; + internal UnityWebFileRequestOperation(string url, string fileSavePath, int timeout = 60) : base(url, timeout) { @@ -23,15 +33,15 @@ namespace YooAsset if (_steps == ESteps.CreateRequest) { - _latestDownloadBytes = 0; - _latestDownloadRealtime = Time.realtimeSinceStartup; - + ResetTimeout(); CreateWebRequest(); _steps = ESteps.Download; } if (_steps == ESteps.Download) { + DownloadProgress = _webRequest.downloadProgress; + DownloadedBytes = (long)_webRequest.downloadedBytes; Progress = _requestOperation.progress; if (_requestOperation.isDone == false) { diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebRequestOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebRequestOperation.cs index c7b7c9bf..4db73f98 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebRequestOperation.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebRequestOperation.cs @@ -1,6 +1,4 @@ using System; -using System.Collections; -using System.Collections.Concurrent; using UnityEngine.Networking; using UnityEngine; @@ -8,24 +6,33 @@ namespace YooAsset { internal abstract class UnityWebRequestOperation : AsyncOperationBase { - protected enum ESteps - { - None, - CreateRequest, - Download, - Done, - } - protected UnityWebRequest _webRequest; protected readonly string _requestURL; - protected ESteps _steps = ESteps.None; // 超时相关 - protected readonly float _timeout; - protected ulong _latestDownloadBytes; - protected float _latestDownloadRealtime; + private readonly float _timeout; + private ulong _latestDownloadBytes; + private float _latestDownloadRealtime; private bool _isAbort = false; + /// + /// HTTP返回码 + /// + public long HttpCode { private set; get; } + + /// + /// 当前下载的字节数 + /// + public long DownloadedBytes { protected set; get; } + + /// + /// 当前下载进度(0f - 1f) + /// + public float DownloadProgress { protected set; get; } + + /// + /// 请求的URL地址 + /// public string URL { get { return _requestURL; } @@ -44,20 +51,33 @@ namespace YooAsset { if (_webRequest != null) { + //注意:引擎底层会自动调用Abort方法 _webRequest.Dispose(); _webRequest = null; } } + /// + /// 重置超时计时 + /// + protected void ResetTimeout() + { + _latestDownloadBytes = 0; + _latestDownloadRealtime = Time.realtimeSinceStartup; + } + /// /// 检测超时 /// protected void CheckRequestTimeout() { + if (_webRequest.isDone) + return; + // 注意:在连续时间段内无新增下载数据及判定为超时 if (_isAbort == false) { - if ( _latestDownloadBytes != _webRequest.downloadedBytes) + if (_latestDownloadBytes != _webRequest.downloadedBytes) { _latestDownloadBytes = _webRequest.downloadedBytes; _latestDownloadRealtime = Time.realtimeSinceStartup; @@ -66,6 +86,7 @@ namespace YooAsset float offset = Time.realtimeSinceStartup - _latestDownloadRealtime; if (offset > _timeout) { + YooLogger.Warning($"Web request timeout : {_requestURL}"); _webRequest.Abort(); _isAbort = true; } @@ -77,6 +98,8 @@ namespace YooAsset /// protected bool CheckRequestResult() { + HttpCode = _webRequest.responseCode; + #if UNITY_2020_3_OR_NEWER if (_webRequest.result != UnityWebRequest.Result.Success) { diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebTextRequestOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebTextRequestOperation.cs index d0045b18..8395d10a 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebTextRequestOperation.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operation/Internal/UnityWebTextRequestOperation.cs @@ -5,7 +5,16 @@ namespace YooAsset { internal class UnityWebTextRequestOperation : UnityWebRequestOperation { + protected enum ESteps + { + None, + CreateRequest, + Download, + Done, + } + private UnityWebRequestAsyncOperation _requestOperation; + private ESteps _steps = ESteps.None; /// /// 请求结果 @@ -27,15 +36,15 @@ namespace YooAsset if (_steps == ESteps.CreateRequest) { - _latestDownloadBytes = 0; - _latestDownloadRealtime = Time.realtimeSinceStartup; - + ResetTimeout(); CreateWebRequest(); _steps = ESteps.Download; } if (_steps == ESteps.Download) { + DownloadProgress = _webRequest.downloadProgress; + DownloadedBytes = (long)_webRequest.downloadedBytes; Progress = _requestOperation.progress; if (_requestOperation.isDone == false) { @@ -45,9 +54,19 @@ namespace YooAsset if (CheckRequestResult()) { - _steps = ESteps.Done; - Result = _webRequest.downloadHandler.text; - Status = EOperationStatus.Succeed; + var fileText = _webRequest.downloadHandler.text; + if (string.IsNullOrEmpty(fileText)) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"URL : {_requestURL} Download handler text is null or empty !"; + } + else + { + _steps = ESteps.Done; + Result = fileText; + Status = EOperationStatus.Succeed; + } } else {