mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-24 17:50:15 +00:00
refactor : 重构网络下载模块
新增通用下载接口,扩展了默认的Unity引擎下载器
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8f060786f8775b4a82cc3f55d9135e2
|
||||
guid: bb70e2274ce5a5d419cfbd7212efdf4a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest 下载后台
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 基于 Unity 内置 UnityWebRequest 实现的下载后台。
|
||||
/// 支持自定义 UnityWebRequest 创建方式,例如添加证书验证、代理设置等。
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestBackend : IDownloadBackend
|
||||
{
|
||||
private readonly UnityWebRequestDelegate _webRequestCreator;
|
||||
|
||||
/// <summary>
|
||||
/// 后端名称
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return nameof(UnityWebRequestBackend); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest 下载后端(使用默认创建方式)
|
||||
/// </summary>
|
||||
public UnityWebRequestBackend() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest 下载后端
|
||||
/// </summary>
|
||||
/// <param name="webRequestCreator">
|
||||
/// 自定义 UnityWebRequest 创建委托(可选)。
|
||||
/// 如果为 null,则使用默认的 UnityWebRequest 构造方式。
|
||||
/// </param>
|
||||
public UnityWebRequestBackend(UnityWebRequestDelegate webRequestCreator)
|
||||
{
|
||||
_webRequestCreator = webRequestCreator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 驱动更新
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// UnityWebRequest 由 Unity 引擎自动驱动,无需额外更新。
|
||||
/// </remarks>
|
||||
public void Update()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// 无需释放资源
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 HEAD 请求
|
||||
/// </summary>
|
||||
public IDownloadHeadRequest CreateHeadRequest(DownloadDataRequestArgs args)
|
||||
{
|
||||
return new UnityWebRequestHeadDownloader(args, _webRequestCreator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件下载请求
|
||||
/// </summary>
|
||||
public IDownloadFileRequest CreateFileRequest(DownloadFileRequestArgs args)
|
||||
{
|
||||
return new UnityWebRequestFileDownloader(args, _webRequestCreator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建字节下载请求
|
||||
/// </summary>
|
||||
public IDownloadBytesRequest CreateBytesRequest(DownloadDataRequestArgs args)
|
||||
{
|
||||
return new UnityWebRequestBytesDownloader(args, _webRequestCreator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文本下载请求
|
||||
/// </summary>
|
||||
public IDownloadTextRequest CreateTextRequest(DownloadDataRequestArgs args)
|
||||
{
|
||||
return new UnityWebRequestTextDownloader(args, _webRequestCreator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 AssetBundle 下载请求
|
||||
/// </summary>
|
||||
public IDownloadAssetBundleRequest CreateAssetBundleRequest(DownloadAssetBundleRequestArgs args)
|
||||
{
|
||||
return new UnityWebRequestAssetBundleDownloader(args, _webRequestCreator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建模拟下载请求
|
||||
/// </summary>
|
||||
public IDownloadFileRequest CreateSimulateRequest(DownloadSimulateRequestArgs args)
|
||||
{
|
||||
return new VirtualFileDownloader(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 932e4c4574244dac8c27d9ddc156f8ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d30af9086de4fb282c2cdd3d26244c0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest AssetBundle 下载器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 下载并加载 Unity AssetBundle 资源包。
|
||||
/// 支持 Unity 内置缓存机制和 CRC 校验。
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestAssetBundleDownloader : UnityWebRequestDownloaderBase, IDownloadAssetBundleRequest
|
||||
{
|
||||
private readonly DownloadAssetBundleRequestArgs _args;
|
||||
private DownloadHandlerAssetBundle _downloadHandler;
|
||||
|
||||
/// <summary>
|
||||
/// 下载结果(AssetBundle 对象)
|
||||
/// </summary>
|
||||
public AssetBundle Result { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造 AssetBundle 下载器
|
||||
/// </summary>
|
||||
/// <param name="args">AssetBundle 下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestAssetBundleDownloader(DownloadAssetBundleRequestArgs args, UnityWebRequestDelegate webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest
|
||||
/// </summary>
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
_downloadHandler = CreateAssetBundleDownloadHandler();
|
||||
_webRequest = CreateUnityWebRequestGet(URL);
|
||||
_webRequest.downloadHandler = _downloadHandler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
ApplyRequestOptions(_args.Timeout, _args.WatchdogTime, _args.Headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
{
|
||||
AssetBundle assetBundle = _downloadHandler.assetBundle;
|
||||
if (assetBundle == null)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] URL: {URL} - AssetBundle object is null";
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = assetBundle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 AssetBundle 下载处理器
|
||||
/// </summary>
|
||||
private DownloadHandlerAssetBundle CreateAssetBundleDownloadHandler()
|
||||
{
|
||||
DownloadHandlerAssetBundle handler;
|
||||
|
||||
if (_args.DisableUnityWebCache)
|
||||
{
|
||||
// 禁用 Unity 缓存
|
||||
handler = new DownloadHandlerAssetBundle(URL, _args.UnityCRC);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 使用 Unity 缓存(需要 FileHash)
|
||||
// The file hash defining the version of the asset bundle.
|
||||
Hash128 fileHash = Hash128.Parse(_args.FileHash);
|
||||
handler = new DownloadHandlerAssetBundle(URL, fileHash, _args.UnityCRC);
|
||||
}
|
||||
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
// 禁用自动加载,允许手动控制加载时机
|
||||
handler.autoLoadAssetBundle = false;
|
||||
#endif
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e01cc308d7179a34281087fafe455b42
|
||||
guid: 6f635344c08e2b04295a108c2bcc6a40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest 字节下载器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将下载内容保存到内存中的字节数组。
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestBytesDownloader : UnityWebRequestDownloaderBase, IDownloadBytesRequest
|
||||
{
|
||||
private readonly DownloadDataRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
/// 下载结果(字节数组)
|
||||
/// </summary>
|
||||
public byte[] Result { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造字节数组下载器
|
||||
/// </summary>
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestBytesDownloader(DownloadDataRequestArgs args, UnityWebRequestDelegate webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest
|
||||
/// </summary>
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
var handler = new DownloadHandlerBuffer();
|
||||
_webRequest = CreateUnityWebRequestGet(URL);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
ApplyRequestOptions(_args.Timeout, _args.WatchdogTime, _args.Headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
{
|
||||
var fileData = _webRequest.downloadHandler.data;
|
||||
if (fileData == null || fileData.Length == 0)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] URL: {URL} - Download bytes data is null or empty !";
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = fileData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6602c4be2ef295546b7bbb328de8fb0c
|
||||
guid: 38884a96e8c2df74082d4e059e2e73ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,290 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest 下载器基类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 封装 UnityWebRequest 的通用下载逻辑,包括状态管理、进度追踪等。
|
||||
/// 子类只需实现 CreateWebRequest 方法来创建特定类型的下载请求。
|
||||
/// </remarks>
|
||||
internal abstract class UnityWebRequestDownloaderBase : IDownloadRequest
|
||||
{
|
||||
private readonly UnityWebRequestDelegate _webRequestCreator;
|
||||
protected UnityWebRequest _webRequest;
|
||||
|
||||
// 看门狗相关
|
||||
private int _watchdogTime = 0;
|
||||
private bool _watchdogAborted = false;
|
||||
private long _lastDownloadBytes = -1;
|
||||
private double _lastGetDataTime;
|
||||
|
||||
#region 接口实现
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public string URL { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否完成
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 每次调用都会主动轮询请求 PollingRequest
|
||||
/// </remarks>
|
||||
public bool IsDone
|
||||
{
|
||||
get
|
||||
{
|
||||
PollingRequest();
|
||||
return Status == EDownloadRequestStatus.Succeed
|
||||
|| Status == EDownloadRequestStatus.Failed
|
||||
|| Status == EDownloadRequestStatus.Aborted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求状态
|
||||
/// </summary>
|
||||
public EDownloadRequestStatus Status { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前下载进度(0f - 1f)
|
||||
/// </summary>
|
||||
public float DownloadProgress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前请求已接收的字节数
|
||||
/// </summary>
|
||||
public long DownloadedBytes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 返回码
|
||||
/// </summary>
|
||||
public long HttpCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string Error { get; protected set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 构造下载器基类
|
||||
/// </summary>
|
||||
/// <param name="url">请求地址</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
protected UnityWebRequestDownloaderBase(string url, UnityWebRequestDelegate webRequestCreator)
|
||||
{
|
||||
URL = url;
|
||||
_webRequestCreator = webRequestCreator;
|
||||
Status = EDownloadRequestStatus.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发起请求
|
||||
/// </summary>
|
||||
public void SendRequest()
|
||||
{
|
||||
if (Status == EDownloadRequestStatus.None)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Running;
|
||||
|
||||
try
|
||||
{
|
||||
CreateWebRequest();
|
||||
|
||||
if (_webRequest == null)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] Created web request is null.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] Failed to create web request : {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询请求
|
||||
/// </summary>
|
||||
public void PollingRequest()
|
||||
{
|
||||
if (Status != EDownloadRequestStatus.Running)
|
||||
return;
|
||||
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
|
||||
CheckWatchdog();
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
HttpCode = _webRequest.responseCode;
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
bool isSuccess = _webRequest.result == UnityWebRequest.Result.Success;
|
||||
#else
|
||||
bool isSuccess = !_webRequest.isNetworkError && !_webRequest.isHttpError;
|
||||
#endif
|
||||
|
||||
if (isSuccess)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Succeed;
|
||||
OnRequestSucceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] URL: {URL} - 错误: {_webRequest.error}";
|
||||
OnRequestFailed();
|
||||
}
|
||||
|
||||
// 完成后释放
|
||||
DisposeWebRequest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中止请求
|
||||
/// </summary>
|
||||
public void AbortRequest()
|
||||
{
|
||||
if (Status == EDownloadRequestStatus.None || Status == EDownloadRequestStatus.Running)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Aborted;
|
||||
if (_webRequest != null)
|
||||
_webRequest.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeWebRequest();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest(子类实现)
|
||||
/// </summary>
|
||||
protected abstract void CreateWebRequest();
|
||||
|
||||
/// <summary>
|
||||
/// 请求成功时的回调(子类可重写)
|
||||
/// </summary>
|
||||
protected virtual void OnRequestSucceed()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求失败时的回调(子类可重写)
|
||||
/// </summary>
|
||||
protected virtual void OnRequestFailed()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest GET 请求
|
||||
/// </summary>
|
||||
/// <param name="requestUrl">请求地址</param>
|
||||
/// <returns>UnityWebRequest 实例</returns>
|
||||
protected UnityWebRequest CreateUnityWebRequestGet(string requestUrl)
|
||||
{
|
||||
if (_webRequestCreator != null)
|
||||
return _webRequestCreator.Invoke(requestUrl);
|
||||
|
||||
return new UnityWebRequest(requestUrl, UnityWebRequest.kHttpVerbGET);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest HEAD 请求
|
||||
/// </summary>
|
||||
/// <param name="requestUrl">请求地址</param>
|
||||
/// <returns>UnityWebRequest 实例</returns>
|
||||
protected UnityWebRequest CreateUnityWebRequestHead(string requestUrl)
|
||||
{
|
||||
return new UnityWebRequest(requestUrl, UnityWebRequest.kHttpVerbHEAD);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用通用请求参数
|
||||
/// </summary>
|
||||
protected void ApplyRequestOptions(int timeout, int watchdogTime, Dictionary<string, string> headers)
|
||||
{
|
||||
if (_webRequest == null)
|
||||
throw new YooInternalException("Web request is null !");
|
||||
|
||||
// 设置看门狗超时时间
|
||||
_watchdogTime = watchdogTime;
|
||||
|
||||
// 设置响应的超时时间
|
||||
if (timeout > 0)
|
||||
_webRequest.timeout = timeout;
|
||||
|
||||
// 设置响应头
|
||||
if (headers != null)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
_webRequest.SetRequestHeader(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测看门狗
|
||||
/// </summary>
|
||||
private void CheckWatchdog()
|
||||
{
|
||||
if (_watchdogTime == 0)
|
||||
return;
|
||||
if (_watchdogAborted)
|
||||
return;
|
||||
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
double realtimeSinceStartup = UnityEngine.Time.realtimeSinceStartupAsDouble;
|
||||
#else
|
||||
double realtimeSinceStartup = UnityEngine.Time.realtimeSinceStartup;
|
||||
#endif
|
||||
|
||||
if (DownloadedBytes != _lastDownloadBytes)
|
||||
{
|
||||
_lastDownloadBytes = DownloadedBytes;
|
||||
_lastGetDataTime = realtimeSinceStartup;
|
||||
}
|
||||
else
|
||||
{
|
||||
double deltaTime = realtimeSinceStartup - _lastGetDataTime;
|
||||
if (deltaTime > _watchdogTime)
|
||||
{
|
||||
_watchdogAborted = true;
|
||||
AbortRequest(); //看门狗终止网络请求
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
//注意:引擎底层会自动调用Abort方法
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e71e850eded0da43906cb4f7cb75629
|
||||
guid: 76b0712524ed69542914db8e44fa64fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest 文件下载器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将下载内容保存到本地文件,支持断点续传和追加写入。
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestFileDownloader : UnityWebRequestDownloaderBase, IDownloadFileRequest
|
||||
{
|
||||
private readonly DownloadFileRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
/// 文件保存路径
|
||||
/// </summary>
|
||||
public string SavePath
|
||||
{
|
||||
get { return _args.SavePath; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造文件下载器
|
||||
/// </summary>
|
||||
/// <param name="args">文件下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestFileDownloader(DownloadFileRequestArgs args, UnityWebRequestDelegate webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest
|
||||
/// </summary>
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
var handler = new DownloadHandlerFile(_args.SavePath, _args.AppendToFile);
|
||||
handler.removeFileOnAbort = _args.RemoveFileOnAbort;
|
||||
|
||||
_webRequest = CreateUnityWebRequestGet(URL);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
|
||||
// 断点续传:设置 Range 请求头
|
||||
if (_args.ResumeFromBytes > 0)
|
||||
{
|
||||
_webRequest.SetRequestHeader("Range", $"bytes={_args.ResumeFromBytes}-");
|
||||
}
|
||||
|
||||
ApplyRequestOptions(_args.Timeout, _args.WatchdogTime, _args.Headers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 375d88bcf5b9a6146adaf98ceb5369f8
|
||||
guid: 101a4be1bb0a85c4d84ecbf3e74f89e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest HEAD 请求下载器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅获取响应头信息,不下载实际内容。
|
||||
/// 用于检查资源是否存在、获取资源大小、检查缓存有效性等场景。
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestHeadDownloader : UnityWebRequestDownloaderBase, IDownloadHeadRequest
|
||||
{
|
||||
// 注意:缓存响应头(因为 WebRequest 释放后无法获取)
|
||||
private Dictionary<string, string> _cachedResponseHeaders;
|
||||
private readonly DownloadDataRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
/// 获取 ETag 响应头
|
||||
/// </summary>
|
||||
public string ETag
|
||||
{
|
||||
get { return GetResponseHeader("ETag"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Last-Modified 响应头
|
||||
/// </summary>
|
||||
public string LastModified
|
||||
{
|
||||
get { return GetResponseHeader("Last-Modified"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Content-Type 响应头
|
||||
/// </summary>
|
||||
public string ContentType
|
||||
{
|
||||
get { return GetResponseHeader("Content-Type"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Content-Length 响应头
|
||||
/// 预期下载的总字节数
|
||||
/// </summary>
|
||||
public long ContentLength
|
||||
{
|
||||
get
|
||||
{
|
||||
string contentLengthStr = GetResponseHeader("Content-Length");
|
||||
if (string.IsNullOrEmpty(contentLengthStr))
|
||||
return -1;
|
||||
|
||||
if (long.TryParse(contentLengthStr, out long contentLength))
|
||||
{
|
||||
return contentLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造 HEAD 请求下载器
|
||||
/// </summary>
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestHeadDownloader(DownloadDataRequestArgs args, UnityWebRequestDelegate webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取响应头信息
|
||||
/// </summary>
|
||||
/// <param name="name">响应头名称(不区分大小写)</param>
|
||||
/// <returns>响应头的值,如果不存在或请求未完成则返回 null</returns>
|
||||
public string GetResponseHeader(string name)
|
||||
{
|
||||
if (_cachedResponseHeaders == null)
|
||||
return null;
|
||||
|
||||
// 注意:UnityWebRequest 的响应头 key 是小写的
|
||||
string lowerName = name.ToLowerInvariant();
|
||||
if (_cachedResponseHeaders.TryGetValue(lowerName, out string value))
|
||||
return value;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest
|
||||
/// </summary>
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
_webRequest = CreateUnityWebRequestHead(URL);
|
||||
_webRequest.downloadHandler = null; // HEAD 请求不需要 DownloadHandler
|
||||
ApplyRequestOptions(_args.Timeout, _args.WatchdogTime, _args.Headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
{
|
||||
var headers = _webRequest.GetResponseHeaders();
|
||||
if (headers != null)
|
||||
{
|
||||
_cachedResponseHeaders = new Dictionary<string, string>(headers.Count, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var kvp in headers)
|
||||
{
|
||||
string name = kvp.Key.ToLowerInvariant();
|
||||
string value = kvp.Value;
|
||||
_cachedResponseHeaders[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ed243d707130394aa85e20dee876d8e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityWebRequest 文本下载器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将下载内容解析为 UTF-8 文本字符串。
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestTextDownloader : UnityWebRequestDownloaderBase, IDownloadTextRequest
|
||||
{
|
||||
private readonly DownloadDataRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
/// 下载结果(文本字符串)
|
||||
/// </summary>
|
||||
public string Result { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造文本下载器
|
||||
/// </summary>
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestTextDownloader(DownloadDataRequestArgs args, UnityWebRequestDelegate webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 UnityWebRequest
|
||||
/// </summary>
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
var handler = new DownloadHandlerBuffer();
|
||||
_webRequest = CreateUnityWebRequestGet(URL);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
ApplyRequestOptions(_args.Timeout, _args.WatchdogTime, _args.Headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
{
|
||||
var fileText = _webRequest.downloadHandler.text;
|
||||
if (string.IsNullOrEmpty(fileText))
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] URL: {URL} - Download text data is null or empty";
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = fileText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b0bd3024ca5bae4dbdc05c7af7479df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 模拟下载器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于编辑器模式下模拟下载进度,不进行实际网络请求。
|
||||
/// 根据配置的下载速度模拟进度变化。
|
||||
/// </remarks>
|
||||
internal sealed class VirtualFileDownloader : IDownloadFileRequest
|
||||
{
|
||||
private readonly DownloadSimulateRequestArgs _args;
|
||||
private double _lastUpdateTime;
|
||||
|
||||
/// <summary>
|
||||
/// 文件保存路径(模拟下载不需要)
|
||||
/// </summary>
|
||||
public string SavePath
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
#region 接口实现
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public string URL { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否完成
|
||||
/// </summary>
|
||||
public bool IsDone
|
||||
{
|
||||
get
|
||||
{
|
||||
PollingRequest();
|
||||
return Status == EDownloadRequestStatus.Succeed
|
||||
|| Status == EDownloadRequestStatus.Failed
|
||||
|| Status == EDownloadRequestStatus.Aborted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求状态
|
||||
/// </summary>
|
||||
public EDownloadRequestStatus Status { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前下载进度(0f - 1f)
|
||||
/// </summary>
|
||||
public float DownloadProgress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前请求已接收的字节数
|
||||
/// </summary>
|
||||
public long DownloadedBytes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 返回码(模拟固定返回 200)
|
||||
/// </summary>
|
||||
public long HttpCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 构造模拟下载器
|
||||
/// </summary>
|
||||
/// <param name="args">模拟下载参数</param>
|
||||
public VirtualFileDownloader(DownloadSimulateRequestArgs args)
|
||||
{
|
||||
_args = args;
|
||||
Status = EDownloadRequestStatus.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发起请求
|
||||
/// </summary>
|
||||
public void SendRequest()
|
||||
{
|
||||
if (Status == EDownloadRequestStatus.None)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Running;
|
||||
_lastUpdateTime = GetUnityEngineRealtime();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询请求
|
||||
/// </summary>
|
||||
public void PollingRequest()
|
||||
{
|
||||
if (Status != EDownloadRequestStatus.Running)
|
||||
return;
|
||||
|
||||
double currentTime = GetUnityEngineRealtime();
|
||||
double deltaTime = currentTime - _lastUpdateTime;
|
||||
_lastUpdateTime = currentTime;
|
||||
|
||||
// 计算本帧下载的字节数
|
||||
long downloadBytes = (long)(_args.DownloadSpeed * deltaTime);
|
||||
DownloadedBytes += downloadBytes;
|
||||
|
||||
if (_args.FileSize > 0)
|
||||
DownloadProgress = (float)DownloadedBytes / _args.FileSize;
|
||||
|
||||
// 检查是否完成
|
||||
if (DownloadedBytes >= _args.FileSize)
|
||||
{
|
||||
HttpCode = 200;
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _args.FileSize;
|
||||
Status = EDownloadRequestStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中止请求
|
||||
/// </summary>
|
||||
public void AbortRequest()
|
||||
{
|
||||
if (Status == EDownloadRequestStatus.None || Status == EDownloadRequestStatus.Running)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Aborted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private double GetUnityEngineRealtime()
|
||||
{
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
return UnityEngine.Time.realtimeSinceStartupAsDouble;
|
||||
#else
|
||||
return = UnityEngine.Time.realtimeSinceStartup;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84daeb1559aadff40b5b5aa5c81d7d64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,118 +0,0 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载器结束
|
||||
/// </summary>
|
||||
public struct DownloaderFinishData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public bool Succeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的更新数据
|
||||
/// </summary>
|
||||
public struct DownloadUpdateData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度 (0-1f)
|
||||
/// </summary>
|
||||
public float Progress;
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件总数
|
||||
/// </summary>
|
||||
public int TotalDownloadCount;
|
||||
|
||||
/// <summary>
|
||||
/// 当前完成的下载文件数量
|
||||
/// </summary>
|
||||
public int CurrentDownloadCount;
|
||||
|
||||
/// <summary>
|
||||
/// 下载数据总大小(单位:字节)
|
||||
/// </summary>
|
||||
public long TotalDownloadBytes;
|
||||
|
||||
/// <summary>
|
||||
/// 当前完成的下载数据大小(单位:字节)
|
||||
/// </summary>
|
||||
public long CurrentDownloadBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的错误数据
|
||||
/// </summary>
|
||||
public struct DownloadErrorData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载失败的文件名称
|
||||
/// </summary>
|
||||
public string FileName;
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string ErrorInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的文件数据
|
||||
/// </summary>
|
||||
public struct DownloadFileData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载的文件名称
|
||||
/// </summary>
|
||||
public string FileName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载的文件大小
|
||||
/// </summary>
|
||||
public long FileSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入文件的信息
|
||||
/// </summary>
|
||||
public struct ImportFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 本地文件路径
|
||||
/// </summary>
|
||||
public string FilePath;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包GUID
|
||||
/// </summary>
|
||||
public string BundleGUID;
|
||||
}
|
||||
}
|
||||
443
Assets/YooAsset/Runtime/DownloadSystem/DownloadSystemDefine.cs
Normal file
443
Assets/YooAsset/Runtime/DownloadSystem/DownloadSystemDefine.cs
Normal file
@@ -0,0 +1,443 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载器结束
|
||||
/// </summary>
|
||||
public struct DownloaderFinishData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public bool Succeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的更新数据
|
||||
/// </summary>
|
||||
public struct DownloadUpdateData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度 (0-1f)
|
||||
/// </summary>
|
||||
public float Progress;
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件总数
|
||||
/// </summary>
|
||||
public int TotalDownloadCount;
|
||||
|
||||
/// <summary>
|
||||
/// 当前完成的下载文件数量
|
||||
/// </summary>
|
||||
public int CurrentDownloadCount;
|
||||
|
||||
/// <summary>
|
||||
/// 下载数据总大小(单位:字节)
|
||||
/// </summary>
|
||||
public long TotalDownloadBytes;
|
||||
|
||||
/// <summary>
|
||||
/// 当前完成的下载数据大小(单位:字节)
|
||||
/// </summary>
|
||||
public long CurrentDownloadBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的错误数据
|
||||
/// </summary>
|
||||
public struct DownloadErrorData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载失败的文件名称
|
||||
/// </summary>
|
||||
public string FileName;
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string ErrorInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的文件数据
|
||||
/// </summary>
|
||||
public struct DownloadFileData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载的文件名称
|
||||
/// </summary>
|
||||
public string FileName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载的文件大小
|
||||
/// </summary>
|
||||
public long FileSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入文件的信息
|
||||
/// </summary>
|
||||
public struct ImportFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 本地文件路径
|
||||
/// </summary>
|
||||
public string FilePath;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包GUID
|
||||
/// </summary>
|
||||
public string BundleGUID;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 下载请求状态
|
||||
/// </summary>
|
||||
internal enum EDownloadRequestStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 未开始
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 进行中
|
||||
/// </summary>
|
||||
Running,
|
||||
|
||||
/// <summary>
|
||||
/// 已成功
|
||||
/// </summary>
|
||||
Succeed,
|
||||
|
||||
/// <summary>
|
||||
/// 已失败
|
||||
/// </summary>
|
||||
Failed,
|
||||
|
||||
/// <summary>
|
||||
/// 已中止
|
||||
/// </summary>
|
||||
Aborted,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件下载请求参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于将下载内容保存到本地文件的请求配置。
|
||||
/// 支持断点续传和追加写入模式。
|
||||
/// </remarks>
|
||||
internal struct DownloadFileRequestArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当 Timeout 设置为 0 时,不应用超时。
|
||||
/// 设置的超时值可能应用于Android上的每个URL重定向,这可能会导致响应时间增加。
|
||||
/// </remarks>
|
||||
public readonly int Timeout;
|
||||
|
||||
/// <summary>
|
||||
/// 看门狗超时时间(单位:秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于监控下载任务的数据接收情况。
|
||||
/// 规则说明:
|
||||
/// 1. 当设置值为 0 时,表示禁用看门狗监控。
|
||||
/// 2. 每次接收到下载数据时,看门狗计时器会重置。
|
||||
/// 3. 若在设定的时间范围内未收到任何数据,任务将被自动终止。
|
||||
/// </remarks>
|
||||
public readonly int WatchdogTime;
|
||||
|
||||
/// <summary>
|
||||
/// 文件保存路径
|
||||
/// </summary>
|
||||
public readonly string SavePath;
|
||||
|
||||
/// <summary>
|
||||
/// 是否追加写入文件
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 配合 ResumeFromBytes 使用,用于断点续传场景。
|
||||
/// </remarks>
|
||||
public readonly bool AppendToFile;
|
||||
|
||||
/// <summary>
|
||||
/// 中止请求时是否删除目标文件
|
||||
/// </summary>
|
||||
public readonly bool RemoveFileOnAbort;
|
||||
|
||||
/// <summary>
|
||||
/// 断点续传的起始字节(小于等于 0 表示不启用)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 推荐由后端自动设置 Range 请求头:"bytes={ResumeFromBytes}-"。
|
||||
/// </remarks>
|
||||
public readonly long ResumeFromBytes;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义请求头(可选)
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Headers;
|
||||
|
||||
/// <summary>
|
||||
/// 构造文件下载请求参数
|
||||
/// </summary>
|
||||
public DownloadFileRequestArgs(
|
||||
string url,
|
||||
string savePath,
|
||||
int timeout,
|
||||
int watchdogTime,
|
||||
bool appendToFile = false,
|
||||
bool removeFileOnAbort = true,
|
||||
long resumeFromBytes = 0)
|
||||
{
|
||||
URL = url;
|
||||
SavePath = savePath;
|
||||
Timeout = timeout;
|
||||
WatchdogTime = watchdogTime;
|
||||
AppendToFile = appendToFile;
|
||||
RemoveFileOnAbort = removeFileOnAbort;
|
||||
ResumeFromBytes = resumeFromBytes;
|
||||
Headers = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加请求头数据
|
||||
/// </summary>
|
||||
public void AddRequestHeader(string name, string value)
|
||||
{
|
||||
if (Headers == null)
|
||||
Headers = new Dictionary<string, string>(10);
|
||||
Headers.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据下载请求参数(通用)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于下载到内存的请求配置。
|
||||
/// 可用于字节数组(bytes)或文本(text)下载。
|
||||
/// </remarks>
|
||||
internal struct DownloadDataRequestArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当 Timeout 设置为 0 时,不应用超时。
|
||||
/// 设置的超时值可能应用于Android上的每个URL重定向,这可能会导致响应时间增加。
|
||||
/// </remarks>
|
||||
public readonly int Timeout;
|
||||
|
||||
/// <summary>
|
||||
/// 看门狗超时时间(单位:秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于监控下载任务的数据接收情况。
|
||||
/// 规则说明:
|
||||
/// 1. 当设置值为 0 时,表示禁用看门狗监控。
|
||||
/// 2. 每次接收到下载数据时,看门狗计时器会重置。
|
||||
/// 3. 若在设定的时间范围内未收到任何数据,任务将被自动终止。
|
||||
/// </remarks>
|
||||
public readonly int WatchdogTime;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义请求头(可选)
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Headers;
|
||||
|
||||
/// <summary>
|
||||
/// 构造数据下载请求参数
|
||||
/// </summary>
|
||||
/// <param name="url">请求地址</param>
|
||||
/// <param name="options">通用请求参数</param>
|
||||
public DownloadDataRequestArgs(string url, int timeout, int watchdogTime)
|
||||
{
|
||||
URL = url;
|
||||
Timeout = timeout;
|
||||
WatchdogTime = watchdogTime;
|
||||
Headers = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加请求头数据
|
||||
/// </summary>
|
||||
public void AddRequestHeader(string name, string value)
|
||||
{
|
||||
if (Headers == null)
|
||||
Headers = new Dictionary<string, string>(10);
|
||||
Headers.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 下载请求参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于下载并加载 Unity AssetBundle 的请求配置。
|
||||
/// 支持 Unity 内置缓存机制和 CRC 校验。
|
||||
/// </remarks>
|
||||
internal struct DownloadAssetBundleRequestArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当 Timeout 设置为 0 时,不应用超时。
|
||||
/// 设置的超时值可能应用于Android上的每个URL重定向,这可能会导致响应时间增加。
|
||||
/// </remarks>
|
||||
public readonly int Timeout;
|
||||
|
||||
/// <summary>
|
||||
/// 看门狗超时时间(单位:秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于监控下载任务的数据接收情况。
|
||||
/// 规则说明:
|
||||
/// 1. 当设置值为 0 时,表示禁用看门狗监控。
|
||||
/// 2. 每次接收到下载数据时,看门狗计时器会重置。
|
||||
/// 3. 若在设定的时间范围内未收到任何数据,任务将被自动终止。
|
||||
/// </remarks>
|
||||
public readonly int WatchdogTime;
|
||||
|
||||
/// <summary>
|
||||
/// 禁用 Unity 的网络缓存
|
||||
/// </summary>
|
||||
public readonly bool DisableUnityWebCache;
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 文件哈希(用于 UnityWebRequest 的缓存)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当 DisableUnityWebCache 为 false 时需要。
|
||||
/// </remarks>
|
||||
public readonly string FileHash;
|
||||
|
||||
/// <summary>
|
||||
/// Unity CRC 校验值
|
||||
/// </summary>
|
||||
public readonly uint UnityCRC;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义请求头(可选)
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Headers;
|
||||
|
||||
/// <summary>
|
||||
/// 构造 AssetBundle 下载请求参数
|
||||
/// </summary>
|
||||
public DownloadAssetBundleRequestArgs(
|
||||
string url,
|
||||
int timeout,
|
||||
int watchdogTime,
|
||||
bool disableUnityWebCache = true,
|
||||
string fileHash = null,
|
||||
uint unityCrc = 0)
|
||||
{
|
||||
URL = url;
|
||||
Timeout = timeout;
|
||||
WatchdogTime = watchdogTime;
|
||||
DisableUnityWebCache = disableUnityWebCache;
|
||||
FileHash = fileHash;
|
||||
UnityCRC = unityCrc;
|
||||
Headers = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加请求头数据
|
||||
/// </summary>
|
||||
public void AddRequestHeader(string name, string value)
|
||||
{
|
||||
if (Headers == null)
|
||||
Headers = new Dictionary<string, string>(10);
|
||||
Headers.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟下载请求参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于编辑器模式下模拟下载进度,不进行实际网络请求。
|
||||
/// </remarks>
|
||||
internal struct DownloadSimulateRequestArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址(仅用于标识)
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟的文件大小(字节)
|
||||
/// </summary>
|
||||
public readonly long FileSize;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟的下载速度(字节/秒)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于计算模拟的下载进度。
|
||||
/// </remarks>
|
||||
public readonly long DownloadSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// 构造模拟下载请求参数
|
||||
/// </summary>
|
||||
/// <param name="url">请求地址(仅用于标识)</param>
|
||||
/// <param name="fileSize">模拟的文件大小(字节)</param>
|
||||
/// <param name="downloadSpeed">模拟的下载速度(字节/秒),默认 1MB/s</param>
|
||||
public DownloadSimulateRequestArgs(string url, long fileSize, long downloadSpeed = 1024 * 1024)
|
||||
{
|
||||
URL = url;
|
||||
FileSize = fileSize;
|
||||
DownloadSpeed = downloadSpeed > 0 ? downloadSpeed : 1024 * 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb0480e877454f7c944f66a01646b6d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -94,8 +94,12 @@ namespace YooAsset
|
||||
public static bool IsRequestLocalFile(string url)
|
||||
{
|
||||
//TODO UNITY_STANDALONE_OSX平台目前无法确定
|
||||
|
||||
// 本地文件传输协议
|
||||
if (url.StartsWith("file:"))
|
||||
return true;
|
||||
|
||||
// JAR文件协议
|
||||
if (url.StartsWith("jar:file:"))
|
||||
return true;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4630dac2050606043bb146325fdce6ad
|
||||
guid: d724672f4d6f24b4db435d10eef6c40d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 不同网络库(UnityWebRequest / BestHTTP / 自研)实现该接口,用于创建具体下载请求。
|
||||
/// 每个后台实例是独立的,不共享全局状态。
|
||||
/// </remarks>
|
||||
internal interface IDownloadBackend : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 后台名称(用于日志与调试)
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 驱动更新
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 部分第三方网络库需要在 Unity 主线程中周期性调用 Update 进行驱动。
|
||||
/// 不需要驱动的后台可实现为空方法。
|
||||
/// </remarks>
|
||||
void Update();
|
||||
|
||||
/// <summary>
|
||||
/// 创建 HEAD 请求
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅获取响应头信息,不下载实际内容。
|
||||
/// 用于检查资源是否存在、获取资源大小、检查缓存有效性等场景。
|
||||
/// </remarks>
|
||||
/// <param name="args">数据请求参数</param>
|
||||
/// <returns>HEAD 请求实例</returns>
|
||||
IDownloadHeadRequest CreateHeadRequest(DownloadDataRequestArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件下载请求
|
||||
/// </summary>
|
||||
/// <param name="args">文件下载参数</param>
|
||||
/// <returns>文件下载请求实例</returns>
|
||||
IDownloadFileRequest CreateFileRequest(DownloadFileRequestArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// 创建内存下载请求(字节数组)
|
||||
/// </summary>
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <returns>字节下载请求实例</returns>
|
||||
IDownloadBytesRequest CreateBytesRequest(DownloadDataRequestArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// 创建文本下载请求
|
||||
/// </summary>
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <returns>文本下载请求实例</returns>
|
||||
IDownloadTextRequest CreateTextRequest(DownloadDataRequestArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// 创建 AssetBundle 下载请求
|
||||
/// </summary>
|
||||
/// <param name="args">AssetBundle 下载参数</param>
|
||||
/// <returns>AssetBundle 下载请求实例</returns>
|
||||
IDownloadAssetBundleRequest CreateAssetBundleRequest(DownloadAssetBundleRequestArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// 创建模拟下载请求
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于编辑器模式下模拟下载进度,不进行实际网络请求。
|
||||
/// 可用于测试下载流程和 UI 展示。
|
||||
/// </remarks>
|
||||
/// <param name="args">模拟下载参数</param>
|
||||
/// <returns>模拟下载请求实例</returns>
|
||||
IDownloadFileRequest CreateSimulateRequest(DownloadSimulateRequestArgs args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e88c026ebbfb40258aad52ad1c2feb70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 可轮询的下载请求接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 上层通常会在每帧轮询 Status IsDone,并在完成后读取结果。
|
||||
/// </remarks>
|
||||
internal interface IDownloadRequest : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
string URL { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否完成(成功/失败/中止)
|
||||
/// </summary>
|
||||
bool IsDone { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求状态
|
||||
/// </summary>
|
||||
EDownloadRequestStatus Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前下载进度(0f - 1f)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 部分情况下无法准确获取总长度,可返回 0。
|
||||
/// </remarks>
|
||||
float DownloadProgress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前请求已接收的字节数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 断点续传场景下,该值仅表示"本次请求新增下载的字节数",不包含已存在的本地文件长度。
|
||||
/// </remarks>
|
||||
long DownloadedBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 返回码
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 非 HTTP 协议可返回 0。使用 long 类型以兼容各种协议的返回码。
|
||||
/// </remarks>
|
||||
long HttpCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 失败时不为空。
|
||||
/// </remarks>
|
||||
string Error { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 发起请求
|
||||
/// </summary>
|
||||
void SendRequest();
|
||||
|
||||
/// <summary>
|
||||
/// 轮询请求
|
||||
/// </summary>
|
||||
void PollingRequest();
|
||||
|
||||
/// <summary>
|
||||
/// 中止请求
|
||||
/// </summary>
|
||||
void AbortRequest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HEAD 请求接口(仅获取响应头)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于检查资源是否存在、获取资源大小、检查缓存有效性等场景。
|
||||
/// 不下载实际内容,仅获取响应头信息。
|
||||
/// </remarks>
|
||||
internal interface IDownloadHeadRequest : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取 ETag 响应头
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于缓存验证,如果服务器未返回则为 null。
|
||||
/// </remarks>
|
||||
string ETag { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Last-Modified 响应头
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 资源最后修改时间,如果服务器未返回则为 null。
|
||||
/// </remarks>
|
||||
string LastModified { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Content-Type 响应头
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 资源的 MIME 类型,如果服务器未返回则为 null。
|
||||
/// </remarks>
|
||||
string ContentType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 预期下载的总字节数(Content-Length)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 从响应头 Content-Length 获取。
|
||||
/// 如果服务器未返回或请求未完成,返回 -1。
|
||||
/// 用于更准确的进度计算。
|
||||
/// </remarks>
|
||||
long ContentLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取响应头信息
|
||||
/// </summary>
|
||||
/// <param name="name">响应头名称(不区分大小写)</param>
|
||||
/// <returns>响应头的值,如果不存在或请求未完成则返回 null</returns>
|
||||
/// <remarks>
|
||||
/// 常用响应头:Content-Length、Content-Type、ETag、Last-Modified 等。
|
||||
/// </remarks>
|
||||
string GetResponseHeader(string name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件下载请求接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将下载内容保存到指定的本地文件路径。
|
||||
/// </remarks>
|
||||
internal interface IDownloadFileRequest : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件保存路径
|
||||
/// </summary>
|
||||
string SavePath { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内存下载请求接口(字节数组)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将下载内容保存到内存中的字节数组。
|
||||
/// </remarks>
|
||||
internal interface IDownloadBytesRequest : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载结果(字节数组)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅在请求成功时可用,失败时为 null。
|
||||
/// </remarks>
|
||||
byte[] Result { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文本下载请求接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将下载内容解析为 UTF-8 文本字符串。
|
||||
/// </remarks>
|
||||
internal interface IDownloadTextRequest : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载结果(文本字符串)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅在请求成功时可用,失败时为 null。
|
||||
/// </remarks>
|
||||
string Result { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 下载请求接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 下载并加载 Unity AssetBundle 资源包。
|
||||
/// </remarks>
|
||||
internal interface IDownloadAssetBundleRequest : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载结果(AssetBundle 对象)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅在请求成功时可用,失败时为 null。
|
||||
/// </remarks>
|
||||
UnityEngine.AssetBundle Result { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a2aafeb309243f4959394a97d66b19f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,113 +0,0 @@
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 请求结果
|
||||
/// </summary>
|
||||
public AssetBundle Result { private set; get; }
|
||||
|
||||
internal UnityAssetBundleRequestOperation(PackageBundle packageBundle, bool disableUnityWebCache, string url) : base(url)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityVirtualBundleRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
Download,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly int _downloadSpeed;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal UnityVirtualBundleRequestOperation(PackageBundle packageBundle, int downloadSpeed, string url) : base(url)
|
||||
{
|
||||
_bundle = packageBundle;
|
||||
_downloadSpeed = downloadSpeed;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
// 模拟下载进度
|
||||
float progress = 0;
|
||||
if (DownloadedBytes > 0)
|
||||
progress = DownloadedBytes / _bundle.FileSize;
|
||||
long downloadBytes = (long)((double)_downloadSpeed * Time.deltaTime);
|
||||
|
||||
Progress = progress;
|
||||
DownloadProgress = progress;
|
||||
DownloadedBytes += downloadBytes;
|
||||
if (DownloadedBytes < _bundle.FileSize)
|
||||
return;
|
||||
|
||||
Progress = 1f;
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Try load bundle {_bundle.BundleName} from remote !";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebCacheRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CreateRequest,
|
||||
Download,
|
||||
Done,
|
||||
}
|
||||
|
||||
private UnityWebRequestAsyncOperation _requestOperation;
|
||||
private readonly Dictionary<string, string> _headers = new Dictionary<string, string>();
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal UnityWebCacheRequestOperation(string url) : base(url)
|
||||
{
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
return;
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置请求头信息
|
||||
/// </summary>
|
||||
public void SetRequestHeader(string name, string value)
|
||||
{
|
||||
_headers.Add(name, value);
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
|
||||
// 设置消息头
|
||||
foreach (var keyValuePair in _headers)
|
||||
{
|
||||
string name = keyValuePair.Key;
|
||||
string value = keyValuePair.Value;
|
||||
_webRequest.SetRequestHeader(name, value);
|
||||
}
|
||||
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebDataRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CreateRequest,
|
||||
Download,
|
||||
Done,
|
||||
}
|
||||
|
||||
private UnityWebRequestAsyncOperation _requestOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒),在经过Timeout的秒数后尝试中止。
|
||||
/// 注意:当Timeout设置为0时,不会应用超时。
|
||||
/// 注意:设置的超时值可能应用于Android上的每个URL重定向,这可能会导致响应时间增加。
|
||||
/// </summary>
|
||||
private readonly int _timeout;
|
||||
|
||||
/// <summary>
|
||||
/// 请求结果
|
||||
/// </summary>
|
||||
public byte[] Result { private set; get; }
|
||||
|
||||
|
||||
internal UnityWebDataRequestOperation(string url, int timeout) : base(url)
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
return;
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
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
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.timeout = _timeout;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7557eb146572de49a1ec9b3f3c0b706
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,83 +0,0 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒),在经过Timeout的秒数后尝试中止。
|
||||
/// 注意:当Timeout设置为0时,不会应用超时。
|
||||
/// 注意:设置的超时值可能应用于Android上的每个URL重定向,这可能会导致响应时间增加。
|
||||
/// </summary>
|
||||
private readonly int _timeout;
|
||||
|
||||
|
||||
internal UnityWebFileRequestOperation(string url, string fileSavePath, int timeout) : base(url)
|
||||
{
|
||||
_fileSavePath = fileSavePath;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
return;
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(_fileSavePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.timeout = _timeout;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ab5f2486d06e2642ba7aa9c9623430e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class UnityWebRequestOperation : AsyncOperationBase
|
||||
{
|
||||
protected UnityWebRequest _webRequest;
|
||||
protected readonly string _requestURL;
|
||||
private bool _isAbort = false;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP返回码
|
||||
/// </summary>
|
||||
public long HttpCode { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前下载的字节数
|
||||
/// </summary>
|
||||
public long DownloadedBytes { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前下载进度(0f - 1f)
|
||||
/// </summary>
|
||||
public float DownloadProgress { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求的URL地址
|
||||
/// </summary>
|
||||
public string URL
|
||||
{
|
||||
get { return _requestURL; }
|
||||
}
|
||||
|
||||
internal UnityWebRequestOperation(string url)
|
||||
{
|
||||
_requestURL = url;
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
//TODO
|
||||
// 1. 编辑器下停止运行游戏的时候主动终止下载任务
|
||||
// 2. 真机上销毁包裹的时候主动终止下载任务
|
||||
if (_isAbort == false)
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
_webRequest.Abort();
|
||||
_isAbort = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放下载器
|
||||
/// </summary>
|
||||
protected void DisposeRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
//注意:引擎底层会自动调用Abort方法
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测请求结果
|
||||
/// </summary>
|
||||
protected bool CheckRequestResult()
|
||||
{
|
||||
HttpCode = _webRequest.responseCode;
|
||||
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Error = $"URL : {_requestURL} Error : {_webRequest.error}";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
{
|
||||
Error = $"URL : {_requestURL} Error : {_webRequest.error}";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e5c3c1a1655a8b41b585c6811201583
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,96 +0,0 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebTextRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CreateRequest,
|
||||
Download,
|
||||
Done,
|
||||
}
|
||||
|
||||
private UnityWebRequestAsyncOperation _requestOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒),在经过Timeout的秒数后尝试中止。
|
||||
/// 注意:当Timeout设置为0时,不会应用超时。
|
||||
/// 注意:设置的超时值可能应用于Android上的每个URL重定向,这可能会导致响应时间增加。
|
||||
/// </summary>
|
||||
private readonly int _timeout;
|
||||
|
||||
/// <summary>
|
||||
/// 请求结果
|
||||
/// </summary>
|
||||
public string Result { private set; get; }
|
||||
|
||||
|
||||
internal UnityWebTextRequestOperation(string url, int timeout) : base(url)
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
return;
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
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
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.timeout = _timeout;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a488de5dcd6f4c448a47c4b574d5c9bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -25,6 +25,11 @@ namespace YooAsset
|
||||
protected IFileSystem _unpackFileSystem;
|
||||
protected string _packageRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
@@ -66,7 +71,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
||||
/// </summary>
|
||||
public int FileVerifyMaxConcurrency { private set; get; } = int.MaxValue;
|
||||
public int FileVerifyMaxConcurrency { private set; get; } = 32;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:数据文件追加文件格式
|
||||
@@ -156,6 +161,13 @@ namespace YooAsset
|
||||
var operation = new DBFSLoadRawBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
#if TUANJIE_1_7_OR_NEWER
|
||||
else if (bundle.BundleType == (int)EBuildBundleType.InstantBundle)
|
||||
{
|
||||
var operation = new DBFSLoadInstantBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
string error = $"{nameof(DefaultBuildinFileSystem)} not support load bundle type : {bundle.BundleType}";
|
||||
@@ -225,6 +237,10 @@ namespace YooAsset
|
||||
else
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||
|
||||
// 创建解压文件系统
|
||||
var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
|
||||
_unpackFileSystem = new DefaultUnpackFileSystem();
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace YooAsset
|
||||
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||
string destFilePath = GetCopyPackageHashDestPath(packageVersion);
|
||||
string sourceFilePath = _fileSystem.GetBuildinPackageHashFilePath(packageVersion);
|
||||
_copyBuildinHashFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
|
||||
_copyBuildinHashFileOp = new CopyBuildinFileOperation(_fileSystem, sourceFilePath, destFilePath);
|
||||
_copyBuildinHashFileOp.StartOperation();
|
||||
AddChildOperation(_copyBuildinHashFileOp);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ namespace YooAsset
|
||||
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||
string destFilePath = GetCopyPackageManifestDestPath(packageVersion);
|
||||
string sourceFilePath = _fileSystem.GetBuildinPackageManifestFilePath(packageVersion);
|
||||
_copyBuildinManifestFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
|
||||
_copyBuildinManifestFileOp = new CopyBuildinFileOperation(_fileSystem, sourceFilePath, destFilePath);
|
||||
_copyBuildinManifestFileOp.StartOperation();
|
||||
AddChildOperation(_copyBuildinManifestFileOp);
|
||||
}
|
||||
|
||||
@@ -14,13 +14,15 @@ namespace YooAsset
|
||||
Done,
|
||||
}
|
||||
|
||||
private UnityWebFileRequestOperation _webFileRequestOp;
|
||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||
private readonly string _sourceFilePath;
|
||||
private readonly string _destFilePath;
|
||||
private IDownloadFileRequest _webFileRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public CopyBuildinFileOperation(string sourceFilePath, string destFilePath)
|
||||
public CopyBuildinFileOperation(DefaultBuildinFileSystem fileSystem, string sourceFilePath, string destFilePath)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_sourceFilePath = sourceFilePath;
|
||||
_destFilePath = destFilePath;
|
||||
}
|
||||
@@ -76,16 +78,15 @@ namespace YooAsset
|
||||
if (_webFileRequestOp == null)
|
||||
{
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(_sourceFilePath);
|
||||
_webFileRequestOp = new UnityWebFileRequestOperation(url, _destFilePath, 60);
|
||||
_webFileRequestOp.StartOperation();
|
||||
AddChildOperation(_webFileRequestOp);
|
||||
var args = new DownloadFileRequestArgs(url, _destFilePath, 60, 0);
|
||||
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_webFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webFileRequestOp.UpdateOperation();
|
||||
if (_webFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private byte[] _fileData;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -57,16 +57,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, 60);
|
||||
_webDataRequestOp.StartOperation();
|
||||
AddChildOperation(_webDataRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webDataRequestOp.UpdateOperation();
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_fileData = _webDataRequestOp.Result;
|
||||
_steps = ESteps.LoadCatalog;
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace YooAsset
|
||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly string _packageHash;
|
||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private DeserializeManifestOperation _deserializer;
|
||||
private byte[] _fileData;
|
||||
private ESteps _steps = ESteps.None;
|
||||
@@ -63,16 +63,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, 60);
|
||||
_webDataRequestOp.StartOperation();
|
||||
AddChildOperation(_webDataRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webDataRequestOp.UpdateOperation();
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_fileData = _webDataRequestOp.Result;
|
||||
_steps = ESteps.VerifyFileData;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
||||
|
||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
@@ -58,16 +58,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetBuildinPackageHashFilePath(_packageVersion);
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, 60);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageHash = _webTextRequestOp.Result;
|
||||
_steps = ESteps.CheckResult;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
@@ -56,16 +56,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetBuildinPackageVersionFilePath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, 60);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageVersion = _webTextRequestOp.Result;
|
||||
_steps = ESteps.CheckResult;
|
||||
|
||||
@@ -23,10 +23,14 @@ namespace YooAsset
|
||||
protected string _cacheManifestFilesRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 下载中心
|
||||
/// 说明:当异步操作任务终止的时候,所有下载子任务都会一同被终止!
|
||||
/// 下载调度器
|
||||
/// </summary>
|
||||
public DownloadCenterOperation DownloadCenter { set; get; }
|
||||
public DownloadSchedulerOperation DownloadScheduler { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
@@ -105,7 +109,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 自定义参数:下载任务的看门狗机制监控时间
|
||||
/// </summary>
|
||||
public int DownloadWatchDogTime { private set; get; } = int.MaxValue;
|
||||
public int DownloadWatchDogTime { private set; get; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:启用断点续传的最小尺寸
|
||||
@@ -288,7 +292,7 @@ namespace YooAsset
|
||||
else if (name == FileSystemParametersDefine.DOWNLOAD_WATCH_DOG_TIME)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
DownloadWatchDogTime = Mathf.Clamp(convertValue, 1, int.MaxValue);
|
||||
DownloadWatchDogTime = Mathf.Clamp(convertValue, 0, int.MaxValue);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE)
|
||||
{
|
||||
@@ -327,13 +331,17 @@ namespace YooAsset
|
||||
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
|
||||
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
||||
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
if (DownloadCenter != null)
|
||||
if (DownloadScheduler != null)
|
||||
{
|
||||
DownloadCenter.AbortOperation();
|
||||
DownloadCenter = null;
|
||||
DownloadScheduler.Dispose();
|
||||
DownloadScheduler = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace YooAsset
|
||||
CheckAppFootPrint,
|
||||
SearchCacheFiles,
|
||||
VerifyCacheFiles,
|
||||
CreateDownloadCenter,
|
||||
CreateDownloadScheduler,
|
||||
Done,
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace YooAsset
|
||||
|
||||
if (_verifyCacheFilesOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.CreateDownloadCenter;
|
||||
_steps = ESteps.CreateDownloadScheduler;
|
||||
YooLogger.Log($"Package '{_fileSystem.PackageName}' '{_fileSystem.GetType().Name}' cached files count : {_fileSystem.FileCount}");
|
||||
}
|
||||
else
|
||||
@@ -121,13 +121,13 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CreateDownloadCenter)
|
||||
if (_steps == ESteps.CreateDownloadScheduler)
|
||||
{
|
||||
// 注意:下载中心作为独立任务运行!
|
||||
if (_fileSystem.DownloadCenter == null)
|
||||
if (_fileSystem.DownloadScheduler == null)
|
||||
{
|
||||
_fileSystem.DownloadCenter = new DownloadCenterOperation(_fileSystem);
|
||||
OperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadCenter);
|
||||
_fileSystem.DownloadScheduler = new DownloadSchedulerOperation(_fileSystem);
|
||||
OperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadScheduler);
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DownloadCenterOperation : AsyncOperationBase
|
||||
{
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
protected readonly Dictionary<string, UnityDownloadFileOperation> _downloaders = new Dictionary<string, UnityDownloadFileOperation>(1000);
|
||||
protected readonly List<string> _removeList = new List<string>(1000);
|
||||
|
||||
public DownloadCenterOperation(DefaultCacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
// 获取可移除的下载器集合
|
||||
_removeList.Clear();
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var downloader = valuePair.Value;
|
||||
downloader.UpdateOperation();
|
||||
if (downloader.IsDone)
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 注意:主动终止引用计数为零的下载任务
|
||||
if (downloader.RefCount <= 0)
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
downloader.AbortOperation();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 移除下载器
|
||||
foreach (var key in _removeList)
|
||||
{
|
||||
if (_downloaders.TryGetValue(key, out var downloader))
|
||||
{
|
||||
Childs.Remove(downloader);
|
||||
_downloaders.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 最大并发数检测
|
||||
int processCount = GetProcessingOperationCount();
|
||||
if (processCount != _downloaders.Count)
|
||||
{
|
||||
if (processCount < _fileSystem.DownloadMaxConcurrency)
|
||||
{
|
||||
int startCount = _fileSystem.DownloadMaxConcurrency - processCount;
|
||||
if (startCount > _fileSystem.DownloadMaxRequestPerFrame)
|
||||
startCount = _fileSystem.DownloadMaxRequestPerFrame;
|
||||
|
||||
foreach (var operationPair in _downloaders)
|
||||
{
|
||||
var operation = operationPair.Value;
|
||||
if (operation.Status == EOperationStatus.None)
|
||||
{
|
||||
operation.StartOperation();
|
||||
startCount--;
|
||||
if (startCount <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建下载任务
|
||||
/// </summary>
|
||||
public UnityDownloadFileOperation DownloadFileAsync(PackageBundle bundle, string url)
|
||||
{
|
||||
// 查询旧的下载器
|
||||
if (_downloaders.TryGetValue(bundle.BundleGUID, out var oldDownloader))
|
||||
{
|
||||
oldDownloader.Reference();
|
||||
return oldDownloader;
|
||||
}
|
||||
|
||||
// 创建新的下载器
|
||||
UnityDownloadFileOperation newDownloader;
|
||||
bool isRequestLocalFile = DownloadSystemHelper.IsRequestLocalFile(url);
|
||||
if (isRequestLocalFile)
|
||||
{
|
||||
newDownloader = new UnityDownloadLocalFileOperation(_fileSystem, bundle, url);
|
||||
AddChildOperation(newDownloader);
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize)
|
||||
{
|
||||
newDownloader = new UnityDownloadResumeFileOperation(_fileSystem, bundle, url);
|
||||
AddChildOperation(newDownloader);
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDownloader = new UnityDownloadNormalFileOperation(_fileSystem, bundle, url);
|
||||
AddChildOperation(newDownloader);
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
}
|
||||
}
|
||||
|
||||
newDownloader.Reference();
|
||||
return newDownloader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取正在进行中的下载器总数
|
||||
/// </summary>
|
||||
private int GetProcessingOperationCount()
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var operationPair in _downloaders)
|
||||
{
|
||||
var operation = operationPair.Value;
|
||||
if (operation.Status != EOperationStatus.None)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 768ef2df3433df245a26fec28d022e45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
@@ -17,7 +18,7 @@ namespace YooAsset
|
||||
// 下载参数
|
||||
protected readonly DefaultCacheFileSystem _fileSystem;
|
||||
protected readonly DownloadFileOptions _options;
|
||||
private UnityDownloadFileOperation _unityDownloadFileOp;
|
||||
private DownloadAndCacheFileOperation _downloadFileOp;
|
||||
|
||||
protected int _requestCount = 0;
|
||||
protected float _tryAgainTimer = 0;
|
||||
@@ -67,7 +68,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
string url = GetRequestURL();
|
||||
_unityDownloadFileOp = _fileSystem.DownloadCenter.DownloadFileAsync(Bundle, url);
|
||||
_downloadFileOp = _fileSystem.DownloadScheduler.DownloadAndCacheFileAsync(Bundle, url);
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
@@ -75,20 +76,16 @@ namespace YooAsset
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
if (IsWaitForAsyncComplete)
|
||||
_unityDownloadFileOp.WaitForAsyncComplete();
|
||||
_downloadFileOp.WaitForAsyncComplete();
|
||||
|
||||
// 因为并发数量限制,下载器可能被挂起!
|
||||
if (_unityDownloadFileOp.Status == EOperationStatus.None)
|
||||
_downloadFileOp.UpdateOperation();
|
||||
Progress = _downloadFileOp.Progress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
_unityDownloadFileOp.UpdateOperation();
|
||||
Progress = _unityDownloadFileOp.Progress;
|
||||
DownloadedBytes = _unityDownloadFileOp.DownloadedBytes;
|
||||
DownloadProgress = _unityDownloadFileOp.DownloadProgress;
|
||||
if (_unityDownloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_unityDownloadFileOp.Status == EOperationStatus.Succeed)
|
||||
if (_downloadFileOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
@@ -98,13 +95,13 @@ namespace YooAsset
|
||||
if (IsWaitForAsyncComplete == false && _failedTryAgain > 0)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
YooLogger.Warning($"Failed download : {_unityDownloadFileOp.URL} Try again !");
|
||||
YooLogger.Warning($"Failed download : {_downloadFileOp.URL} Try again !");
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _unityDownloadFileOp.Error;
|
||||
Error = _downloadFileOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
@@ -141,9 +138,9 @@ namespace YooAsset
|
||||
// 注意:取消下载任务的时候引用计数减一
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
if (_unityDownloadFileOp != null)
|
||||
if (_downloadFileOp != null)
|
||||
{
|
||||
_unityDownloadFileOp.Release();
|
||||
_downloadFileOp.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private UnityWebFileRequestOperation _webFileRequestOp;
|
||||
private IDownloadFileRequest _webFileRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -57,16 +57,16 @@ namespace YooAsset
|
||||
string savePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
|
||||
string webURL = GetWebRequestURL(fileName);
|
||||
_webFileRequestOp = new UnityWebFileRequestOperation(webURL, savePath, _timeout);
|
||||
_webFileRequestOp.StartOperation();
|
||||
AddChildOperation(_webFileRequestOp);
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||
var args = new DownloadFileRequestArgs(webURL, savePath, _timeout, watchdogTime);
|
||||
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_webFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webFileRequestOp.UpdateOperation();
|
||||
if (_webFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private UnityWebFileRequestOperation _webFileRequestOp;
|
||||
private IDownloadFileRequest _webFileRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -57,16 +57,16 @@ namespace YooAsset
|
||||
string savePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
|
||||
string webURL = GetDownloadRequestURL(fileName);
|
||||
_webFileRequestOp = new UnityWebFileRequestOperation(webURL, savePath, _timeout);
|
||||
_webFileRequestOp.StartOperation();
|
||||
AddChildOperation(_webFileRequestOp);
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||
var args = new DownloadFileRequestArgs(webURL, savePath, _timeout, watchdogTime);
|
||||
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_webFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webFileRequestOp.UpdateOperation();
|
||||
if (_webFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace YooAsset
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly bool _appendTimeTicks;
|
||||
private readonly int _timeout;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -45,17 +45,17 @@ namespace YooAsset
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
|
||||
string url = GetWebRequestURL(fileName);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
int watchDogTime = _fileSystem.DownloadWatchDogTime;
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, watchDogTime);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
Progress = _webTextRequestOp.Progress;
|
||||
Progress = _webTextRequestOp.DownloadProgress;
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageVersion = _webTextRequestOp.Result;
|
||||
if (string.IsNullOrEmpty(PackageVersion))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf9991076b60f0f459846f54b0ca6698
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class DownloadAndCacheFileOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 引用计数
|
||||
/// </summary>
|
||||
public int RefCount { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度
|
||||
/// </summary>
|
||||
public float DownloadProgress { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载字节
|
||||
/// </summary>
|
||||
public long DownloadedBytes { get; protected set; }
|
||||
|
||||
public DownloadAndCacheFileOperation(string url)
|
||||
{
|
||||
URL = url;
|
||||
}
|
||||
internal override string InternalGetDesc()
|
||||
{
|
||||
return $"RefCount : {RefCount}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 减少引用计数
|
||||
/// </summary>
|
||||
public void Release()
|
||||
{
|
||||
RefCount--;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加引用计数
|
||||
/// </summary>
|
||||
public void Reference()
|
||||
{
|
||||
RefCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2954a64fd419d5a4b9d0a102260d193c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,94 +1,79 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class UnityDownloadLocalFileOperation : UnityDownloadFileOperation
|
||||
internal sealed class DownloadAndCacheLocalFileOperation : DownloadAndCacheFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckCopy,
|
||||
CopyLocalFile,
|
||||
CreateRequest,
|
||||
CheckRequest,
|
||||
VerifyBundleFile,
|
||||
CacheBundleFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly string _tempFilePath;
|
||||
private IDownloadRequest _request;
|
||||
private VerifyTempFileOperation _verifyOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal UnityDownloadLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url)
|
||||
: base(fileSystem, bundle, url)
|
||||
internal DownloadAndCacheLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url) : base(url)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(_bundle);
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
if (_fileSystem.CopyLocalFileServices != null)
|
||||
_steps = ESteps.CopyLocalFile;
|
||||
else
|
||||
_steps = ESteps.CreateRequest;
|
||||
_steps = ESteps.CheckCopy;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
// 检测文件拷贝
|
||||
if (_steps == ESteps.CheckCopy)
|
||||
{
|
||||
// 删除历史缓存文件
|
||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
|
||||
UpdateWatchDog();
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.VerifyFile;
|
||||
}
|
||||
if (_fileSystem.CopyLocalFileServices != null)
|
||||
_steps = ESteps.CopyLocalFile;
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
|
||||
// 拷贝内置文件
|
||||
// 拷贝本地文件
|
||||
if (_steps == ESteps.CopyLocalFile)
|
||||
{
|
||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
try
|
||||
{
|
||||
//TODO 团结引擎,在某些机型(红米),拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。
|
||||
var localFileInfo = new LocalFileInfo();
|
||||
localFileInfo.PackageName = _fileSystem.PackageName;
|
||||
localFileInfo.BundleName = _bundle.BundleName;
|
||||
localFileInfo.SourceFileURL = _requestURL;
|
||||
localFileInfo.SourceFileURL = URL;
|
||||
_fileSystem.CopyLocalFileServices.CopyFile(localFileInfo, _tempFilePath);
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
Progress = DownloadProgress;
|
||||
_steps = ESteps.VerifyFile;
|
||||
_steps = ESteps.VerifyBundleFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed copy local file : {_requestURL}";
|
||||
Error = $"Failed copy local file : {URL}";
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
@@ -99,8 +84,44 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
// 验证下载文件
|
||||
if (_steps == ESteps.VerifyFile)
|
||||
// 创建下载请求
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||
int timeout = 0; //注意:文件下载不做超时检测
|
||||
var args = new DownloadFileRequestArgs(URL, _tempFilePath, timeout, watchdogTime);
|
||||
_request = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_request.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
DownloadProgress = _request.DownloadProgress;
|
||||
DownloadedBytes = _request.DownloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_request.IsDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (_request.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.VerifyBundleFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _request.Error;
|
||||
}
|
||||
|
||||
// 最终释放请求器
|
||||
_request.Dispose();
|
||||
}
|
||||
|
||||
// 验证下载结果
|
||||
if (_steps == ESteps.VerifyBundleFile)
|
||||
{
|
||||
if (_verifyOperation == null)
|
||||
{
|
||||
@@ -119,35 +140,51 @@ namespace YooAsset
|
||||
|
||||
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 !";
|
||||
}
|
||||
_steps = ESteps.CacheBundleFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _verifyOperation.Error;
|
||||
|
||||
// 注意:验证失败后直接删除文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存文件
|
||||
if (_steps == ESteps.CacheBundleFile)
|
||||
{
|
||||
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 !";
|
||||
}
|
||||
|
||||
// 注意:验证完成后直接删除文件
|
||||
// 注意:缓存完成后直接删除临时文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
if (_request != null)
|
||||
_request.AbortRequest();
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
//TODO 等待导入或解压本地文件完毕,该操作会挂起主线程!
|
||||
_fileSystem.DownloadBackend.Update();
|
||||
InternalUpdate();
|
||||
if (IsDone)
|
||||
break;
|
||||
@@ -156,15 +193,5 @@ namespace YooAsset
|
||||
System.Threading.Thread.Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47700ac672942834f8d5a7c59783d88e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,206 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class DownloadAndCacheRemoteFileOperation : DownloadAndCacheFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CreateRequest,
|
||||
CheckRequest,
|
||||
VerifyBundleFile,
|
||||
CacheBundleFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly string _tempFilePath;
|
||||
private bool _enableResume = false;
|
||||
private long _fileOriginLength = 0;
|
||||
private IDownloadRequest _request;
|
||||
private VerifyTempFileOperation _verifyOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal DownloadAndCacheRemoteFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url) : base(url)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(_bundle);
|
||||
}
|
||||
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);
|
||||
|
||||
_enableResume = _bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize;
|
||||
if (_enableResume)
|
||||
{
|
||||
_request = CreateResumeRequest();
|
||||
_request.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_request = CreateNormalRequest();
|
||||
_request.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
DownloadProgress = _request.DownloadProgress;
|
||||
DownloadedBytes = _fileOriginLength + _request.DownloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_request.IsDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (_request.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.VerifyBundleFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _request.Error;
|
||||
}
|
||||
|
||||
// 在遇到特殊错误的时候删除文件
|
||||
if (_enableResume)
|
||||
ClearTempFileWhenError(_request.HttpCode);
|
||||
|
||||
// 最终释放请求器
|
||||
_request.Dispose();
|
||||
}
|
||||
|
||||
// 验证下载结果
|
||||
if (_steps == ESteps.VerifyBundleFile)
|
||||
{
|
||||
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)
|
||||
{
|
||||
_steps = ESteps.CacheBundleFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _verifyOperation.Error;
|
||||
|
||||
// 注意:验证失败后直接删除文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存文件
|
||||
if (_steps == ESteps.CacheBundleFile)
|
||||
{
|
||||
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 !";
|
||||
}
|
||||
|
||||
// 注意:缓存完成后直接删除临时文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
if (_request != null)
|
||||
_request.AbortRequest();
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
// 注意:不中断下载任务,保持后台继续下载
|
||||
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote : {URL} !");
|
||||
}
|
||||
}
|
||||
|
||||
private IDownloadRequest CreateResumeRequest()
|
||||
{
|
||||
// 获取下载起始位置
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
||||
if (fileInfo.Length >= _bundle.FileSize)
|
||||
{
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileOriginLength = fileInfo.Length;
|
||||
}
|
||||
}
|
||||
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||
int timeout = 0; //注意:文件下载不做超时检测
|
||||
bool appendToFile = true;
|
||||
bool removeFileOnAbort = false;
|
||||
long resumeFromBytes = _fileOriginLength;
|
||||
var args = new DownloadFileRequestArgs(URL, _tempFilePath, timeout, watchdogTime, appendToFile, removeFileOnAbort, resumeFromBytes);
|
||||
return _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
}
|
||||
private IDownloadRequest CreateNormalRequest()
|
||||
{
|
||||
// 删除历史缓存文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||
int timeout = 0; //注意:文件下载不做超时检测
|
||||
var args = new DownloadFileRequestArgs(URL, _tempFilePath, timeout, watchdogTime);
|
||||
return _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
}
|
||||
private void ClearTempFileWhenError(long httpCode)
|
||||
{
|
||||
if (_fileSystem.ResumeDownloadResponseCodes == null)
|
||||
return;
|
||||
|
||||
//说明:如果遇到以下错误返回码,验证失败直接删除文件
|
||||
if (_fileSystem.ResumeDownloadResponseCodes.Contains(httpCode))
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad910a81855976e44b4f1f09051910b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载调度器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 管理所有活跃的下载任务,控制并发数量。
|
||||
/// </remarks>
|
||||
internal class DownloadSchedulerOperation : AsyncOperationBase, IDisposable
|
||||
{
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly Dictionary<string, DownloadAndCacheFileOperation> _downloaders = new Dictionary<string, DownloadAndCacheFileOperation>(1000);
|
||||
private readonly List<string> _removeList = new List<string>(1000);
|
||||
|
||||
/// <summary>
|
||||
/// 是否已暂停
|
||||
/// </summary>
|
||||
public bool Paused { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 当前活跃的下载任务数
|
||||
/// </summary>
|
||||
public int ActiveDownloadCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前等待中的下载任务数
|
||||
/// </summary>
|
||||
public int PendingDownloadCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _downloaders.Count - ActiveDownloadCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构造下载中心
|
||||
/// </summary>
|
||||
public DownloadSchedulerOperation(DefaultCacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
// 驱动下载后台
|
||||
_fileSystem.DownloadBackend.Update();
|
||||
|
||||
// 获取可移除的下载器集合
|
||||
_removeList.Clear();
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var downloader = valuePair.Value;
|
||||
downloader.UpdateOperation();
|
||||
if (downloader.IsDone)
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 注意:主动终止引用计数为零的下载任务
|
||||
if (downloader.RefCount <= 0)
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
downloader.AbortOperation();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 移除下载器
|
||||
foreach (var key in _removeList)
|
||||
{
|
||||
if (_downloaders.TryGetValue(key, out var downloader))
|
||||
{
|
||||
RemoveChildOperation(downloader);
|
||||
_downloaders.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 暂停时不启动新任务
|
||||
if (Paused)
|
||||
return;
|
||||
|
||||
// 最大并发数检测
|
||||
ActiveDownloadCount = GetProcessingOperationCount();
|
||||
if (ActiveDownloadCount != _downloaders.Count)
|
||||
{
|
||||
int maxConcurrency = _fileSystem.DownloadMaxConcurrency;
|
||||
int maxRequestPerFrame = _fileSystem.DownloadMaxRequestPerFrame;
|
||||
if (ActiveDownloadCount < maxConcurrency)
|
||||
{
|
||||
int startCount = maxConcurrency - ActiveDownloadCount;
|
||||
if (startCount > maxRequestPerFrame)
|
||||
startCount = maxRequestPerFrame;
|
||||
|
||||
foreach (var operationPair in _downloaders)
|
||||
{
|
||||
var operation = operationPair.Value;
|
||||
if (operation.Status == EOperationStatus.None)
|
||||
{
|
||||
operation.StartOperation();
|
||||
startCount--;
|
||||
if (startCount <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中止所有下载任务
|
||||
/// </summary>
|
||||
public void AbortAll()
|
||||
{
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
valuePair.Value.AbortOperation();
|
||||
}
|
||||
_downloaders.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
AbortAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建下载任务
|
||||
/// </summary>
|
||||
/// <param name="bundle">资源包信息</param>
|
||||
/// <param name="url">下载地址</param>
|
||||
/// <returns>下载操作</returns>
|
||||
public DownloadAndCacheFileOperation DownloadAndCacheFileAsync(PackageBundle bundle, string url)
|
||||
{
|
||||
// 查询旧的下载器
|
||||
if (_downloaders.TryGetValue(bundle.BundleGUID, out var oldDownloader))
|
||||
{
|
||||
oldDownloader.Reference();
|
||||
return oldDownloader;
|
||||
}
|
||||
|
||||
// 创建新的下载器
|
||||
DownloadAndCacheFileOperation newDownloader;
|
||||
bool isRequestLocalFile = DownloadSystemHelper.IsRequestLocalFile(url);
|
||||
if (isRequestLocalFile)
|
||||
{
|
||||
newDownloader = new DownloadAndCacheLocalFileOperation(_fileSystem, bundle, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDownloader = new DownloadAndCacheRemoteFileOperation(_fileSystem, bundle, url);
|
||||
}
|
||||
|
||||
AddChildOperation(newDownloader);
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
newDownloader.Reference();
|
||||
return newDownloader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取正在进行中的下载器总数
|
||||
/// </summary>
|
||||
private int GetProcessingOperationCount()
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var operationPair in _downloaders)
|
||||
{
|
||||
var operation = operationPair.Value;
|
||||
if (operation.Status != EOperationStatus.None)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73441e829c36a36418f5d677e189e9f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,98 +0,0 @@
|
||||
|
||||
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;
|
||||
|
||||
private bool _watchDogInit = false;
|
||||
private bool _watchDogAborted = false;
|
||||
private ulong _lastDownloadBytes;
|
||||
private double _lastGetDataTime;
|
||||
|
||||
/// <summary>
|
||||
/// 引用计数
|
||||
/// </summary>
|
||||
public int RefCount { private set; get; }
|
||||
|
||||
internal UnityDownloadFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url) : base(url)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(bundle);
|
||||
}
|
||||
internal override string InternalGetDesc()
|
||||
{
|
||||
return $"RefCount : {RefCount}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新看门狗监测
|
||||
/// 说明:监控时间范围内,如果没有接收到任何下载数据,那么直接终止任务!
|
||||
/// </summary>
|
||||
protected void UpdateWatchDog()
|
||||
{
|
||||
if (_fileSystem.DownloadWatchDogTime == int.MaxValue)
|
||||
return;
|
||||
|
||||
if (_watchDogAborted)
|
||||
return;
|
||||
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
double realtimeSinceStartup = UnityEngine.Time.realtimeSinceStartupAsDouble;
|
||||
#else
|
||||
double realtimeSinceStartup = UnityEngine.Time.realtimeSinceStartup;
|
||||
#endif
|
||||
|
||||
if (_watchDogInit == false)
|
||||
{
|
||||
_watchDogInit = true;
|
||||
_lastDownloadBytes = 0;
|
||||
_lastGetDataTime = realtimeSinceStartup;
|
||||
}
|
||||
|
||||
if (_webRequest.downloadedBytes != _lastDownloadBytes)
|
||||
{
|
||||
_lastDownloadBytes = _webRequest.downloadedBytes;
|
||||
_lastGetDataTime = realtimeSinceStartup;
|
||||
}
|
||||
else
|
||||
{
|
||||
double deltaTime = realtimeSinceStartup - _lastGetDataTime;
|
||||
if (deltaTime > _fileSystem.DownloadWatchDogTime)
|
||||
{
|
||||
_watchDogAborted = true;
|
||||
InternalAbort(); //终止网络请求
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 减少引用计数
|
||||
/// </summary>
|
||||
public void Release()
|
||||
{
|
||||
RefCount--;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加引用计数
|
||||
/// </summary>
|
||||
public void Reference()
|
||||
{
|
||||
RefCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40bb5e9391f413c42ae70e48ca90c4b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c68640bb1d36552469024324e3357bc2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,124 +0,0 @@
|
||||
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)
|
||||
: base(fileSystem, bundle, url)
|
||||
{
|
||||
}
|
||||
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);
|
||||
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
|
||||
UpdateWatchDog();
|
||||
if (_webRequest.isDone == false)
|
||||
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()
|
||||
{
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 759967d543776a0469b625eff171d235
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,158 +0,0 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class UnityDownloadResumeFileOperation : UnityDownloadFileOperation
|
||||
{
|
||||
private VerifyTempFileOperation _verifyOperation;
|
||||
private long _fileOriginLength = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal UnityDownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url)
|
||||
: base(fileSystem, bundle, url)
|
||||
{
|
||||
}
|
||||
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);
|
||||
|
||||
// 获取下载起始位置
|
||||
_fileOriginLength = 0;
|
||||
long fileBeginLength = -1;
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
||||
if (fileInfo.Length >= _bundle.FileSize)
|
||||
{
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileBeginLength = fileInfo.Length;
|
||||
_fileOriginLength = fileBeginLength;
|
||||
DownloadedBytes = _fileOriginLength;
|
||||
}
|
||||
}
|
||||
|
||||
CreateWebRequest(fileBeginLength);
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = _fileOriginLength + (long)_webRequest.downloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
|
||||
UpdateWatchDog();
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.VerifyFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 在遇到特殊错误的时候删除文件
|
||||
ClearTempFileWhenError();
|
||||
|
||||
// 注意:最终释放请求器
|
||||
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 !";
|
||||
}
|
||||
}
|
||||
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 ClearTempFileWhenError()
|
||||
{
|
||||
if (_fileSystem.ResumeDownloadResponseCodes == null)
|
||||
return;
|
||||
|
||||
//说明:如果遇到以下错误返回码,验证失败直接删除文件
|
||||
if (_fileSystem.ResumeDownloadResponseCodes.Contains(HttpCode))
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
private void CreateWebRequest(long fileBeginLength)
|
||||
{
|
||||
var handler = new DownloadHandlerFile(_tempFilePath, true);
|
||||
handler.removeFileOnAbort = false;
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
if (fileBeginLength > 0)
|
||||
_webRequest.SetRequestHeader("Range", $"bytes={fileBeginLength}-");
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bfb785912326f942a31dc77762eb16a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -11,6 +11,11 @@ namespace YooAsset
|
||||
protected readonly Dictionary<string, string> _records = new Dictionary<string, string>(10000);
|
||||
protected string _packageRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
@@ -145,6 +150,10 @@ namespace YooAsset
|
||||
throw new YooFileSystemException($"{nameof(DefaultEditorFileSystem)} package root is null or empty !");
|
||||
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace YooAsset
|
||||
// 下载参数
|
||||
protected readonly DefaultEditorFileSystem _fileSystem;
|
||||
protected readonly DownloadFileOptions _options;
|
||||
protected UnityVirtualBundleRequestOperation _unityDownloadFileOp;
|
||||
protected IDownloadFileRequest _downloadFileOp;
|
||||
|
||||
protected int _requestCount = 0;
|
||||
protected float _tryAgainTimer = 0;
|
||||
@@ -68,29 +68,22 @@ namespace YooAsset
|
||||
|
||||
string url = GetRequestURL();
|
||||
int speed = _fileSystem.VirtualDownloadSpeed;
|
||||
_unityDownloadFileOp = new UnityVirtualBundleRequestOperation(Bundle, speed, url);
|
||||
_unityDownloadFileOp.StartOperation();
|
||||
var args = new DownloadSimulateRequestArgs(url, Bundle.FileSize, speed);
|
||||
_downloadFileOp = _fileSystem.DownloadBackend.CreateSimulateRequest(args);
|
||||
_downloadFileOp.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
if (IsWaitForAsyncComplete)
|
||||
_unityDownloadFileOp.WaitForAsyncComplete();
|
||||
|
||||
// 因为并发数量限制,下载器可能被挂起!
|
||||
if (_unityDownloadFileOp.Status == EOperationStatus.None)
|
||||
Progress = _downloadFileOp.DownloadProgress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
_unityDownloadFileOp.UpdateOperation();
|
||||
Progress = _unityDownloadFileOp.Progress;
|
||||
DownloadedBytes = _unityDownloadFileOp.DownloadedBytes;
|
||||
DownloadProgress = _unityDownloadFileOp.DownloadProgress;
|
||||
if (_unityDownloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_unityDownloadFileOp.Status == EOperationStatus.Succeed)
|
||||
if (_downloadFileOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_fileSystem.RecordDownloadFile(Bundle);
|
||||
_steps = ESteps.Done;
|
||||
@@ -101,13 +94,13 @@ namespace YooAsset
|
||||
if (IsWaitForAsyncComplete == false && _failedTryAgain > 0)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
YooLogger.Warning($"Failed download : {_unityDownloadFileOp.URL} Try again !");
|
||||
YooLogger.Warning($"Failed download : {_downloadFileOp.URL} Try again !");
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _unityDownloadFileOp.Error;
|
||||
Error = _downloadFileOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
@@ -130,13 +123,11 @@ namespace YooAsset
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
while (true)
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
if (ExecuteWhileDone())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
break;
|
||||
}
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Try load bundle {Bundle.BundleName} from remote !";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,11 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
internal class DefaultWebRemoteFileSystem : IFileSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
@@ -128,6 +133,10 @@ namespace YooAsset
|
||||
public virtual void OnCreate(string packageName, string packageRoot)
|
||||
{
|
||||
PackageName = packageName;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
|
||||
@@ -38,16 +38,16 @@ namespace YooAsset
|
||||
string fallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName);
|
||||
DownloadFileOptions options = new DownloadFileOptions(int.MaxValue);
|
||||
options.SetURL(mainURL, fallbackURL);
|
||||
|
||||
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
_loadWebAssetBundleOp = new LoadWebEncryptAssetBundleOperation(_bundle, options, _fileSystem.DecryptionServices);
|
||||
_loadWebAssetBundleOp = new LoadWebEncryptAssetBundleOperation(_bundle, options, _fileSystem.DecryptionServices, _fileSystem.DownloadBackend);
|
||||
_loadWebAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_loadWebAssetBundleOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
_loadWebAssetBundleOp = new LoadWebNormalAssetBundleOperation(_bundle, options, _fileSystem.DisableUnityWebCache);
|
||||
_loadWebAssetBundleOp = new LoadWebNormalAssetBundleOperation(_bundle, options, _fileSystem.DisableUnityWebCache, _fileSystem.DownloadBackend);
|
||||
_loadWebAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_loadWebAssetBundleOp);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace YooAsset
|
||||
{
|
||||
if (_requestWebPackageHashOp == null)
|
||||
{
|
||||
_requestWebPackageHashOp = new RequestWebPackageHashOperation(_fileSystem.RemoteServices, _fileSystem.PackageName, _packageVersion, _timeout);
|
||||
_requestWebPackageHashOp = new RequestWebPackageHashOperation(_fileSystem.RemoteServices, _fileSystem.DownloadBackend, _fileSystem.PackageName, _packageVersion, _timeout);
|
||||
_requestWebPackageHashOp.StartOperation();
|
||||
AddChildOperation(_requestWebPackageHashOp);
|
||||
}
|
||||
@@ -67,7 +67,8 @@ namespace YooAsset
|
||||
string packageName = _fileSystem.PackageName;
|
||||
var manifestServices = _fileSystem.ManifestServices;
|
||||
var remoteServices = _fileSystem.RemoteServices;
|
||||
_loadWebPackageManifestOp = new LoadWebPackageManifestOperation(manifestServices, remoteServices, packageName, _packageVersion, packageHash, _timeout);
|
||||
var downloadBackend = _fileSystem.DownloadBackend;
|
||||
_loadWebPackageManifestOp = new LoadWebPackageManifestOperation(manifestServices, remoteServices, downloadBackend, packageName, _packageVersion, packageHash, _timeout);
|
||||
_loadWebPackageManifestOp.StartOperation();
|
||||
AddChildOperation(_loadWebPackageManifestOp);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace YooAsset
|
||||
{
|
||||
if (_requestWebPackageVersionOp == null)
|
||||
{
|
||||
_requestWebPackageVersionOp = new RequestWebPackageVersionOperation(_fileSystem.RemoteServices, _fileSystem.PackageName, _appendTimeTicks, _timeout);
|
||||
_requestWebPackageVersionOp = new RequestWebPackageVersionOperation(_fileSystem.RemoteServices, _fileSystem.DownloadBackend, _fileSystem.PackageName, _appendTimeTicks, _timeout);
|
||||
_requestWebPackageVersionOp.StartOperation();
|
||||
AddChildOperation(_requestWebPackageVersionOp);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@ namespace YooAsset
|
||||
protected readonly Dictionary<string, string> _webFilePathMapping = new Dictionary<string, string>(10000);
|
||||
protected string _webPackageRoot = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
@@ -138,6 +143,10 @@ namespace YooAsset
|
||||
_webPackageRoot = GetDefaultWebPackageRoot(packageName);
|
||||
else
|
||||
_webPackageRoot = packageRoot;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
|
||||
@@ -41,13 +41,13 @@ namespace YooAsset
|
||||
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
_loadWebAssetBundleOp = new LoadWebEncryptAssetBundleOperation(_bundle, options, _fileSystem.DecryptionServices);
|
||||
_loadWebAssetBundleOp = new LoadWebEncryptAssetBundleOperation(_bundle, options, _fileSystem.DecryptionServices, _fileSystem.DownloadBackend);
|
||||
_loadWebAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_loadWebAssetBundleOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
_loadWebAssetBundleOp = new LoadWebNormalAssetBundleOperation(_bundle, options, _fileSystem.DisableUnityWebCache);
|
||||
_loadWebAssetBundleOp = new LoadWebNormalAssetBundleOperation(_bundle, options, _fileSystem.DisableUnityWebCache, _fileSystem.DownloadBackend);
|
||||
_loadWebAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_loadWebAssetBundleOp);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace YooAsset
|
||||
|
||||
private readonly DefaultWebServerFileSystem _fileSystem;
|
||||
private readonly int _timeout;
|
||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal LoadWebServerCatalogFileOperation(DefaultWebServerFileSystem fileSystem, int timeout)
|
||||
@@ -37,16 +37,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
|
||||
_webDataRequestOp.StartOperation();
|
||||
AddChildOperation(_webDataRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webDataRequestOp.UpdateOperation();
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.LoadCatalog;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace YooAsset
|
||||
private readonly string _packageVersion;
|
||||
private readonly string _packageHash;
|
||||
private readonly int _timeout;
|
||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private DeserializeManifestOperation _deserializer;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -48,16 +48,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetWebPackageManifestFilePath(_packageVersion);
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
|
||||
_webDataRequestOp.StartOperation();
|
||||
AddChildOperation(_webDataRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webDataRequestOp.UpdateOperation();
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.VerifyFileData;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace YooAsset
|
||||
private readonly DefaultWebServerFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
@@ -43,17 +43,16 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetWebPackageHashFilePath(_packageVersion);
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
Progress = _webTextRequestOp.Progress;
|
||||
Progress = _webTextRequestOp.DownloadProgress;
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageHash = _webTextRequestOp.Result;
|
||||
if (string.IsNullOrEmpty(PackageHash))
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace YooAsset
|
||||
|
||||
private readonly DefaultWebServerFileSystem _fileSystem;
|
||||
private readonly int _timeout;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
@@ -41,16 +41,15 @@ namespace YooAsset
|
||||
{
|
||||
string filePath = _fileSystem.GetWebPackageVersionFilePath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageVersion = _webTextRequestOp.Result;
|
||||
if (string.IsNullOrEmpty(PackageVersion))
|
||||
|
||||
@@ -16,19 +16,21 @@ namespace YooAsset
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly DownloadFileOptions _options;
|
||||
private readonly IWebDecryptionServices _decryptionServices;
|
||||
private UnityWebDataRequestOperation _unityWebDataRequestOp;
|
||||
private readonly IDownloadBackend _downloadBackend;
|
||||
private IDownloadBytesRequest _unityWebDataRequestOp;
|
||||
|
||||
private int _requestCount = 0;
|
||||
private float _tryAgainTimer = 0;
|
||||
private int _failedTryAgain;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal LoadWebEncryptAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options, IWebDecryptionServices decryptionServices)
|
||||
internal LoadWebEncryptAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options, IWebDecryptionServices decryptionServices, IDownloadBackend downloadBackend)
|
||||
{
|
||||
_bundle = bundle;
|
||||
_options = options;
|
||||
_failedTryAgain = options.FailedTryAgain;
|
||||
_decryptionServices = decryptionServices;
|
||||
_downloadBackend = downloadBackend;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -52,24 +54,23 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
string url = GetRequestURL();
|
||||
_unityWebDataRequestOp = new UnityWebDataRequestOperation(url, 0);
|
||||
_unityWebDataRequestOp.StartOperation();
|
||||
AddChildOperation(_unityWebDataRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, 0, 0);
|
||||
_unityWebDataRequestOp = _downloadBackend.CreateBytesRequest(args);
|
||||
_unityWebDataRequestOp.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
_unityWebDataRequestOp.UpdateOperation();
|
||||
Progress = _unityWebDataRequestOp.Progress;
|
||||
Progress = _unityWebDataRequestOp.DownloadProgress;
|
||||
DownloadProgress = _unityWebDataRequestOp.DownloadProgress;
|
||||
DownloadedBytes = _unityWebDataRequestOp.DownloadedBytes;
|
||||
if (_unityWebDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (_unityWebDataRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_unityWebDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
AssetBundle assetBundle = LoadEncryptedAssetBundle(_unityWebDataRequestOp.Result);
|
||||
if (assetBundle == null)
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace YooAsset
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly DownloadFileOptions _options;
|
||||
private readonly bool _disableUnityWebCache;
|
||||
private UnityAssetBundleRequestOperation _unityAssetBundleRequestOp;
|
||||
private readonly IDownloadBackend _downloadBackend;
|
||||
private IDownloadAssetBundleRequest _unityAssetBundleRequestOp;
|
||||
|
||||
private int _requestCount = 0;
|
||||
private float _tryAgainTimer = 0;
|
||||
@@ -24,12 +25,13 @@ namespace YooAsset
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal LoadWebNormalAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options, bool disableUnityWebCache)
|
||||
internal LoadWebNormalAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options, bool disableUnityWebCache, IDownloadBackend downloadBackend)
|
||||
{
|
||||
_bundle = bundle;
|
||||
_options = options;
|
||||
_failedTryAgain = options.FailedTryAgain;
|
||||
_disableUnityWebCache = disableUnityWebCache;
|
||||
_downloadBackend = downloadBackend;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -44,23 +46,22 @@ namespace YooAsset
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
string url = GetRequestURL();
|
||||
_unityAssetBundleRequestOp = new UnityAssetBundleRequestOperation(_bundle, _disableUnityWebCache, url);
|
||||
_unityAssetBundleRequestOp.StartOperation();
|
||||
AddChildOperation(_unityAssetBundleRequestOp);
|
||||
var args = new DownloadAssetBundleRequestArgs(url, 0, 0, _disableUnityWebCache, _bundle.FileHash, _bundle.UnityCRC);
|
||||
_unityAssetBundleRequestOp = _downloadBackend.CreateAssetBundleRequest(args);
|
||||
_unityAssetBundleRequestOp.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
_unityAssetBundleRequestOp.UpdateOperation();
|
||||
Progress = _unityAssetBundleRequestOp.Progress;
|
||||
Progress = _unityAssetBundleRequestOp.DownloadProgress;
|
||||
DownloadedBytes = _unityAssetBundleRequestOp.DownloadedBytes;
|
||||
DownloadProgress = _unityAssetBundleRequestOp.DownloadProgress;
|
||||
if (_unityAssetBundleRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_unityAssetBundleRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_unityAssetBundleRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
@@ -13,11 +13,12 @@ internal class LoadWebPackageManifestOperation : AsyncOperationBase
|
||||
|
||||
private readonly IManifestRestoreServices _manifestServices;
|
||||
private readonly IRemoteServices _remoteServices;
|
||||
private readonly IDownloadBackend _downloadBackend;
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private readonly string _packageHash;
|
||||
private readonly int _timeout;
|
||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private DeserializeManifestOperation _deserializer;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
@@ -28,11 +29,12 @@ internal class LoadWebPackageManifestOperation : AsyncOperationBase
|
||||
public PackageManifest Manifest { private set; get; }
|
||||
|
||||
|
||||
internal LoadWebPackageManifestOperation(IManifestRestoreServices manifestServices, IRemoteServices remoteServices,
|
||||
internal LoadWebPackageManifestOperation(IManifestRestoreServices manifestServices, IRemoteServices remoteServices, IDownloadBackend downloadBackend,
|
||||
string packageName, string packageVersion, string packageHash, int timeout)
|
||||
{
|
||||
_manifestServices = manifestServices;
|
||||
_remoteServices = remoteServices;
|
||||
_downloadBackend = downloadBackend;
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
_packageHash = packageHash;
|
||||
@@ -54,17 +56,16 @@ internal class LoadWebPackageManifestOperation : AsyncOperationBase
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_packageName, _packageVersion);
|
||||
string url = GetRequestURL(fileName);
|
||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
|
||||
_webDataRequestOp.StartOperation();
|
||||
AddChildOperation(_webDataRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webDataRequestOp = _downloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webDataRequestOp.UpdateOperation();
|
||||
Progress = _webDataRequestOp.Progress;
|
||||
Progress = _webDataRequestOp.DownloadProgress;
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.VerifyFileData;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@ internal class RequestWebPackageHashOperation : AsyncOperationBase
|
||||
}
|
||||
|
||||
private readonly IRemoteServices _remoteServices;
|
||||
private readonly IDownloadBackend _downloadBackend;
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -23,9 +24,10 @@ internal class RequestWebPackageHashOperation : AsyncOperationBase
|
||||
public string PackageHash { private set; get; }
|
||||
|
||||
|
||||
public RequestWebPackageHashOperation(IRemoteServices remoteServices, string packageName, string packageVersion, int timeout)
|
||||
public RequestWebPackageHashOperation(IRemoteServices remoteServices, IDownloadBackend downloadBackend, string packageName, string packageVersion, int timeout)
|
||||
{
|
||||
_remoteServices = remoteServices;
|
||||
_downloadBackend = downloadBackend;
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
@@ -46,17 +48,16 @@ internal class RequestWebPackageHashOperation : AsyncOperationBase
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(_packageName, _packageVersion);
|
||||
string url = GetRequestURL(fileName);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webTextRequestOp = _downloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
Progress = _webTextRequestOp.Progress;
|
||||
Progress = _webTextRequestOp.DownloadProgress;
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageHash = _webTextRequestOp.Result;
|
||||
if (string.IsNullOrEmpty(PackageHash))
|
||||
|
||||
@@ -10,10 +10,11 @@ internal class RequestWebPackageVersionOperation : AsyncOperationBase
|
||||
}
|
||||
|
||||
private readonly IRemoteServices _remoteServices;
|
||||
private readonly IDownloadBackend _downloadBackend;
|
||||
private readonly string _packageName;
|
||||
private readonly bool _appendTimeTicks;
|
||||
private readonly int _timeout;
|
||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -23,9 +24,10 @@ internal class RequestWebPackageVersionOperation : AsyncOperationBase
|
||||
public string PackageVersion { private set; get; }
|
||||
|
||||
|
||||
public RequestWebPackageVersionOperation(IRemoteServices remoteServices, string packageName, bool appendTimeTicks, int timeout)
|
||||
public RequestWebPackageVersionOperation(IRemoteServices remoteServices, IDownloadBackend downloadBackend, string packageName, bool appendTimeTicks, int timeout)
|
||||
{
|
||||
_remoteServices = remoteServices;
|
||||
_downloadBackend = downloadBackend;
|
||||
_packageName = packageName;
|
||||
_appendTimeTicks = appendTimeTicks;
|
||||
_timeout = timeout;
|
||||
@@ -46,17 +48,16 @@ internal class RequestWebPackageVersionOperation : AsyncOperationBase
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_packageName);
|
||||
string url = GetRequestURL(fileName);
|
||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
|
||||
_webTextRequestOp.StartOperation();
|
||||
AddChildOperation(_webTextRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, 0);
|
||||
_webTextRequestOp = _downloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
_webTextRequestOp.UpdateOperation();
|
||||
Progress = _webTextRequestOp.Progress;
|
||||
Progress = _webTextRequestOp.DownloadProgress;
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageVersion = _webTextRequestOp.Result;
|
||||
if (string.IsNullOrEmpty(PackageVersion))
|
||||
|
||||
@@ -139,6 +139,19 @@ namespace YooAsset
|
||||
Childs.Add(child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除子任务
|
||||
/// </summary>
|
||||
internal void RemoveChildOperation(AsyncOperationBase child)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (Childs.Contains(child) == false)
|
||||
throw new YooInternalException($"The child node {child.GetType().Name} not exists !");
|
||||
#endif
|
||||
|
||||
Childs.Remove(child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步操作说明
|
||||
/// </summary>
|
||||
|
||||
@@ -21,14 +21,16 @@ public class CopyBuildinManifestOperation : GameAsyncOperation
|
||||
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private readonly IDownloadBackend _backend;
|
||||
private IDownloadFileRequest _hashFileRequestOp;
|
||||
private IDownloadFileRequest _manifestFileRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
private UnityWebFileRequestOperation _hashFileRequestOp;
|
||||
private UnityWebFileRequestOperation _manifestFileRequestOp;
|
||||
|
||||
public CopyBuildinManifestOperation(string packageName, string packageVersion)
|
||||
{
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
_backend = new UnityWebRequestBackend();
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
@@ -58,14 +60,15 @@ public class CopyBuildinManifestOperation : GameAsyncOperation
|
||||
string sourcePath = GetBuildinHashFilePath();
|
||||
string destPath = GetCacheHashFilePath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(sourcePath);
|
||||
_hashFileRequestOp = new UnityWebFileRequestOperation(url, destPath, 60);
|
||||
OperationSystem.StartOperation(_packageName, _hashFileRequestOp);
|
||||
var args = new DownloadFileRequestArgs(url, destPath, 60, 0);
|
||||
_hashFileRequestOp = _backend.CreateFileRequest(args);
|
||||
_hashFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_hashFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_hashFileRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_hashFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.CheckManifestFile;
|
||||
}
|
||||
@@ -97,14 +100,15 @@ public class CopyBuildinManifestOperation : GameAsyncOperation
|
||||
string sourcePath = GetBuildinManifestFilePath();
|
||||
string destPath = GetCacheManifestFilePath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(sourcePath);
|
||||
_manifestFileRequestOp = new UnityWebFileRequestOperation(url, destPath, 60);
|
||||
OperationSystem.StartOperation(_packageName, _manifestFileRequestOp);
|
||||
var args = new DownloadFileRequestArgs(url, destPath, 60, 0);
|
||||
_manifestFileRequestOp = _backend.CreateFileRequest(args);
|
||||
_manifestFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_manifestFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_manifestFileRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_manifestFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
@@ -17,7 +17,8 @@ public class GetBuildinPackageVersionOperation : GameAsyncOperation
|
||||
}
|
||||
|
||||
private readonly string _packageName;
|
||||
private UnityWebTextRequestOperation _versionFileRequestOp;
|
||||
private readonly IDownloadBackend _backend;
|
||||
private IDownloadTextRequest _versionFileRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
@@ -28,6 +29,7 @@ public class GetBuildinPackageVersionOperation : GameAsyncOperation
|
||||
public GetBuildinPackageVersionOperation(string packageName)
|
||||
{
|
||||
_packageName = packageName;
|
||||
_backend = new UnityWebRequestBackend();
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
@@ -44,14 +46,15 @@ public class GetBuildinPackageVersionOperation : GameAsyncOperation
|
||||
{
|
||||
string filePath = GetBuildinPackageVersionFilePath();
|
||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||
_versionFileRequestOp = new UnityWebTextRequestOperation(url, 60);
|
||||
OperationSystem.StartOperation(_packageName, _versionFileRequestOp);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_versionFileRequestOp = _backend.CreateTextRequest(args);
|
||||
_versionFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_versionFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_versionFileRequestOp.Status == EOperationStatus.Succeed)
|
||||
if (_versionFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
Reference in New Issue
Block a user