update yooasset2.0

This commit is contained in:
hevinci
2023-09-20 16:09:52 +08:00
parent 880b6d429d
commit 01cf9ccd54
369 changed files with 6557 additions and 5490 deletions

View File

@@ -0,0 +1,41 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine.Networking;
namespace YooAsset
{
/// <summary>
/// 自定义下载器的请求委托
/// </summary>
public delegate UnityWebRequest DownloadRequestDelegate(string url);
internal static class DownloadHelper
{
/// <summary>
/// 下载失败后清理文件的HTTP错误码
/// </summary>
public static List<long> ClearFileResponseCodes { set; get; }
/// <summary>
/// 自定义下载器的请求委托
/// </summary>
public static DownloadRequestDelegate RequestDelegate = null;
/// <summary>
/// 创建一个新的网络请求
/// </summary>
public static UnityWebRequest NewRequest(string requestURL)
{
UnityWebRequest webRequest;
if (RequestDelegate != null)
webRequest = RequestDelegate.Invoke(requestURL);
else
webRequest = new UnityWebRequest(requestURL, UnityWebRequest.kHttpVerbGET);
return webRequest;
}
}
}

View File

@@ -0,0 +1,132 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
namespace YooAsset
{
/// <summary>
/// 1. 保证每一时刻资源文件只存在一个下载器
/// 2. 保证下载器下载完成后立刻验证并缓存
/// 3. 保证资源文件不会被重复下载
/// </summary>
internal class DownloadManager
{
private readonly Dictionary<string, DownloaderBase> _downloaders = new Dictionary<string, DownloaderBase>(1000);
private readonly List<string> _removeList = new List<string>(1000);
private uint _breakpointResumeFileSize;
/// <summary>
/// 所属包裹
/// </summary>
public readonly string PackageName;
public DownloadManager(string packageName)
{
PackageName = packageName;
}
/// <summary>
/// 初始化
/// </summary>
public void Initialize(uint breakpointResumeFileSize)
{
_breakpointResumeFileSize = breakpointResumeFileSize;
}
/// <summary>
/// 更新下载器
/// </summary>
public void Update()
{
// 更新下载器
_removeList.Clear();
foreach (var valuePair in _downloaders)
{
var downloader = valuePair.Value;
downloader.Update();
if (downloader.IsDone())
_removeList.Add(valuePair.Key);
}
// 移除下载器
foreach (var key in _removeList)
{
_downloaders.Remove(key);
}
}
/// <summary>
/// 销毁所有下载器
/// </summary>
public void DestroyAll()
{
foreach (var valuePair in _downloaders)
{
var downloader = valuePair.Value;
downloader.Abort();
}
_downloaders.Clear();
_removeList.Clear();
}
/// <summary>
/// 创建下载器
/// 注意:只有第一次请求的参数才有效
/// </summary>
public DownloaderBase CreateDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60)
{
// 查询存在的下载器
if (_downloaders.TryGetValue(bundleInfo.CachedDataFilePath, out var downloader))
return downloader;
// 如果资源已经缓存
if (bundleInfo.IsCached())
{
var completedDownloader = new CompletedDownloader(bundleInfo);
return completedDownloader;
}
// 创建新的下载器
YooLogger.Log($"Beginning to download bundle : {bundleInfo.Bundle.BundleName} URL : {bundleInfo.RemoteMainURL}");
#if UNITY_WEBGL
if (bundleInfo.Bundle.Buildpipeline == DefaultBuildPipeline.RawFileBuildPipelineName)
{
FileUtility.CreateFileDirectory(bundleInfo.CachedDataFilePath);
System.Type requesterType = typeof(FileGeneralRequest);
DownloaderBase newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
_downloaders.Add(bundleInfo.CachedDataFilePath, newDownloader);
return newDownloader;
}
else
{
System.Type requesterType = typeof(AssetBundleWebRequest);
WebDownloader newDownloader = new WebDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
_downloaders.Add(bundleInfo.CachedDataFilePath, newDownloader);
return newDownloader;
}
#else
FileUtility.CreateFileDirectory(bundleInfo.CachedDataFilePath);
bool resumeDownload = bundleInfo.Bundle.FileSize >= _breakpointResumeFileSize;
if (resumeDownload)
{
System.Type requesterType = typeof(FileResumeRequest);
DownloaderBase newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
_downloaders.Add(bundleInfo.CachedDataFilePath, newDownloader);
return newDownloader;
}
else
{
System.Type requesterType = typeof(FileGeneralRequest);
DownloaderBase newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
_downloaders.Add(bundleInfo.CachedDataFilePath, newDownloader);
return newDownloader;
}
#endif
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a439c9a8f36dcc942b92a8e8af927237
guid: 6fbbbfe01e018b241bf33469f870a4b8
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,30 +0,0 @@

namespace YooAsset
{
public struct DownloadReport
{
/// <summary>
/// 下载进度0f~1f
/// </summary>
public float Progress;
/// <summary>
/// 需要下载的总字节数
/// </summary>
public ulong TotalSize;
/// <summary>
/// 已经下载的字节数
/// </summary>
public ulong DownloadedBytes;
public static DownloadReport CreateDefaultReport()
{
DownloadReport report = new DownloadReport();
report.Progress = 0f;
report.TotalSize = 0;
report.DownloadedBytes = 0;
return report;
}
}
}

View File

@@ -0,0 +1,36 @@

namespace YooAsset
{
public struct DownloadStatus
{
/// <summary>
/// 下载是否完成
/// </summary>
public bool IsDone;
/// <summary>
/// 下载进度0f~1f
/// </summary>
public float Progress;
/// <summary>
/// 需要下载的总字节数
/// </summary>
public ulong TotalBytes;
/// <summary>
/// 已经下载的字节数
/// </summary>
public ulong DownloadedBytes;
public static DownloadStatus CreateDefaultStatus()
{
DownloadStatus status = new DownloadStatus();
status.IsDone = false;
status.Progress = 0f;
status.TotalBytes = 0;
status.DownloadedBytes = 0;
return status;
}
}
}

View File

@@ -1,184 +0,0 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine.Networking;
namespace YooAsset
{
/// <summary>
/// 自定义下载器的请求委托
/// </summary>
public delegate UnityWebRequest DownloadRequestDelegate(string url);
/// <summary>
/// 1. 保证每一时刻资源文件只存在一个下载器
/// 2. 保证下载器下载完成后立刻验证并缓存
/// 3. 保证资源文件不会被重复下载
/// </summary>
internal static class DownloadSystem
{
private static readonly Dictionary<string, DownloaderBase> _downloaderDic = new Dictionary<string, DownloaderBase>();
private static readonly List<string> _removeList = new List<string>(100);
/// <summary>
/// 自定义下载器的请求委托
/// </summary>
public static DownloadRequestDelegate RequestDelegate = null;
/// <summary>
/// 自定义的证书认证实例
/// </summary>
public static CertificateHandler CertificateHandlerInstance = null;
/// <summary>
/// 网络重定向次数
/// </summary>
public static int RedirectLimit { set; get; } = -1;
/// <summary>
/// 启用断点续传功能文件的最小字节数
/// </summary>
public static int BreakpointResumeFileSize { set; get; } = int.MaxValue;
/// <summary>
/// 下载失败后清理文件的HTTP错误码
/// </summary>
public static List<long> ClearFileResponseCodes { set; get; }
/// <summary>
/// 初始化下载器
/// </summary>
public static void Initialize()
{
}
/// <summary>
/// 更新下载器
/// </summary>
public static void Update()
{
// 更新下载器
_removeList.Clear();
foreach (var valuePair in _downloaderDic)
{
var downloader = valuePair.Value;
downloader.Update();
if (downloader.IsDone())
_removeList.Add(valuePair.Key);
}
// 移除下载器
foreach (var key in _removeList)
{
_downloaderDic.Remove(key);
}
}
/// <summary>
/// 销毁所有下载器
/// </summary>
public static void DestroyAll()
{
foreach (var valuePair in _downloaderDic)
{
var downloader = valuePair.Value;
downloader.Abort();
}
_downloaderDic.Clear();
_removeList.Clear();
RequestDelegate = null;
CertificateHandlerInstance = null;
BreakpointResumeFileSize = int.MaxValue;
ClearFileResponseCodes = null;
}
/// <summary>
/// 创建下载器
/// 注意:只有第一次请求的参数才有效
/// </summary>
public static DownloaderBase CreateDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60)
{
// 查询存在的下载器
if (_downloaderDic.TryGetValue(bundleInfo.Bundle.CachedDataFilePath, out var downloader))
return downloader;
// 如果资源已经缓存
if (CacheSystem.IsCached(bundleInfo.Bundle.PackageName, bundleInfo.Bundle.CacheGUID))
{
var completedDownloader = new CompletedDownloader(bundleInfo);
return completedDownloader;
}
// 创建新的下载器
YooLogger.Log($"Beginning to download bundle : {bundleInfo.Bundle.BundleName} URL : {bundleInfo.RemoteMainURL}");
#if UNITY_WEBGL
if (bundleInfo.Bundle.IsRawFile)
{
FileUtility.CreateFileDirectory(bundleInfo.Bundle.CachedDataFilePath);
DownloaderBase newDownloader = new FileGeneralDownloader(bundleInfo, failedTryAgain, timeout);
_downloaderDic.Add(bundleInfo.Bundle.CachedDataFilePath, newDownloader);
return newDownloader;
}
else
{
WebDownloader newDownloader = new WebDownloader(bundleInfo, failedTryAgain, timeout);
_downloaderDic.Add(bundleInfo.Bundle.CachedDataFilePath, newDownloader);
return newDownloader;
}
#else
FileUtility.CreateFileDirectory(bundleInfo.Bundle.CachedDataFilePath);
bool resumeDownload = bundleInfo.Bundle.FileSize >= BreakpointResumeFileSize;
DownloaderBase newDownloader;
if (resumeDownload)
newDownloader = new FileResumeDownloader(bundleInfo, failedTryAgain, timeout);
else
newDownloader = new FileGeneralDownloader(bundleInfo, failedTryAgain, timeout);
_downloaderDic.Add(bundleInfo.Bundle.CachedDataFilePath, newDownloader);
return newDownloader;
#endif
}
/// <summary>
/// 创建一个新的网络请求
/// </summary>
public static UnityWebRequest NewRequest(string requestURL)
{
UnityWebRequest webRequest;
if (RequestDelegate != null)
webRequest = RequestDelegate.Invoke(requestURL);
else
webRequest = new UnityWebRequest(requestURL, UnityWebRequest.kHttpVerbGET);
SetUnityWebRequestParam(webRequest);
return webRequest;
}
/// <summary>
/// 设置网络请求的自定义参数
/// </summary>
private static void SetUnityWebRequestParam(UnityWebRequest webRequest)
{
if (RedirectLimit >= 0)
webRequest.redirectLimit = RedirectLimit;
if (CertificateHandlerInstance != null)
{
webRequest.certificateHandler = CertificateHandlerInstance;
webRequest.disposeCertificateHandlerOnDispose = false;
}
}
/// <summary>
/// 获取下载器的总数
/// </summary>
public static int GetDownloaderTotalCount()
{
return _downloaderDic.Count;
}
}
}

View File

@@ -1,12 +1,14 @@

using UnityEngine;
namespace YooAsset
{
internal sealed class CompletedDownloader : DownloaderBase
{
public CompletedDownloader(BundleInfo bundleInfo) : base(bundleInfo, 0, 0)
public CompletedDownloader(BundleInfo bundleInfo) : base(bundleInfo, null, 0, 0)
{
_downloadProgress = 1f;
_downloadedBytes = (ulong)bundleInfo.Bundle.FileSize;
DownloadProgress = 1f;
DownloadedBytes = (ulong)bundleInfo.Bundle.FileSize;
_status = EStatus.Succeed;
}
@@ -19,5 +21,9 @@ namespace YooAsset
public override void Abort()
{
}
public override AssetBundle GetAssetBundle()
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -1,4 +1,4 @@
using System.IO;
using System;
using UnityEngine;
using UnityEngine.Networking;
@@ -14,22 +14,19 @@ namespace YooAsset
}
protected readonly BundleInfo _bundleInfo;
protected readonly System.Type _requesterType;
protected readonly int _timeout;
protected int _failedTryAgain;
protected UnityWebRequest _webRequest;
protected IWebRequester _requester;
protected EStatus _status = EStatus.None;
protected string _lastError = string.Empty;
protected long _lastCode = 0;
protected string _lastestNetError = string.Empty;
protected long _lastestHttpCode = 0;
// 请求次数
protected int _requestCount = 0;
protected string _requestURL;
// 下载进度
protected float _downloadProgress = 0f;
protected ulong _downloadedBytes = 0;
// 超时相关
protected bool _isAbort = false;
protected ulong _latestDownloadBytes;
@@ -45,29 +42,25 @@ namespace YooAsset
/// <summary>
/// 下载进度0f~1f
/// </summary>
public float DownloadProgress
{
get { return _downloadProgress; }
}
public float DownloadProgress { protected set; get; }
/// <summary>
/// 已经下载的总字节数
/// </summary>
public ulong DownloadedBytes
{
get { return _downloadedBytes; }
}
public ulong DownloadedBytes { protected set; get; }
public DownloaderBase(BundleInfo bundleInfo, int failedTryAgain, int timeout)
public DownloaderBase(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout)
{
_bundleInfo = bundleInfo;
_requesterType = requesterType;
_failedTryAgain = failedTryAgain;
_timeout = timeout;
}
public abstract void SendRequest(params object[] param);
public abstract void SendRequest(params object[] args);
public abstract void Update();
public abstract void Abort();
public abstract AssetBundle GetAssetBundle();
/// <summary>
/// 获取下载文件的大小
@@ -123,7 +116,7 @@ namespace YooAsset
/// </summary>
public string GetLastError()
{
return $"Failed to download : {_requestURL} Error : {_lastError} Code : {_lastCode}";
return $"Failed to download : {_requestURL} Error : {_lastestNetError} Code : {_lastestHttpCode}";
}
@@ -158,36 +151,11 @@ namespace YooAsset
if (offset > _timeout)
{
YooLogger.Warning($"Web file request timeout : {_requestURL}");
_webRequest.Abort();
if(_requester != null)
_requester.Abort();
_isAbort = true;
}
}
}
/// <summary>
/// 缓存下载文件
/// </summary>
protected void CachingFile(string tempFilePath)
{
string infoFilePath = _bundleInfo.Bundle.CachedInfoFilePath;
string dataFilePath = _bundleInfo.Bundle.CachedDataFilePath;
string dataFileCRC = _bundleInfo.Bundle.FileCRC;
long dataFileSize = _bundleInfo.Bundle.FileSize;
if (File.Exists(infoFilePath))
File.Delete(infoFilePath);
if (File.Exists(dataFilePath))
File.Delete(dataFilePath);
FileInfo fileInfo = new FileInfo(tempFilePath);
fileInfo.MoveTo(dataFilePath);
// 写入信息文件记录验证数据
CacheFileInfo.WriteInfoToFile(infoFilePath, dataFileCRC, dataFileSize);
// 记录缓存文件
var wrapper = new PackageCache.RecordWrapper(infoFilePath, dataFilePath, dataFileCRC, dataFileSize);
CacheSystem.RecordFile(_bundleInfo.Bundle.PackageName, _bundleInfo.Bundle.CacheGUID, wrapper);
}
}
}

View File

@@ -3,14 +3,13 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
/// <summary>
/// 普通的下载器
/// 文件下载器
/// </summary>
internal sealed class FileGeneralDownloader : DownloaderBase
internal sealed class FileDownloader : DownloaderBase
{
private enum ESteps
{
@@ -25,16 +24,13 @@ namespace YooAsset
Done,
}
private readonly string _tempFilePath;
private VerifyTempFileOperation _verifyFileOp = null;
private ESteps _steps = ESteps.None;
public FileGeneralDownloader(BundleInfo bundleInfo, int failedTryAgain, int timeout) : base(bundleInfo, failedTryAgain, timeout)
public FileDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
{
_tempFilePath = bundleInfo.Bundle.TempDataFilePath;
}
public override void SendRequest(params object[] param)
public override void SendRequest(params object[] args)
{
if (_steps == ESteps.None)
{
@@ -55,8 +51,8 @@ namespace YooAsset
_requestURL = GetRequestURL();
// 重置变量
_downloadProgress = 0f;
_downloadedBytes = 0;
DownloadProgress = 0f;
DownloadedBytes = 0;
// 重置变量
_isAbort = false;
@@ -64,83 +60,51 @@ namespace YooAsset
_latestDownloadRealtime = Time.realtimeSinceStartup;
// 重置计时器
if(_tryAgainTimer > 0f)
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
// 删除临时文件
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
_steps = ESteps.CreateDownloader;
}
// 创建下载器
if (_steps == ESteps.CreateDownloader)
{
_webRequest = DownloadSystem.NewRequest(_requestURL);
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
_requester = (IWebRequester)Activator.CreateInstance(_requesterType);
_requester.Create(_requestURL, _bundleInfo);
_steps = ESteps.CheckDownload;
}
// 检测下载结果
if (_steps == ESteps.CheckDownload)
{
_downloadProgress = _webRequest.downloadProgress;
_downloadedBytes = _webRequest.downloadedBytes;
if (_webRequest.isDone == false)
_requester.Update();
DownloadedBytes = _requester.DownloadedBytes;
DownloadProgress = _requester.DownloadProgress;
if (_requester.IsDone() == false)
{
CheckTimeout();
return;
}
bool hasError = false;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
_lastestNetError = _requester.RequestNetError;
_lastestHttpCode = _requester.RequestHttpCode;
if (_requester.Status != ERequestStatus.Success)
{
hasError = true;
_lastError = _webRequest.error;
_lastCode = _webRequest.responseCode;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
hasError = true;
_lastError = _webRequest.error;
_lastCode = _webRequest.responseCode;
}
#endif
// 如果网络异常
if (hasError)
{
// 下载失败之后删除文件
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
_steps = ESteps.TryAgain;
}
else
{
_steps = ESteps.VerifyTempFile;
}
// 最终释放下载器
DisposeWebRequest();
}
// 验证下载文件
if (_steps == ESteps.VerifyTempFile)
{
VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.Bundle.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
_verifyFileOp = VerifyTempFileOperation.CreateOperation(element);
OperationSystem.StartOperation(_verifyFileOp);
OperationSystem.StartOperation(_bundleInfo.Bundle.PackageName, _verifyFileOp);
_steps = ESteps.WaitingVerifyTempFile;
}
@@ -159,10 +123,11 @@ namespace YooAsset
}
else
{
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
string tempFilePath = _bundleInfo.TempDataFilePath;
if (File.Exists(tempFilePath))
File.Delete(tempFilePath);
_lastError = _verifyFileOp.Error;
_lastestNetError = _verifyFileOp.Error;
_steps = ESteps.TryAgain;
}
}
@@ -172,15 +137,13 @@ namespace YooAsset
{
try
{
CachingFile(_tempFilePath);
CachingFile();
_status = EStatus.Succeed;
_steps = ESteps.Done;
_lastError = string.Empty;
_lastCode = 0;
}
catch (Exception e)
{
_lastError = e.Message;
_lastestNetError = e.Message;
_steps = ESteps.TryAgain;
}
}
@@ -207,23 +170,47 @@ namespace YooAsset
}
public override void Abort()
{
if (_requester != null)
_requester.Abort();
if (IsDone() == false)
{
_status = EStatus.Failed;
_steps = ESteps.Done;
_lastError = "user abort";
_lastCode = 0;
DisposeWebRequest();
_lastestNetError = "user abort";
_lastestHttpCode = 0;
}
}
private void DisposeWebRequest()
public override AssetBundle GetAssetBundle()
{
if (_webRequest != null)
{
_webRequest.Dispose();
_webRequest = null;
}
throw new NotImplementedException();
}
/// <summary>
/// 缓存下载文件
/// </summary>
private void CachingFile()
{
string tempFilePath = _bundleInfo.TempDataFilePath;
string infoFilePath = _bundleInfo.CachedInfoFilePath;
string dataFilePath = _bundleInfo.CachedDataFilePath;
string dataFileCRC = _bundleInfo.Bundle.FileCRC;
long dataFileSize = _bundleInfo.Bundle.FileSize;
if (File.Exists(infoFilePath))
File.Delete(infoFilePath);
if (File.Exists(dataFilePath))
File.Delete(dataFilePath);
// 移动临时文件路径
FileInfo fileInfo = new FileInfo(tempFilePath);
fileInfo.MoveTo(dataFilePath);
// 写入信息文件记录验证数据
CacheFileInfo.WriteInfoToFile(infoFilePath, dataFileCRC, dataFileSize);
// 记录缓存文件
_bundleInfo.CacheRecord();
}
}
}

View File

@@ -1,295 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
/// <summary>
/// 断点续传下载器
/// </summary>
internal sealed class FileResumeDownloader : DownloaderBase
{
private enum ESteps
{
None,
CheckTempFile,
WaitingCheckTempFile,
PrepareDownload,
CreateDownloader,
CheckDownload,
VerifyTempFile,
WaitingVerifyTempFile,
CachingFile,
TryAgain,
Done,
}
private readonly string _tempFilePath;
private DownloadHandlerFileRange _downloadHandle = null;
private VerifyTempFileOperation _checkFileOp = null;
private VerifyTempFileOperation _verifyFileOp = null;
private ESteps _steps = ESteps.None;
// 重置变量
private ulong _fileOriginLength;
public FileResumeDownloader(BundleInfo bundleInfo, int failedTryAgain, int timeout) : base(bundleInfo, failedTryAgain, timeout)
{
_tempFilePath = bundleInfo.Bundle.TempDataFilePath;
}
public override void SendRequest(params object[] param)
{
if (_steps == ESteps.None)
{
_steps = ESteps.CheckTempFile;
}
}
public override void Update()
{
if (_steps == ESteps.None)
return;
if (IsDone())
return;
// 检测临时文件
if (_steps == ESteps.CheckTempFile)
{
VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.Bundle.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
_checkFileOp = VerifyTempFileOperation.CreateOperation(element);
OperationSystem.StartOperation(_checkFileOp);
_steps = ESteps.WaitingCheckTempFile;
}
// 等待检测结果
if (_steps == ESteps.WaitingCheckTempFile)
{
if (WaitForAsyncComplete)
_checkFileOp.Update();
if (_checkFileOp.IsDone == false)
return;
if (_checkFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CachingFile;
}
else
{
if (_checkFileOp.VerifyResult == EVerifyResult.FileOverflow)
{
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
}
_steps = ESteps.PrepareDownload;
}
}
// 创建下载器
if (_steps == ESteps.PrepareDownload)
{
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
_downloadProgress = 0f;
_downloadedBytes = 0;
// 重置变量
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
_fileOriginLength = 0;
// 重置计时器
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
_steps = ESteps.CreateDownloader;
}
// 创建下载器
if (_steps == ESteps.CreateDownloader)
{
long fileLength = -1;
if (File.Exists(_tempFilePath))
{
FileInfo fileInfo = new FileInfo(_tempFilePath);
fileLength = fileInfo.Length;
_fileOriginLength = (ulong)fileLength;
_downloadedBytes = _fileOriginLength;
}
#if UNITY_2019_4_OR_NEWER
_webRequest = DownloadSystem.NewRequest(_requestURL);
var handler = new DownloadHandlerFile(_tempFilePath, true);
handler.removeFileOnAbort = false;
#else
_webRequest = DownloadSystem.NewRequest(_requestURL);
var handler = new DownloadHandlerFileRange(_tempFilePath, _bundleInfo.Bundle.FileSize, _webRequest);
_downloadHandle = handler;
#endif
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
if (fileLength > 0)
_webRequest.SetRequestHeader("Range", $"bytes={fileLength}-");
_webRequest.SendWebRequest();
_steps = ESteps.CheckDownload;
}
// 检测下载结果
if (_steps == ESteps.CheckDownload)
{
_downloadProgress = _webRequest.downloadProgress;
_downloadedBytes = _fileOriginLength + _webRequest.downloadedBytes;
if (_webRequest.isDone == false)
{
CheckTimeout();
return;
}
bool hasError = false;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
{
hasError = true;
_lastError = _webRequest.error;
_lastCode = _webRequest.responseCode;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
hasError = true;
_lastError = _webRequest.error;
_lastCode = _webRequest.responseCode;
}
#endif
// 如果网络异常
if (hasError)
{
// 注意:下载断点续传文件发生特殊错误码之后删除文件
if (DownloadSystem.ClearFileResponseCodes != null)
{
if (DownloadSystem.ClearFileResponseCodes.Contains(_webRequest.responseCode))
{
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
}
}
_steps = ESteps.TryAgain;
}
else
{
_steps = ESteps.VerifyTempFile;
}
// 最终释放下载器
DisposeWebRequest();
}
// 验证下载文件
if (_steps == ESteps.VerifyTempFile)
{
VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.Bundle.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
_verifyFileOp = VerifyTempFileOperation.CreateOperation(element);
OperationSystem.StartOperation(_verifyFileOp);
_steps = ESteps.WaitingVerifyTempFile;
}
// 等待验证完成
if (_steps == ESteps.WaitingVerifyTempFile)
{
if (WaitForAsyncComplete)
_verifyFileOp.Update();
if (_verifyFileOp.IsDone == false)
return;
if (_verifyFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CachingFile;
}
else
{
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
_lastError = _verifyFileOp.Error;
_steps = ESteps.TryAgain;
}
}
// 缓存下载文件
if (_steps == ESteps.CachingFile)
{
try
{
CachingFile(_tempFilePath);
_status = EStatus.Succeed;
_steps = ESteps.Done;
_lastError = string.Empty;
_lastCode = 0;
}
catch (Exception e)
{
_lastError = e.Message;
_steps = ESteps.TryAgain;
}
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (_failedTryAgain <= 0)
{
ReportError();
_status = EStatus.Failed;
_steps = ESteps.Done;
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_failedTryAgain--;
_steps = ESteps.PrepareDownload;
ReportWarning();
}
}
}
public override void Abort()
{
if (IsDone() == false)
{
_status = EStatus.Failed;
_steps = ESteps.Done;
_lastError = "user abort";
_lastCode = 0;
DisposeWebRequest();
}
}
private void DisposeWebRequest()
{
if (_downloadHandle != null)
{
_downloadHandle.Cleanup();
_downloadHandle = null;
}
if (_webRequest != null)
{
_webRequest.Dispose();
_webRequest = null;
}
}
}
}

View File

@@ -3,7 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
@@ -15,26 +14,21 @@ namespace YooAsset
PrepareDownload,
CreateDownloader,
CheckDownload,
VerifyTempFile,
WaitingVerifyTempFile,
CachingFile,
TryAgain,
Done,
}
private bool _keepDownloadHandleLife = false;
private DownloadHandlerAssetBundle _downloadhandler;
private ESteps _steps = ESteps.None;
private bool _getAssetBundle;
public WebDownloader(BundleInfo bundleInfo, int failedTryAgain, int timeout) : base(bundleInfo, failedTryAgain, timeout)
public WebDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
{
}
public override void SendRequest(params object[] param)
public override void SendRequest(params object[] args)
{
if (_steps == ESteps.None)
{
_keepDownloadHandleLife = (bool)param[0];
_getAssetBundle = (bool)args[0];
_steps = ESteps.PrepareDownload;
}
}
@@ -48,82 +42,49 @@ namespace YooAsset
// 创建下载器
if (_steps == ESteps.PrepareDownload)
{
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
_downloadProgress = 0f;
_downloadedBytes = 0;
DownloadProgress = 0f;
DownloadedBytes = 0;
// 重置变量
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
// 重置计时器
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
// 获取请求地址
_requestURL = GetRequestURL();
_steps = ESteps.CreateDownloader;
}
// 创建下载器
if (_steps == ESteps.CreateDownloader)
{
_webRequest = DownloadSystem.NewRequest(_requestURL);
if (CacheSystem.DisableUnityCacheOnWebGL)
{
uint crc = _bundleInfo.Bundle.UnityCRC;
_downloadhandler = new DownloadHandlerAssetBundle(_requestURL, crc);
#if UNITY_2020_3_OR_NEWER
_downloadhandler.autoLoadAssetBundle = false;
#endif
}
else
{
uint crc = _bundleInfo.Bundle.UnityCRC;
var hash = Hash128.Parse(_bundleInfo.Bundle.FileHash);
_downloadhandler = new DownloadHandlerAssetBundle(_requestURL, hash, crc);
#if UNITY_2020_3_OR_NEWER
_downloadhandler.autoLoadAssetBundle = false;
#endif
}
_webRequest.downloadHandler = _downloadhandler;
_webRequest.disposeDownloadHandlerOnDispose = false;
_webRequest.SendWebRequest();
_requester = (IWebRequester)Activator.CreateInstance(_requesterType);
_requester.Create(_requestURL, _bundleInfo, _getAssetBundle);
_steps = ESteps.CheckDownload;
}
// 检测下载结果
if (_steps == ESteps.CheckDownload)
{
_downloadProgress = _webRequest.downloadProgress;
_downloadedBytes = _webRequest.downloadedBytes;
if (_webRequest.isDone == false)
_requester.Update();
DownloadedBytes = _requester.DownloadedBytes;
DownloadProgress = _requester.DownloadProgress;
if (_requester.IsDone() == false)
{
CheckTimeout();
return;
}
bool hasError = false;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
{
hasError = true;
_lastError = _webRequest.error;
_lastCode = _webRequest.responseCode;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
hasError = true;
_lastError = _webRequest.error;
_lastCode = _webRequest.responseCode;
}
#endif
// 如果网络异常
if (hasError)
_lastestNetError = _requester.RequestNetError;
_lastestHttpCode = _requester.RequestHttpCode;
if (_requester.Status != ERequestStatus.Success)
{
_steps = ESteps.TryAgain;
}
@@ -131,15 +92,7 @@ namespace YooAsset
{
_status = EStatus.Succeed;
_steps = ESteps.Done;
_lastError = string.Empty;
_lastCode = 0;
}
// 最终释放请求
DisposeRequest();
if (_keepDownloadHandleLife == false)
DisposeHandler();
}
// 重新尝试下载
@@ -147,8 +100,6 @@ namespace YooAsset
{
if (_failedTryAgain <= 0)
{
DisposeRequest();
DisposeHandler();
ReportError();
_status = EStatus.Failed;
_steps = ESteps.Done;
@@ -167,47 +118,20 @@ namespace YooAsset
}
public override void Abort()
{
if (_requester != null)
_requester.Abort();
if (IsDone() == false)
{
_status = EStatus.Failed;
_steps = ESteps.Done;
_lastError = "user abort";
_lastCode = 0;
DisposeRequest();
DisposeHandler();
_lastestNetError = "user abort";
_lastestHttpCode = 0;
}
}
private void DisposeRequest()
public override AssetBundle GetAssetBundle()
{
if (_webRequest != null)
{
_webRequest.Dispose();
_webRequest = null;
}
}
/// <summary>
/// 获取资源包
/// </summary>
public AssetBundle GetAssetBundle()
{
if (_downloadhandler != null)
return _downloadhandler.assetBundle;
return null;
}
/// <summary>
/// 释放下载句柄
/// </summary>
public void DisposeHandler()
{
if (_downloadhandler != null)
{
_downloadhandler.Dispose();
_downloadhandler = null;
}
return (AssetBundle)_requester.GetRequestObject();
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
public class RemoteTools
{
/// <summary>
/// 记录网络请求失败事件的次数
/// </summary>
private static readonly Dictionary<string, int> _requestFailedRecorder = new Dictionary<string, int>(1000);
/// <summary>
/// 记录请求失败事件
/// </summary>
public static void RecordRequestFailed(string packageName, string eventName)
{
string key = $"{packageName}_{eventName}";
if (_requestFailedRecorder.ContainsKey(key) == false)
_requestFailedRecorder.Add(key, 0);
_requestFailedRecorder[key]++;
}
/// <summary>
/// 获取请求失败的次数
/// </summary>
public static int GetRequestFailedCount(string packageName, string eventName)
{
string key = $"{packageName}_{eventName}";
if (_requestFailedRecorder.ContainsKey(key) == false)
_requestFailedRecorder.Add(key, 0);
return _requestFailedRecorder[key];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca9b2c6456d21bb4e9eecd9dc820a641
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8a97534752300584a9b8c60c04c6a6a8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,144 @@
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
internal class AssetBundleWebRequest : IWebRequester
{
private UnityWebRequest _webRequest;
private DownloadHandlerAssetBundle _downloadhandler;
private AssetBundle _cacheAssetBundle;
private bool _getAssetBundle = false;
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
public float DownloadProgress { private set; get; }
public ulong DownloadedBytes { private set; get; }
public string RequestNetError { private set; get; }
public long RequestHttpCode { private set; get; }
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
{
if (Status != ERequestStatus.None)
throw new System.Exception("Should never get here !");
if (args.Length == 0)
throw new System.Exception("Not found param value");
// 解析附加参数
_getAssetBundle = (bool)args[0];
// 创建下载器
_webRequest = DownloadHelper.NewRequest(requestURL);
if (CacheHelper.DisableUnityCacheOnWebGL)
{
uint crc = bundleInfo.Bundle.UnityCRC;
_downloadhandler = new DownloadHandlerAssetBundle(requestURL, crc);
}
else
{
uint crc = bundleInfo.Bundle.UnityCRC;
var hash = Hash128.Parse(bundleInfo.Bundle.FileHash);
_downloadhandler = new DownloadHandlerAssetBundle(requestURL, hash, crc);
}
#if UNITY_2020_3_OR_NEWER
_downloadhandler.autoLoadAssetBundle = false;
#endif
_webRequest.downloadHandler = _downloadhandler;
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
Status = ERequestStatus.InProgress;
}
public void Update()
{
if (Status == ERequestStatus.None)
return;
if (IsDone())
return;
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = _webRequest.downloadedBytes;
if (_webRequest.isDone == false)
return;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER
RequestHttpCode = _webRequest.responseCode;
if (_webRequest.result != UnityWebRequest.Result.Success)
{
RequestNetError = _webRequest.error;
Status = ERequestStatus.Error;
}
else
{
Status = ERequestStatus.Success;
}
#else
RequestHttpCode = _webRequest.responseCode;
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
RequestNetError = _webRequest.error;
Status = ERequestStatus.Error;
}
else
{
Status = ERequestStatus.Success;
}
#endif
// 缓存加载的AssetBundle对象
if (Status == ERequestStatus.Success)
{
if (_getAssetBundle)
{
_cacheAssetBundle = _downloadhandler.assetBundle;
if (_cacheAssetBundle == null)
{
RequestNetError = "assetBundle is null";
Status = ERequestStatus.Error;
}
}
}
// 最终释放下载器
DisposeWebRequest();
}
public void Abort()
{
// 如果下载任务还未开始
if (Status == ERequestStatus.None)
{
RequestNetError = "user cancel";
Status = ERequestStatus.Error;
}
else
{
// 注意:为了防止同一个文件强制停止之后立马创建新的请求,应该让进行中的请求自然终止。
if (_webRequest != null)
{
if (_webRequest.isDone == false)
_webRequest.Abort(); // If in progress, halts the UnityWebRequest as soon as possible.
}
}
}
public bool IsDone()
{
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
return true;
else
return false;
}
public object GetRequestObject()
{
return _cacheAssetBundle;
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
_webRequest.Dispose();
_webRequest = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 34efa85440da15247b570a98b0971282
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
using System.IO;
using UnityEngine.Networking;
namespace YooAsset
{
internal class FileGeneralRequest : IWebRequester
{
private UnityWebRequest _webRequest;
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
public float DownloadProgress { private set; get; }
public ulong DownloadedBytes { private set; get; }
public string RequestNetError { private set; get; }
public long RequestHttpCode { private set; get; }
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
{
if (Status != ERequestStatus.None)
throw new System.Exception("Should never get here !");
string tempFilePath = bundleInfo.TempDataFilePath;
// 删除临时文件
if (File.Exists(tempFilePath))
File.Delete(tempFilePath);
// 创建下载器
_webRequest = DownloadHelper.NewRequest(requestURL);
DownloadHandlerFile handler = new DownloadHandlerFile(tempFilePath);
handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
Status = ERequestStatus.InProgress;
}
public void Update()
{
if (Status == ERequestStatus.None)
return;
if (IsDone())
return;
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = _webRequest.downloadedBytes;
if (_webRequest.isDone == false)
return;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER
RequestHttpCode = _webRequest.responseCode;
if (_webRequest.result != UnityWebRequest.Result.Success)
{
RequestNetError = _webRequest.error;
Status = ERequestStatus.Error;
}
else
{
Status = ERequestStatus.Success;
}
#else
RequestHttpCode = _webRequest.responseCode;
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
RequestNetError = _webRequest.error;
Status = ERequestStatus.Error;
}
else
{
Status = ERequestStatus.Success;
}
#endif
// 最终释放下载器
DisposeWebRequest();
}
public void Abort()
{
DisposeWebRequest();
if (IsDone() == false)
{
RequestNetError = "user abort";
RequestHttpCode = 0;
Status = ERequestStatus.Error;
}
}
public bool IsDone()
{
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
return true;
else
return false;
}
public object GetRequestObject()
{
throw new System.NotImplementedException();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
_webRequest.Dispose(); //注意引擎底层会自动调用Abort方法
_webRequest = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2f339136a4269343a3b5ab80450b889
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
using System.IO;
using UnityEngine.Networking;
namespace YooAsset
{
internal class FileResumeRequest : IWebRequester
{
private string _tempFilePath;
private UnityWebRequest _webRequest;
private DownloadHandlerFileRange _downloadHandle;
private ulong _fileOriginLength;
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
public float DownloadProgress { private set; get; }
public ulong DownloadedBytes { private set; get; }
public string RequestNetError { private set; get; }
public long RequestHttpCode { private set; get; }
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
{
if (Status != ERequestStatus.None)
throw new System.Exception("Should never get here !");
_tempFilePath = bundleInfo.TempDataFilePath;
long fileBytes = bundleInfo.Bundle.FileSize;
// 获取下载的起始位置
long fileLength = -1;
if (File.Exists(_tempFilePath))
{
FileInfo fileInfo = new FileInfo(_tempFilePath);
fileLength = fileInfo.Length;
_fileOriginLength = (ulong)fileLength;
DownloadedBytes = _fileOriginLength;
}
// 检测下载起始位置是否有效
if (fileLength >= fileBytes)
{
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
}
// 创建下载器
_webRequest = DownloadHelper.NewRequest(requestURL);
#if UNITY_2019_4_OR_NEWER
var handler = new DownloadHandlerFile(_tempFilePath, true);
handler.removeFileOnAbort = false;
#else
var handler = new DownloadHandlerFileRange(tempFilePath, _bundleInfo.Bundle.FileSize, _webRequest);
_downloadHandle = handler;
#endif
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
if (fileLength > 0)
_webRequest.SetRequestHeader("Range", $"bytes={fileLength}-");
_webRequest.SendWebRequest();
Status = ERequestStatus.InProgress;
}
public void Update()
{
if (Status == ERequestStatus.None)
return;
if (IsDone())
return;
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = _fileOriginLength + _webRequest.downloadedBytes;
if (_webRequest.isDone == false)
return;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER
RequestHttpCode = _webRequest.responseCode;
if (_webRequest.result != UnityWebRequest.Result.Success)
{
RequestNetError = _webRequest.error;
Status = ERequestStatus.Error;
}
else
{
Status = ERequestStatus.Success;
}
#else
RequestHttpCode = _webRequest.responseCode;
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
RequestNetError = _webRequest.error;
Status = ERequestStatus.Error;
}
else
{
Status = ERequestStatus.Success;
}
#endif
// 注意:下载断点续传文件发生特殊错误码之后删除文件
if (Status == ERequestStatus.Error)
{
if (DownloadHelper.ClearFileResponseCodes != null)
{
if (DownloadHelper.ClearFileResponseCodes.Contains(RequestHttpCode))
{
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
}
}
}
// 最终释放下载器
DisposeWebRequest();
}
public void Abort()
{
DisposeWebRequest();
if (IsDone() == false)
{
RequestNetError = "user abort";
RequestHttpCode = 0;
Status = ERequestStatus.Error;
}
}
public bool IsDone()
{
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
return true;
else
return false;
}
public object GetRequestObject()
{
throw new System.NotImplementedException();
}
private void DisposeWebRequest()
{
if (_downloadHandle != null)
{
_downloadHandle.Cleanup();
_downloadHandle = null;
}
if (_webRequest != null)
{
_webRequest.Dispose();
_webRequest = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 816bf5396d7570e4ab28f1af407bc10f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@

namespace YooAsset
{
internal enum ERequestStatus
{
None,
InProgress,
Error,
Success,
}
internal interface IWebRequester
{
/// <summary>
/// 任务状态
/// </summary>
public ERequestStatus Status { get; }
/// <summary>
/// 下载进度0f~1f
/// </summary>
public float DownloadProgress { get; }
/// <summary>
/// 已经下载的总字节数
/// </summary>
public ulong DownloadedBytes { get; }
/// <summary>
/// 返回的网络错误
/// </summary>
public string RequestNetError { get; }
/// <summary>
/// 返回的HTTP CODE
/// </summary>
public long RequestHttpCode { get; }
/// <summary>
/// 创建任务
/// </summary>
public void Create(string url, BundleInfo bundleInfo, params object[] args);
/// <summary>
/// 更新任务
/// </summary>
public void Update();
/// <summary>
/// 终止任务
/// </summary>
public void Abort();
/// <summary>
/// 是否已经完成(无论成功或失败)
/// </summary>
public bool IsDone();
/// <summary>
/// 获取请求的对象
/// </summary>
public object GetRequestObject();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d80b965d56870b43af1bf6943015914
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -18,7 +18,7 @@ namespace YooAsset
URL = url;
ResetTimeout(timeout);
_webRequest = DownloadSystem.NewRequest(URL);
_webRequest = DownloadHelper.NewRequest(URL);
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;

View File

@@ -18,7 +18,7 @@ namespace YooAsset
URL = url;
ResetTimeout(timeout);
_webRequest = DownloadSystem.NewRequest(URL);
_webRequest = DownloadHelper.NewRequest(URL);
DownloadHandlerFile handler = new DownloadHandlerFile(fileSavePath);
handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler;