mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-28 19:48:47 +00:00
Compare commits
22 Commits
2.3.17
...
c87efdb509
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c87efdb509 | ||
|
|
1884fab0c2 | ||
|
|
e5d0a856a5 | ||
|
|
5da8c6baf8 | ||
|
|
33356cb270 | ||
|
|
4b6a8ca406 | ||
|
|
c8e45a6cae | ||
|
|
1fbc9d26a6 | ||
|
|
abb087b02e | ||
|
|
aeaf03011f | ||
|
|
78d24ad3a6 | ||
|
|
aab2c4625e | ||
|
|
079ef75605 | ||
|
|
75881b55f6 | ||
|
|
2020c7d508 | ||
|
|
088d939346 | ||
|
|
fa50e91c9f | ||
|
|
2e7b992a4b | ||
|
|
29fbbd97ff | ||
|
|
abb150e33f | ||
|
|
78e20f434e | ||
|
|
304222b788 |
@@ -2,6 +2,57 @@
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [2.3.18] - 2025-12-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#676) 修复了UniTask扩展包的编译报错。
|
||||
- (#684) 修复了资源配置窗口Group列表数量过多的时候,添加和删除按钮会变小的问题。
|
||||
- (#700) [**严重**] 修复了小游戏扩展库的下载器再失败后重试逻辑不起效的问题。
|
||||
|
||||
### Added
|
||||
|
||||
- (#683) 新增了内置文件系统类初始化参数:UNPACK_FILE_SYSTEM_ROOT
|
||||
|
||||
```csharp
|
||||
class FileSystemParametersDefine
|
||||
{
|
||||
// 指定解压文件的根目录
|
||||
public const string UNPACK_FILE_SYSTEM_ROOT = "UNPACK_FILE_SYSTEM_ROOT";
|
||||
}
|
||||
```
|
||||
|
||||
- (#682) 原生文件构建管线新增构建参数:IncludePathInHash
|
||||
|
||||
```csharp
|
||||
class RawFileBuildParameters : BuildParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件哈希值计算包含路径信息
|
||||
/// </summary>
|
||||
public bool IncludePathInHash = false;
|
||||
}
|
||||
```
|
||||
|
||||
- (#671) 新增扩展工具,可以生成空的包裹内置资源目录文件。
|
||||
|
||||
```csharp
|
||||
public class CreateEmptyCatalogWindow : EditorWindow
|
||||
```
|
||||
|
||||
- (#694) 新增资源清理方式:ClearBundleFilesByLocations
|
||||
|
||||
```csharp
|
||||
public enum EFileClearMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 清理指定地址的文件
|
||||
/// 说明:需要指定参数,可选:string, string[], List<string>
|
||||
/// </summary>
|
||||
ClearBundleFilesByLocations,
|
||||
}
|
||||
```
|
||||
|
||||
## [2.3.17] - 2025-10-30
|
||||
|
||||
**非常重要**:修复了#627优化导致的资源清单CRC值为空的问题。
|
||||
@@ -16,10 +67,6 @@ All notable changes to this package will be documented in this file.
|
||||
|
||||
影响范围:所有版本!
|
||||
|
||||
### Improvements
|
||||
|
||||
- 重构并统一了资源清单的反序列化逻辑。
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#645) 修复了着色器变种收集工具,在极端情况下变种收集不完整的问题。
|
||||
@@ -29,6 +76,7 @@ All notable changes to this package will be documented in this file.
|
||||
|
||||
### Improvements
|
||||
|
||||
- 重构并统一了资源清单的反序列化逻辑。
|
||||
- (#650) 解决互相依赖的资源包无法卸载的问题。需要开启宏定义:YOOASSET_EXPERIMENTAL
|
||||
- (#655) 优化了初始化的时候,缓存文件搜索效率。安卓平台性能提升1倍,IOS平台性能提升3倍。
|
||||
|
||||
|
||||
@@ -261,14 +261,14 @@ namespace YooAsset.Editor
|
||||
catch (System.Exception e)
|
||||
{
|
||||
_reportCombiner = null;
|
||||
_titleLabel.text = "导入报告失败!";
|
||||
_titleLabel.text = "Failed to import report!";
|
||||
_descLabel.text = e.Message;
|
||||
UnityEngine.Debug.LogError(e.StackTrace);
|
||||
}
|
||||
}
|
||||
private void FixAllBtn_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", "修复全部资源(排除白名单和隐藏元素)", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", "Fix all resources (excluding whitelist and hidden elements)", "Yes", "No"))
|
||||
{
|
||||
if (_reportCombiner != null)
|
||||
_reportCombiner.FixAll();
|
||||
@@ -276,7 +276,7 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void FixSelectBtn_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", "修复勾选资源(包含白名单和隐藏元素)", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", "Fix selected resources (including whitelist and hidden elements)", "Yes", "No"))
|
||||
{
|
||||
if (_reportCombiner != null)
|
||||
_reportCombiner.FixSelect();
|
||||
@@ -302,7 +302,7 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void ExportFilesBtn_clicked()
|
||||
{
|
||||
string selectFolderPath = EditorUtility.OpenFolderPanel("导入所有选中资源", EditorTools.GetProjectPath(), string.Empty);
|
||||
string selectFolderPath = EditorUtility.OpenFolderPanel("Export all selected resources", EditorTools.GetProjectPath(), string.Empty);
|
||||
if (string.IsNullOrEmpty(selectFolderPath) == false)
|
||||
{
|
||||
if (_reportCombiner != null)
|
||||
|
||||
@@ -240,7 +240,7 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void ScanAllBtn_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", $"开始全面扫描!", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", $"Start full scan!", "Yes", "No"))
|
||||
{
|
||||
string searchKeyWord = _scannerSearchField.value;
|
||||
AssetArtScannerSettingData.ScanAll(searchKeyWord);
|
||||
@@ -248,7 +248,7 @@ namespace YooAsset.Editor
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("全面扫描已经取消");
|
||||
Debug.LogWarning("Full scan has been canceled.");
|
||||
}
|
||||
}
|
||||
private void ScanBtn_clicked()
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace YooAsset.Editor
|
||||
{
|
||||
bundleInfo.PackageUnityHash = GetUnityHash(bundleInfo, context);
|
||||
bundleInfo.PackageUnityCRC = GetUnityCRC(bundleInfo, context);
|
||||
bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, buildParametersContext);
|
||||
bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, buildParametersContext);
|
||||
bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, buildParametersContext);
|
||||
bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, context);
|
||||
bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, context);
|
||||
bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, context);
|
||||
}
|
||||
|
||||
// 4.更新补丁包输出的文件路径
|
||||
@@ -62,8 +62,8 @@ namespace YooAsset.Editor
|
||||
|
||||
protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
||||
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
||||
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
||||
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
}
|
||||
}
|
||||
@@ -40,17 +40,17 @@ namespace YooAsset.Editor
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileCRC32Value(filePath);
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return FileUtility.GetFileSize(filePath);
|
||||
|
||||
@@ -19,16 +19,16 @@ namespace YooAsset.Editor
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return GetFilePathTempHash(filePath);
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
return GetBundleTempSize(bundleInfo);
|
||||
}
|
||||
|
||||
@@ -15,27 +15,55 @@ namespace YooAsset.Editor
|
||||
|
||||
protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var rawFileBuildParameters = buildParametersContext.Parameters as RawFileBuildParameters;
|
||||
if (rawFileBuildParameters.IncludePathInHash)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return GetFileMD5IncludePath(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
}
|
||||
protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var rawFileBuildParameters = buildParametersContext.Parameters as RawFileBuildParameters;
|
||||
if (rawFileBuildParameters.IncludePathInHash)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return GetFileMD5IncludePath(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileCRC32Value(filePath);
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return FileUtility.GetFileSize(filePath);
|
||||
}
|
||||
|
||||
private string GetFileMD5IncludePath(string filePath)
|
||||
{
|
||||
string pathHash = HashUtility.StringMD5(filePath.ToLowerInvariant());
|
||||
string contentHash = HashUtility.FileMD5(filePath);
|
||||
string combined = pathHash + contentHash;
|
||||
return HashUtility.StringMD5(combined);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,9 @@ namespace YooAsset.Editor
|
||||
{
|
||||
public class RawFileBuildParameters : BuildParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件哈希值计算包含路径信息
|
||||
/// </summary>
|
||||
public bool IncludePathInHash = false;
|
||||
}
|
||||
}
|
||||
@@ -40,17 +40,17 @@ namespace YooAsset.Editor
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileCRC32Value(filePath);
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return FileUtility.GetFileSize(filePath);
|
||||
|
||||
@@ -82,14 +82,14 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void BuildButton_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||
{
|
||||
EditorTools.ClearUnityConsole();
|
||||
EditorApplication.delayCall += ExecuteBuild;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[Build] 打包已经取消");
|
||||
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,14 +42,14 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void BuildButton_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||
{
|
||||
EditorTools.ClearUnityConsole();
|
||||
EditorApplication.delayCall += ExecuteBuild;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[Build] 打包已经取消");
|
||||
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,14 +77,14 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void BuildButton_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||
{
|
||||
EditorTools.ClearUnityConsole();
|
||||
EditorApplication.delayCall += ExecuteBuild;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[Build] 打包已经取消");
|
||||
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,14 +82,14 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void BuildButton_clicked()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
||||
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||
{
|
||||
EditorTools.ClearUnityConsole();
|
||||
EditorApplication.delayCall += ExecuteBuild;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[Build] 打包已经取消");
|
||||
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<ui:VisualElement name="PackageContainer" style="width: 200px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||
<ui:Label text="Packages" display-tooltip-when-elided="true" name="PackageTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px;" />
|
||||
<ui:ListView focusable="true" name="PackageListView" item-height="20" virtualization-method="DynamicHeight" reorderable="true" reorder-mode="Animated" style="flex-grow: 1;" />
|
||||
<ui:VisualElement name="PackageAddContainer" style="height: 20px; flex-direction: row; justify-content: center;">
|
||||
<ui:VisualElement name="PackageAddContainer" style="height: 20px; flex-direction: row; justify-content: center; flex-shrink: 0;">
|
||||
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
|
||||
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||
</ui:VisualElement>
|
||||
@@ -40,7 +40,7 @@
|
||||
<ui:TextField picking-mode="Ignore" label="Package Name" name="PackageName" style="flex-direction: column;" />
|
||||
<ui:TextField picking-mode="Ignore" label="Package Desc" name="PackageDesc" style="flex-direction: column;" />
|
||||
<ui:ListView focusable="true" name="GroupListView" item-height="20" virtualization-method="DynamicHeight" reorderable="true" reorder-mode="Animated" style="flex-grow: 1;" />
|
||||
<ui:VisualElement name="GroupAddContainer" style="height: 20px; flex-direction: row; justify-content: center;">
|
||||
<ui:VisualElement name="GroupAddContainer" style="height: 20px; flex-direction: row; justify-content: center; flex-shrink: 0;">
|
||||
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
|
||||
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||
</ui:VisualElement>
|
||||
|
||||
@@ -88,8 +88,8 @@ namespace YooAsset.Editor
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ClearDatabase(true);
|
||||
Debug.LogError($"Failed to load cache database : {ex.Message}");
|
||||
ClearDatabase(true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -169,7 +169,8 @@ namespace YooAsset.Editor
|
||||
File.Delete(_databaseFilePath);
|
||||
}
|
||||
|
||||
_database.Clear();
|
||||
if (_database != null)
|
||||
_database.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace YooAsset.Editor
|
||||
Texture,
|
||||
RenderTexture,
|
||||
VideoClip,
|
||||
PlayableAsset,
|
||||
TimelineAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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:
|
||||
@@ -118,6 +118,34 @@ namespace YooAsset
|
||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成空的包裹内置资源目录文件
|
||||
/// </summary>
|
||||
public static bool CreateEmptyCatalogFile(string packageName, string packageVersion, string outputPath)
|
||||
{
|
||||
// 创建内置清单实例
|
||||
var buildinFileCatalog = new DefaultBuildinFileCatalog();
|
||||
buildinFileCatalog.FileVersion = CatalogDefine.FileVersion;
|
||||
buildinFileCatalog.PackageName = packageName;
|
||||
buildinFileCatalog.PackageVersion = packageVersion;
|
||||
|
||||
// 创建输出文件
|
||||
string jsonFilePath = $"{outputPath}/{DefaultBuildinFileSystemDefine.BuildinCatalogJsonFileName}";
|
||||
if (File.Exists(jsonFilePath))
|
||||
File.Delete(jsonFilePath);
|
||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
||||
|
||||
// 创建输出文件
|
||||
string binaryFilePath = $"{outputPath}/{DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName}";
|
||||
if (File.Exists(binaryFilePath))
|
||||
File.Delete(binaryFilePath);
|
||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
||||
|
||||
UnityEditor.AssetDatabase.Refresh();
|
||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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>
|
||||
/// 自定义参数:数据文件追加文件格式
|
||||
@@ -89,6 +94,11 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public string CopyBuildinPackageManifestDestRoot { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:解压文件系统的根目录
|
||||
/// </summary>
|
||||
public string UnpackFileSystemRoot { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:解密服务接口的实例类
|
||||
/// </summary>
|
||||
@@ -151,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}";
|
||||
@@ -190,6 +207,10 @@ namespace YooAsset
|
||||
{
|
||||
CopyBuildinPackageManifestDestRoot = (string)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.UNPACK_FILE_SYSTEM_ROOT)
|
||||
{
|
||||
UnpackFileSystemRoot = (string)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
|
||||
{
|
||||
DecryptionServices = (IDecryptionServices)value;
|
||||
@@ -216,6 +237,10 @@ namespace YooAsset
|
||||
else
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||
|
||||
// 创建解压文件系统
|
||||
var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
|
||||
_unpackFileSystem = new DefaultUnpackFileSystem();
|
||||
@@ -226,7 +251,7 @@ namespace YooAsset
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES, CopyLocalFileServices);
|
||||
_unpackFileSystem.OnCreate(packageName, null);
|
||||
_unpackFileSystem.OnCreate(packageName, UnpackFileSystemRoot);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
@@ -87,11 +86,11 @@ namespace YooAsset
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load catalog file : {e.Message}";
|
||||
Error = $"Failed to load catalog file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
/// 包裹名称
|
||||
@@ -73,8 +77,10 @@ namespace YooAsset
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
||||
/// 默认值:32(推荐范围 1-128)
|
||||
/// 说明:过大的值可能导致线程池任务过多,影响系统稳定性
|
||||
/// </summary>
|
||||
public int FileVerifyMaxConcurrency { private set; get; } = int.MaxValue;
|
||||
public int FileVerifyMaxConcurrency { private set; get; } = 32;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:数据文件追加文件格式
|
||||
@@ -88,18 +94,22 @@ namespace YooAsset
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:最大并发连接数
|
||||
/// 默认值:10(推荐范围 1-32)
|
||||
/// 说明:过大的并发数可能被服务器限流,也会增加本地资源消耗
|
||||
/// </summary>
|
||||
public int DownloadMaxConcurrency { private set; get; } = int.MaxValue;
|
||||
public int DownloadMaxConcurrency { private set; get; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:每帧发起的最大请求数
|
||||
/// 默认值:5(推荐范围 1-10)
|
||||
/// 说明:避免单帧发起过多请求导致卡顿
|
||||
/// </summary>
|
||||
public int DownloadMaxRequestPerFrame { private set; get; } = int.MaxValue;
|
||||
public int DownloadMaxRequestPerFrame { private set; get; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:下载任务的看门狗机制监控时间
|
||||
/// </summary>
|
||||
public int DownloadWatchDogTime { private set; get; } = int.MaxValue;
|
||||
public int DownloadWatchDogTime { private set; get; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:启用断点续传的最小尺寸
|
||||
@@ -158,6 +168,11 @@ namespace YooAsset
|
||||
var operation = new ClearUnusedCacheBundleFilesOperation(this, manifest);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearBundleFilesByLocations.ToString())
|
||||
{
|
||||
var operation = new ClearCacheBundleFilesByLocationsOperaiton(this, manifest, options.ClearParam);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearBundleFilesByTags.ToString())
|
||||
{
|
||||
var operation = new ClearCacheBundleFilesByTagsOperaiton(this, manifest, options.ClearParam);
|
||||
@@ -237,7 +252,14 @@ namespace YooAsset
|
||||
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
|
||||
if (convertValue > 256)
|
||||
{
|
||||
YooLogger.Warning($"FILE_VERIFY_MAX_CONCURRENCY value {convertValue} is too large, clamped to 256. Recommended range: 1 - 128.");
|
||||
}
|
||||
|
||||
// 限制在合理范围内:1-256
|
||||
// 超过 256 的并发数对于文件验证来说没有意义,反而会增加线程池压力
|
||||
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, 256);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
|
||||
{
|
||||
@@ -250,17 +272,27 @@ namespace YooAsset
|
||||
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
DownloadMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
|
||||
if (convertValue > 64)
|
||||
{
|
||||
YooLogger.Warning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 64. Recommended range: 1 - 32.");
|
||||
}
|
||||
|
||||
DownloadMaxConcurrency = Mathf.Clamp(convertValue, 1, 64);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
DownloadMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, int.MaxValue);
|
||||
if (convertValue > 20)
|
||||
{
|
||||
YooLogger.Warning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 20. Recommended range: 1 - 10.");
|
||||
}
|
||||
|
||||
DownloadMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, 20);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -299,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,7 +507,7 @@ namespace YooAsset
|
||||
{
|
||||
if (_records.ContainsKey(bundle.BundleGUID))
|
||||
{
|
||||
throw new Exception("Should never get here !");
|
||||
throw new YooInternalException();
|
||||
}
|
||||
|
||||
string infoFilePath = GetBundleInfoFilePath(bundle);
|
||||
@@ -493,9 +529,9 @@ namespace YooAsset
|
||||
// 写入文件信息
|
||||
WriteBundleInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
YooLogger.Error($"Failed to write cache file ! {e.Message}");
|
||||
YooLogger.Error($"Failed to write cache file ! {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,9 @@ namespace YooAsset
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
|
||||
YooLogger.Error($"Failed to delete cache file ! {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ namespace YooAsset
|
||||
{
|
||||
Directory.Delete(FileRootPath, true);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
YooLogger.Warning($"Failed to delete cache bundle folder : {e}");
|
||||
YooLogger.Warning($"Failed to delete cache bundle folder : {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -320,11 +320,11 @@ namespace YooAsset
|
||||
File.Move(recordFileElement.DataFilePath, filePath);
|
||||
_steps = ESteps.LoadCacheRawBundle;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Faild rename raw data file : {e.Message}";
|
||||
Error = $"Faild rename raw data file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class ClearCacheBundleFilesByLocationsOperaiton : FSClearCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckManifest,
|
||||
CheckArgs,
|
||||
GetClearCacheFiles,
|
||||
ClearFilterCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private readonly object _clearParam;
|
||||
private string[] _locations;
|
||||
private List<string> _clearBundleGUIDs;
|
||||
private int _clearFileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearCacheBundleFilesByLocationsOperaiton(DefaultCacheFileSystem fileSystem, PackageManifest manifest, object clearParam)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
_clearParam = clearParam;
|
||||
}
|
||||
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckManifest;
|
||||
}
|
||||
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckManifest)
|
||||
{
|
||||
if (_manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Can not found active package manifest !";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckArgs;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckArgs)
|
||||
{
|
||||
if (_clearParam == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Clear param is null !";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clearParam is string)
|
||||
{
|
||||
_locations = new string[] { _clearParam as string };
|
||||
}
|
||||
else if (_clearParam is List<string>)
|
||||
{
|
||||
var tempList = _clearParam as List<string>;
|
||||
_locations = tempList.ToArray();
|
||||
}
|
||||
else if (_clearParam is string[])
|
||||
{
|
||||
_locations = _clearParam as string[];
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Invalid clear param : {_clearParam.GetType().FullName}";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.GetClearCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.GetClearCacheFiles)
|
||||
{
|
||||
_clearBundleGUIDs = GetBundleGUIDsByLocation();
|
||||
_clearFileTotalCount = _clearBundleGUIDs.Count;
|
||||
_steps = ESteps.ClearFilterCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearFilterCacheFiles)
|
||||
{
|
||||
for (int i = _clearBundleGUIDs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string bundleGUID = _clearBundleGUIDs[i];
|
||||
_fileSystem.DeleteCacheBundleFile(bundleGUID);
|
||||
_clearBundleGUIDs.RemoveAt(i);
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_clearFileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - (_clearBundleGUIDs.Count / _clearFileTotalCount);
|
||||
|
||||
if (_clearBundleGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetBundleGUIDsByLocation()
|
||||
{
|
||||
List<string> result = new List<string>(_locations.Length);
|
||||
|
||||
foreach (var location in _locations)
|
||||
{
|
||||
string assetPath = _manifest.TryMappingToAssetPath(location);
|
||||
if (_manifest.TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
|
||||
{
|
||||
PackageBundle bundle = _manifest.GetMainPackageBundle(packageAsset.BundleID);
|
||||
|
||||
if (bundle != null)
|
||||
{
|
||||
result.Add(bundle.BundleGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0be6ffd570645bf4a95126958a8e8a86
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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,10 +18,10 @@ namespace YooAsset
|
||||
// 下载参数
|
||||
protected readonly DefaultCacheFileSystem _fileSystem;
|
||||
protected readonly DownloadFileOptions _options;
|
||||
private UnityDownloadFileOperation _unityDownloadFileOp;
|
||||
private DownloadAndCacheFileOperation _downloadFileOp;
|
||||
|
||||
protected int _requestCount = 0;
|
||||
protected float _tryAgainTimer;
|
||||
protected float _tryAgainTimer = 0;
|
||||
protected int _failedTryAgain;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -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>
|
||||
@@ -142,9 +147,13 @@ namespace YooAsset
|
||||
PackageName = packageName;
|
||||
|
||||
if (string.IsNullOrEmpty(packageRoot))
|
||||
throw new Exception($"{nameof(DefaultEditorFileSystem)} root directory is null or empty !");
|
||||
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,10 +17,10 @@ namespace YooAsset
|
||||
// 下载参数
|
||||
protected readonly DefaultEditorFileSystem _fileSystem;
|
||||
protected readonly DownloadFileOptions _options;
|
||||
protected UnityVirtualBundleRequestOperation _unityDownloadFileOp;
|
||||
protected IDownloadFileRequest _downloadFileOp;
|
||||
|
||||
protected int _requestCount = 0;
|
||||
protected float _tryAgainTimer;
|
||||
protected float _tryAgainTimer = 0;
|
||||
protected int _failedTryAgain;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -81,11 +80,11 @@ namespace YooAsset
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load catalog file : {e.Message}";
|
||||
Error = $"Failed to load catalog file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user