mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-29 20:48:47 +00:00
Compare commits
45 Commits
2.3.16
...
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 | ||
|
|
101236db8a | ||
|
|
37de007b3f | ||
|
|
d570ba8d74 | ||
|
|
2a956099ae | ||
|
|
74037a5a29 | ||
|
|
861f850a32 | ||
|
|
8b1b5f988a | ||
|
|
efafd1173f | ||
|
|
03e49ff1fb | ||
|
|
ea34be1f00 | ||
|
|
831a9981e3 | ||
|
|
9de4aaa658 | ||
|
|
3579a23bd5 | ||
|
|
c865ddc7f2 | ||
|
|
0bde506aec | ||
|
|
15005b3d30 | ||
|
|
4caf733ac6 | ||
|
|
014b17f5cb | ||
|
|
f3ebda0c04 | ||
|
|
5602addaca | ||
|
|
c4ae67aa8e | ||
|
|
bbcc3bf971 | ||
|
|
8b0e75b9b3 |
@@ -2,6 +2,115 @@
|
|||||||
|
|
||||||
All notable changes to this package will be documented in this file.
|
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值为空的问题。
|
||||||
|
|
||||||
|
该问题会导致下载的损坏文件验证通过。
|
||||||
|
|
||||||
|
影响范围:v2.3.15版本,v2.3.16版本。
|
||||||
|
|
||||||
|
**非常重要**:(#661) 修复了Package销毁过程中,遇到正在加载的AssetBundle会导致无法卸载的问题。
|
||||||
|
|
||||||
|
该问题是偶现,引擎会提示AssetBundle已经加载,无法加载新的文件,导致资源对象加载失败!
|
||||||
|
|
||||||
|
影响范围:所有版本!
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- (#645) 修复了着色器变种收集工具,在极端情况下变种收集不完整的问题。
|
||||||
|
- (#646) 修复了EditorSimulateMode模式下开启模拟下载tag不生效的问题。
|
||||||
|
- (#667) 修复了所有编辑器窗口针对中文IME的输入问题。
|
||||||
|
- (#670) 修复了Catalog文件生成过程中白名单未考虑自定义清单前缀名。
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- 重构并统一了资源清单的反序列化逻辑。
|
||||||
|
- (#650) 解决互相依赖的资源包无法卸载的问题。需要开启宏定义:YOOASSET_EXPERIMENTAL
|
||||||
|
- (#655) 优化了初始化的时候,缓存文件搜索效率。安卓平台性能提升1倍,IOS平台性能提升3倍。
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- (#643) 新增构建参数,可以节省资源清单运行时内存
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class ScriptableBuildParameters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 使用可寻址地址代替资源路径
|
||||||
|
/// 说明:开启此项可以节省运行时清单占用的内存!
|
||||||
|
/// </summary>
|
||||||
|
public bool ReplaceAssetPathWithAddress = false;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- (#648) 新增初始化参数,可以自动释放引用计数为零的资源包
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class InitializeParameters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 当资源引用计数为零的时候自动释放资源包
|
||||||
|
/// </summary>
|
||||||
|
public bool AutoUnloadBundleWhenUnused = false;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- 程序集宏定义代码转移到扩展工程。参考MacroSupport文件夹。
|
||||||
|
|
||||||
## [2.3.16] - 2025-09-17
|
## [2.3.16] - 2025-09-17
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|||||||
@@ -261,14 +261,14 @@ namespace YooAsset.Editor
|
|||||||
catch (System.Exception e)
|
catch (System.Exception e)
|
||||||
{
|
{
|
||||||
_reportCombiner = null;
|
_reportCombiner = null;
|
||||||
_titleLabel.text = "导入报告失败!";
|
_titleLabel.text = "Failed to import report!";
|
||||||
_descLabel.text = e.Message;
|
_descLabel.text = e.Message;
|
||||||
UnityEngine.Debug.LogError(e.StackTrace);
|
UnityEngine.Debug.LogError(e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void FixAllBtn_clicked()
|
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)
|
if (_reportCombiner != null)
|
||||||
_reportCombiner.FixAll();
|
_reportCombiner.FixAll();
|
||||||
@@ -276,7 +276,7 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void FixSelectBtn_clicked()
|
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)
|
if (_reportCombiner != null)
|
||||||
_reportCombiner.FixSelect();
|
_reportCombiner.FixSelect();
|
||||||
@@ -302,7 +302,7 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void ExportFilesBtn_clicked()
|
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 (string.IsNullOrEmpty(selectFolderPath) == false)
|
||||||
{
|
{
|
||||||
if (_reportCombiner != null)
|
if (_reportCombiner != null)
|
||||||
|
|||||||
@@ -32,17 +32,10 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 开始扫描工作
|
// 开始扫描工作
|
||||||
ScanReport report = scanner.RunScanner();
|
ScanReport report = scanner.RunScanner();
|
||||||
|
|
||||||
// 检测报告合法性
|
|
||||||
report.CheckError();
|
report.CheckError();
|
||||||
|
|
||||||
// 保存扫描结果
|
// 返回扫描结果
|
||||||
string saveDirectory = scanner.SaveDirectory;
|
return new ScannerResult(report);
|
||||||
if (string.IsNullOrEmpty(saveDirectory))
|
|
||||||
saveDirectory = "Assets/";
|
|
||||||
string filePath = $"{saveDirectory}/{scanner.ScannerName}_{scanner.ScannerDesc}.json";
|
|
||||||
ScanReportConfig.ExportJsonConfig(filePath, report);
|
|
||||||
return new ScannerResult(filePath, report);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void ScanAllBtn_clicked()
|
private void ScanAllBtn_clicked()
|
||||||
{
|
{
|
||||||
if (EditorUtility.DisplayDialog("提示", $"开始全面扫描!", "Yes", "No"))
|
if (EditorUtility.DisplayDialog("Info", $"Start full scan!", "Yes", "No"))
|
||||||
{
|
{
|
||||||
string searchKeyWord = _scannerSearchField.value;
|
string searchKeyWord = _scannerSearchField.value;
|
||||||
AssetArtScannerSettingData.ScanAll(searchKeyWord);
|
AssetArtScannerSettingData.ScanAll(searchKeyWord);
|
||||||
@@ -248,7 +248,7 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("全面扫描已经取消");
|
Debug.LogWarning("Full scan has been canceled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void ScanBtn_clicked()
|
private void ScanBtn_clicked()
|
||||||
|
|||||||
@@ -3,11 +3,6 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
public class ScannerResult
|
public class ScannerResult
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 生成的报告文件路径
|
|
||||||
/// </summary>
|
|
||||||
public string ReprotFilePath { private set; get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 报告对象
|
/// 报告对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -43,11 +38,9 @@ namespace YooAsset.Editor
|
|||||||
ErrorInfo = error;
|
ErrorInfo = error;
|
||||||
ErrorStack = stack;
|
ErrorStack = stack;
|
||||||
}
|
}
|
||||||
public ScannerResult(string filePath, ScanReport report)
|
public ScannerResult(ScanReport report)
|
||||||
{
|
{
|
||||||
ReprotFilePath = filePath;
|
|
||||||
Report = report;
|
Report = report;
|
||||||
ErrorInfo = string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -61,5 +54,19 @@ namespace YooAsset.Editor
|
|||||||
reproterWindow.ImportSingleReprotFile(Report);
|
reproterWindow.ImportSingleReprotFile(Report);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存报告文件
|
||||||
|
/// </summary>
|
||||||
|
public void SaveReportFile(string saveDirectory)
|
||||||
|
{
|
||||||
|
if (Report == null)
|
||||||
|
throw new System.Exception("Scan report is invalid !");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(saveDirectory))
|
||||||
|
saveDirectory = "Assets/";
|
||||||
|
string filePath = $"{saveDirectory}/{Report.ReportName}_{Report.ReportDesc}.json";
|
||||||
|
ScanReportConfig.ExportJsonConfig(filePath, Report);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,27 @@ namespace YooAsset.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] GetAllPackAssetPaths()
|
public string[] GetAllPackAssetPaths()
|
||||||
{
|
{
|
||||||
return AllPackAssets.Select(t => t.AssetInfo.AssetPath).ToArray();
|
List<string> results = new List<string>(AllPackAssets.Count);
|
||||||
|
for (int i = 0; i < AllPackAssets.Count; i++)
|
||||||
|
{
|
||||||
|
var packAsset = AllPackAssets[i];
|
||||||
|
results.Add(packAsset.AssetInfo.AssetPath);
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取构建的资源可寻址列表
|
||||||
|
/// </summary>
|
||||||
|
public string[] GetAllPackAssetAddress()
|
||||||
|
{
|
||||||
|
List<string> results = new List<string>(AllPackAssets.Count);
|
||||||
|
for (int i = 0; i < AllPackAssets.Count; i++)
|
||||||
|
{
|
||||||
|
var packAsset = AllPackAssets[i];
|
||||||
|
results.Add(packAsset.Address);
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -153,13 +173,15 @@ namespace YooAsset.Editor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建AssetBundleBuild类
|
/// 创建AssetBundleBuild类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UnityEditor.AssetBundleBuild CreatePipelineBuild()
|
public UnityEditor.AssetBundleBuild CreatePipelineBuild(bool replaceAssetPathWithAddress)
|
||||||
{
|
{
|
||||||
// 注意:我们不再支持AssetBundle的变种机制
|
// 注意:我们不再支持AssetBundle的变种机制
|
||||||
AssetBundleBuild build = new AssetBundleBuild();
|
AssetBundleBuild build = new AssetBundleBuild();
|
||||||
build.assetBundleName = BundleName;
|
build.assetBundleName = BundleName;
|
||||||
build.assetBundleVariant = string.Empty;
|
build.assetBundleVariant = string.Empty;
|
||||||
build.assetNames = GetAllPackAssetPaths();
|
build.assetNames = GetAllPackAssetPaths();
|
||||||
|
if (replaceAssetPathWithAddress)
|
||||||
|
build.addressableNames = GetAllPackAssetAddress();
|
||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,12 +96,12 @@ namespace YooAsset.Editor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取构建管线里需要的数据
|
/// 获取构建管线里需要的数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
|
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds(bool replaceAssetPathWithAddres)
|
||||||
{
|
{
|
||||||
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);
|
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);
|
||||||
foreach (var bundleInfo in _bundleInfoDic.Values)
|
foreach (var bundleInfo in _bundleInfoDic.Values)
|
||||||
{
|
{
|
||||||
builds.Add(bundleInfo.CreatePipelineBuild());
|
builds.Add(bundleInfo.CreatePipelineBuild(replaceAssetPathWithAddres));
|
||||||
}
|
}
|
||||||
return builds.ToArray();
|
return builds.ToArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace YooAsset.Editor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建补丁清单文件到输出目录
|
/// 创建补丁清单文件到输出目录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, BuildContext context)
|
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, bool replaceAssetPathWithAddress, BuildContext context)
|
||||||
{
|
{
|
||||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||||
@@ -36,6 +36,7 @@ namespace YooAsset.Editor
|
|||||||
manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
|
manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
|
||||||
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
|
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
|
||||||
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
|
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
|
||||||
|
manifest.ReplaceAssetPathWithAddress = replaceAssetPathWithAddress;
|
||||||
manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
|
manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
|
||||||
manifest.BuildBundleType = buildParameters.BuildBundleType;
|
manifest.BuildBundleType = buildParameters.BuildBundleType;
|
||||||
manifest.BuildPipeline = buildParameters.BuildPipeline;
|
manifest.BuildPipeline = buildParameters.BuildPipeline;
|
||||||
@@ -58,7 +59,13 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 4. 处理内置资源包
|
// 4. 处理内置资源包
|
||||||
if (processBundleDepends)
|
if (processBundleDepends)
|
||||||
|
{
|
||||||
|
// 注意:初始化资源清单建立引用关系
|
||||||
|
manifest.Initialize();
|
||||||
|
|
||||||
ProcessBuiltinBundleDependency(context, manifest);
|
ProcessBuiltinBundleDependency(context, manifest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 创建资源清单文本文件
|
// 创建资源清单文本文件
|
||||||
{
|
{
|
||||||
@@ -302,9 +309,6 @@ namespace YooAsset.Editor
|
|||||||
#region YOOASSET_LEGACY_DEPENDENCY
|
#region YOOASSET_LEGACY_DEPENDENCY
|
||||||
private void ProcessBuiltinBundleDependency(BuildContext context, PackageManifest manifest)
|
private void ProcessBuiltinBundleDependency(BuildContext context, PackageManifest manifest)
|
||||||
{
|
{
|
||||||
// 注意:初始化资源清单建立引用关系
|
|
||||||
ManifestTools.InitManifest(manifest);
|
|
||||||
|
|
||||||
// 注意:如果是可编程构建管线,需要补充内置资源包
|
// 注意:如果是可编程构建管线,需要补充内置资源包
|
||||||
// 注意:该步骤依赖前面的操作!
|
// 注意:该步骤依赖前面的操作!
|
||||||
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
|
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ namespace YooAsset.Editor
|
|||||||
buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
|
buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
|
||||||
buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
|
buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
|
||||||
buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
|
buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
|
||||||
|
buildReport.Summary.ReplaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
|
||||||
}
|
}
|
||||||
else if (buildParameters is ScriptableBuildParameters)
|
else if (buildParameters is ScriptableBuildParameters)
|
||||||
{
|
{
|
||||||
@@ -61,6 +62,7 @@ namespace YooAsset.Editor
|
|||||||
buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
|
buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
|
||||||
buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
|
buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
|
||||||
buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
|
buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
|
||||||
|
buildReport.Summary.ReplaceAssetPathWithAddress = scriptableBuildParameters.ReplaceAssetPathWithAddress;
|
||||||
buildReport.Summary.WriteLinkXML = scriptableBuildParameters.WriteLinkXML;
|
buildReport.Summary.WriteLinkXML = scriptableBuildParameters.WriteLinkXML;
|
||||||
buildReport.Summary.CacheServerHost = scriptableBuildParameters.CacheServerHost;
|
buildReport.Summary.CacheServerHost = scriptableBuildParameters.CacheServerHost;
|
||||||
buildReport.Summary.CacheServerPort = scriptableBuildParameters.CacheServerPort;
|
buildReport.Summary.CacheServerPort = scriptableBuildParameters.CacheServerPort;
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
bundleInfo.PackageUnityHash = GetUnityHash(bundleInfo, context);
|
bundleInfo.PackageUnityHash = GetUnityHash(bundleInfo, context);
|
||||||
bundleInfo.PackageUnityCRC = GetUnityCRC(bundleInfo, context);
|
bundleInfo.PackageUnityCRC = GetUnityCRC(bundleInfo, context);
|
||||||
bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, buildParametersContext);
|
bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, context);
|
||||||
bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, buildParametersContext);
|
bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, context);
|
||||||
bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, buildParametersContext);
|
bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4.更新补丁包输出的文件路径
|
// 4.更新补丁包输出的文件路径
|
||||||
@@ -62,8 +62,8 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
|
protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
|
||||||
protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
|
protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
|
||||||
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context);
|
||||||
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context);
|
||||||
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,8 @@ namespace YooAsset.Editor
|
|||||||
// 开始构建
|
// 开始构建
|
||||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||||
BuildAssetBundleOptions buildOptions = builtinBuildParameters.GetBundleBuildOptions();
|
BuildAssetBundleOptions buildOptions = builtinBuildParameters.GetBundleBuildOptions();
|
||||||
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), buildOptions, buildParametersContext.Parameters.BuildTarget);
|
var bundleBuilds = buildMapContext.GetPipelineBuilds(builtinBuildParameters.ReplaceAssetPathWithAddress);
|
||||||
|
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, bundleBuilds, buildOptions, buildParametersContext.Parameters.BuildTarget);
|
||||||
if (unityManifest == null)
|
if (unityManifest == null)
|
||||||
{
|
{
|
||||||
string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFailed, "UnityEngine build failed !");
|
string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFailed, "UnityEngine build failed !");
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
void IBuildTask.Run(BuildContext context)
|
void IBuildTask.Run(BuildContext context)
|
||||||
{
|
{
|
||||||
CreateManifestFile(true, true, context);
|
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||||
|
var builtinBuildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
|
||||||
|
bool replaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
|
||||||
|
CreateManifestFile(true, true, replaceAssetPathWithAddress, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
||||||
|
|||||||
@@ -40,17 +40,17 @@ namespace YooAsset.Editor
|
|||||||
throw new Exception(message);
|
throw new Exception(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return HashUtility.FileMD5(filePath);
|
return HashUtility.FileMD5(filePath);
|
||||||
}
|
}
|
||||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return HashUtility.FileCRC32Value(filePath);
|
return HashUtility.FileCRC32Value(filePath);
|
||||||
}
|
}
|
||||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return FileUtility.GetFileSize(filePath);
|
return FileUtility.GetFileSize(filePath);
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ namespace YooAsset.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IgnoreTypeTreeChanges = true;
|
public bool IgnoreTypeTreeChanges = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用可寻址地址代替资源路径
|
||||||
|
/// 说明:开启此项可以节省运行时清单占用的内存!
|
||||||
|
/// </summary>
|
||||||
|
public bool ReplaceAssetPathWithAddress = false;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取内置构建管线的构建选项
|
/// 获取内置构建管线的构建选项
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
void IBuildTask.Run(BuildContext context)
|
void IBuildTask.Run(BuildContext context)
|
||||||
{
|
{
|
||||||
CreateManifestFile(false, false, context);
|
CreateManifestFile(false, true, false, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
||||||
|
|||||||
@@ -19,16 +19,16 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return GetFilePathTempHash(filePath);
|
return GetFilePathTempHash(filePath);
|
||||||
}
|
}
|
||||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
return GetBundleTempSize(bundleInfo);
|
return GetBundleTempSize(bundleInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
void IBuildTask.Run(BuildContext context)
|
void IBuildTask.Run(BuildContext context)
|
||||||
{
|
{
|
||||||
CreateManifestFile(false, true, context);
|
CreateManifestFile(false, true, false, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
||||||
|
|||||||
@@ -15,27 +15,55 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
|
protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||||
return HashUtility.FileMD5(filePath);
|
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)
|
protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||||
return HashUtility.FileMD5(filePath);
|
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;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return HashUtility.FileCRC32Value(filePath);
|
return HashUtility.FileCRC32Value(filePath);
|
||||||
}
|
}
|
||||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return FileUtility.GetFileSize(filePath);
|
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
|
public class RawFileBuildParameters : BuildParameters
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件哈希值计算包含路径信息
|
||||||
|
/// </summary>
|
||||||
|
public bool IncludePathInHash = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,8 @@ namespace YooAsset.Editor
|
|||||||
var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
|
var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
|
||||||
|
|
||||||
// 构建内容
|
// 构建内容
|
||||||
var buildContent = new BundleBuildContent(buildMapContext.GetPipelineBuilds());
|
var bundleBuilds = buildMapContext.GetPipelineBuilds(scriptableBuildParameters.ReplaceAssetPathWithAddress);
|
||||||
|
var buildContent = new BundleBuildContent(bundleBuilds);
|
||||||
|
|
||||||
// 开始构建
|
// 开始构建
|
||||||
IBundleBuildResults buildResults;
|
IBundleBuildResults buildResults;
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
void IBuildTask.Run(BuildContext context)
|
void IBuildTask.Run(BuildContext context)
|
||||||
{
|
{
|
||||||
CreateManifestFile(true, true, context);
|
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||||
|
var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
|
||||||
|
bool replaceAssetPathWithAddress = scriptableBuildParameters.ReplaceAssetPathWithAddress;
|
||||||
|
CreateManifestFile(true, true, replaceAssetPathWithAddress, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
||||||
|
|||||||
@@ -40,17 +40,17 @@ namespace YooAsset.Editor
|
|||||||
throw new Exception(message);
|
throw new Exception(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return HashUtility.FileMD5(filePath);
|
return HashUtility.FileMD5(filePath);
|
||||||
}
|
}
|
||||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return HashUtility.FileCRC32Value(filePath);
|
return HashUtility.FileCRC32Value(filePath);
|
||||||
}
|
}
|
||||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||||
{
|
{
|
||||||
string filePath = bundleInfo.PackageSourceFilePath;
|
string filePath = bundleInfo.PackageSourceFilePath;
|
||||||
return FileUtility.GetFileSize(filePath);
|
return FileUtility.GetFileSize(filePath);
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ namespace YooAsset.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IgnoreTypeTreeChanges = true;
|
public bool IgnoreTypeTreeChanges = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用可寻址地址代替资源路径
|
||||||
|
/// 说明:开启此项可以节省运行时清单占用的内存!
|
||||||
|
/// </summary>
|
||||||
|
public bool ReplaceAssetPathWithAddress = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自动建立资源对象对图集的依赖关系
|
/// 自动建立资源对象对图集的依赖关系
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void BuildButton_clicked()
|
private void BuildButton_clicked()
|
||||||
{
|
{
|
||||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||||
{
|
{
|
||||||
EditorTools.ClearUnityConsole();
|
EditorTools.ClearUnityConsole();
|
||||||
EditorApplication.delayCall += ExecuteBuild;
|
EditorApplication.delayCall += ExecuteBuild;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[Build] 打包已经取消");
|
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void BuildButton_clicked()
|
private void BuildButton_clicked()
|
||||||
{
|
{
|
||||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||||
{
|
{
|
||||||
EditorTools.ClearUnityConsole();
|
EditorTools.ClearUnityConsole();
|
||||||
EditorApplication.delayCall += ExecuteBuild;
|
EditorApplication.delayCall += ExecuteBuild;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[Build] 打包已经取消");
|
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,14 +77,14 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void BuildButton_clicked()
|
private void BuildButton_clicked()
|
||||||
{
|
{
|
||||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||||
{
|
{
|
||||||
EditorTools.ClearUnityConsole();
|
EditorTools.ClearUnityConsole();
|
||||||
EditorApplication.delayCall += ExecuteBuild;
|
EditorApplication.delayCall += ExecuteBuild;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[Build] 打包已经取消");
|
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
private void BuildButton_clicked()
|
private void BuildButton_clicked()
|
||||||
{
|
{
|
||||||
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]!", "Yes", "No"))
|
if (EditorUtility.DisplayDialog("Info", $"Start building resource package [{PackageName}]!", "Yes", "No"))
|
||||||
{
|
{
|
||||||
EditorTools.ClearUnityConsole();
|
EditorTools.ClearUnityConsole();
|
||||||
EditorApplication.delayCall += ExecuteBuild;
|
EditorApplication.delayCall += ExecuteBuild;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[Build] 打包已经取消");
|
Debug.LogWarning("[Build] Packaging has been canceled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 包裹名称
|
// 包裹名称
|
||||||
_packageNameTxt = root.Q<TextField>("PackageName");
|
_packageNameTxt = root.Q<TextField>("PackageName");
|
||||||
|
_packageNameTxt.isDelayed = true;
|
||||||
_packageNameTxt.RegisterValueChangedCallback(evt =>
|
_packageNameTxt.RegisterValueChangedCallback(evt =>
|
||||||
{
|
{
|
||||||
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
||||||
@@ -249,6 +250,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 包裹备注
|
// 包裹备注
|
||||||
_packageDescTxt = root.Q<TextField>("PackageDesc");
|
_packageDescTxt = root.Q<TextField>("PackageDesc");
|
||||||
|
_packageDescTxt.isDelayed = true;
|
||||||
_packageDescTxt.RegisterValueChangedCallback(evt =>
|
_packageDescTxt.RegisterValueChangedCallback(evt =>
|
||||||
{
|
{
|
||||||
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
||||||
@@ -286,6 +288,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 分组名称
|
// 分组名称
|
||||||
_groupNameTxt = root.Q<TextField>("GroupName");
|
_groupNameTxt = root.Q<TextField>("GroupName");
|
||||||
|
_groupNameTxt.isDelayed = true;
|
||||||
_groupNameTxt.RegisterValueChangedCallback(evt =>
|
_groupNameTxt.RegisterValueChangedCallback(evt =>
|
||||||
{
|
{
|
||||||
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
||||||
@@ -300,6 +303,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 分组备注
|
// 分组备注
|
||||||
_groupDescTxt = root.Q<TextField>("GroupDesc");
|
_groupDescTxt = root.Q<TextField>("GroupDesc");
|
||||||
|
_groupDescTxt.isDelayed = true;
|
||||||
_groupDescTxt.RegisterValueChangedCallback(evt =>
|
_groupDescTxt.RegisterValueChangedCallback(evt =>
|
||||||
{
|
{
|
||||||
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
||||||
@@ -314,6 +318,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// 分组的资源标签
|
// 分组的资源标签
|
||||||
_groupTagsTxt = root.Q<TextField>("GroupTags");
|
_groupTagsTxt = root.Q<TextField>("GroupTags");
|
||||||
|
_groupTagsTxt.isDelayed = true;
|
||||||
_groupTagsTxt.RegisterValueChangedCallback(evt =>
|
_groupTagsTxt.RegisterValueChangedCallback(evt =>
|
||||||
{
|
{
|
||||||
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
|
||||||
@@ -817,6 +822,7 @@ namespace YooAsset.Editor
|
|||||||
var textField = new TextField();
|
var textField = new TextField();
|
||||||
textField.name = "TextField0";
|
textField.name = "TextField0";
|
||||||
textField.label = "User Data";
|
textField.label = "User Data";
|
||||||
|
textField.isDelayed = true;
|
||||||
textField.style.width = 200;
|
textField.style.width = 200;
|
||||||
elementBottom.Add(textField);
|
elementBottom.Add(textField);
|
||||||
var label = textField.Q<Label>();
|
var label = textField.Q<Label>();
|
||||||
@@ -826,6 +832,7 @@ namespace YooAsset.Editor
|
|||||||
var textField = new TextField();
|
var textField = new TextField();
|
||||||
textField.name = "TextField1";
|
textField.name = "TextField1";
|
||||||
textField.label = "Asset Tags";
|
textField.label = "Asset Tags";
|
||||||
|
textField.isDelayed = true;
|
||||||
textField.style.width = 100;
|
textField.style.width = 100;
|
||||||
textField.style.marginLeft = 20;
|
textField.style.marginLeft = 20;
|
||||||
textField.style.flexGrow = 1;
|
textField.style.flexGrow = 1;
|
||||||
|
|||||||
@@ -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: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: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: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="RemoveBtn" />
|
||||||
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||||
</ui:VisualElement>
|
</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 Name" name="PackageName" style="flex-direction: column;" />
|
||||||
<ui:TextField picking-mode="Ignore" label="Package Desc" name="PackageDesc" 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: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="RemoveBtn" />
|
||||||
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ namespace YooAsset.Editor
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ClearDatabase(true);
|
|
||||||
Debug.LogError($"Failed to load cache database : {ex.Message}");
|
Debug.LogError($"Failed to load cache database : {ex.Message}");
|
||||||
|
ClearDatabase(true);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -169,7 +169,8 @@ namespace YooAsset.Editor
|
|||||||
File.Delete(_databaseFilePath);
|
File.Delete(_databaseFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
_database.Clear();
|
if (_database != null)
|
||||||
|
_database.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ namespace YooAsset.Editor
|
|||||||
public ECompressOption CompressOption;
|
public ECompressOption CompressOption;
|
||||||
public bool DisableWriteTypeTree;
|
public bool DisableWriteTypeTree;
|
||||||
public bool IgnoreTypeTreeChanges;
|
public bool IgnoreTypeTreeChanges;
|
||||||
|
public bool ReplaceAssetPathWithAddress;
|
||||||
public bool WriteLinkXML = true;
|
public bool WriteLinkXML = true;
|
||||||
public string CacheServerHost;
|
public string CacheServerHost;
|
||||||
public int CacheServerPort;
|
public int CacheServerPort;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ namespace YooAsset.Editor
|
|||||||
BindListViewItem("CompressOption", $"{buildReport.Summary.CompressOption}");
|
BindListViewItem("CompressOption", $"{buildReport.Summary.CompressOption}");
|
||||||
BindListViewItem("DisableWriteTypeTree", $"{buildReport.Summary.DisableWriteTypeTree}");
|
BindListViewItem("DisableWriteTypeTree", $"{buildReport.Summary.DisableWriteTypeTree}");
|
||||||
BindListViewItem("IgnoreTypeTreeChanges", $"{buildReport.Summary.IgnoreTypeTreeChanges}");
|
BindListViewItem("IgnoreTypeTreeChanges", $"{buildReport.Summary.IgnoreTypeTreeChanges}");
|
||||||
|
BindListViewItem("ReplaceAssetPathWithAddress", $"{buildReport.Summary.ReplaceAssetPathWithAddress}");
|
||||||
BindListViewItem(string.Empty, string.Empty);
|
BindListViewItem(string.Empty, string.Empty);
|
||||||
|
|
||||||
BindListViewHeader("Build Results");
|
BindListViewHeader("Build Results");
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ namespace YooAsset.Editor
|
|||||||
Texture,
|
Texture,
|
||||||
RenderTexture,
|
RenderTexture,
|
||||||
VideoClip,
|
VideoClip,
|
||||||
|
PlayableAsset,
|
||||||
|
TimelineAsset
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a8f060786f8775b4a82cc3f55d9135e2
|
guid: bb70e2274ce5a5d419cfbd7212efdf4a
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
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
|
fileFormatVersion: 2
|
||||||
guid: e01cc308d7179a34281087fafe455b42
|
guid: 6f635344c08e2b04295a108c2bcc6a40
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
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
|
fileFormatVersion: 2
|
||||||
guid: 6602c4be2ef295546b7bbb328de8fb0c
|
guid: 38884a96e8c2df74082d4e059e2e73ed
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
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
|
fileFormatVersion: 2
|
||||||
guid: 9e71e850eded0da43906cb4f7cb75629
|
guid: 76b0712524ed69542914db8e44fa64fd
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
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
|
fileFormatVersion: 2
|
||||||
guid: 375d88bcf5b9a6146adaf98ceb5369f8
|
guid: 101a4be1bb0a85c4d84ecbf3e74f89e4
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
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)
|
public static bool IsRequestLocalFile(string url)
|
||||||
{
|
{
|
||||||
//TODO UNITY_STANDALONE_OSX平台目前无法确定
|
//TODO UNITY_STANDALONE_OSX平台目前无法确定
|
||||||
|
|
||||||
|
// 本地文件传输协议
|
||||||
if (url.StartsWith("file:"))
|
if (url.StartsWith("file:"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// JAR文件协议
|
||||||
if (url.StartsWith("jar:file:"))
|
if (url.StartsWith("jar:file:"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4630dac2050606043bb146325fdce6ad
|
guid: d724672f4d6f24b4db435d10eef6c40d
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
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:
|
|
||||||
@@ -63,14 +63,19 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
"link.xml",
|
"link.xml",
|
||||||
"buildlogtep.json",
|
"buildlogtep.json",
|
||||||
$"{packageName}.version",
|
|
||||||
$"{packageName}_{packageVersion}.bytes",
|
|
||||||
$"{packageName}_{packageVersion}.hash",
|
|
||||||
$"{packageName}_{packageVersion}.json",
|
|
||||||
$"{packageName}_{packageVersion}.report",
|
|
||||||
DefaultBuildinFileSystemDefine.BuildinCatalogJsonFileName,
|
DefaultBuildinFileSystemDefine.BuildinCatalogJsonFileName,
|
||||||
DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName
|
DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName
|
||||||
};
|
};
|
||||||
|
string packageVersionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
||||||
|
string packageHashFileName = YooAssetSettingsData.GetPackageHashFileName(packageName, packageVersion);
|
||||||
|
string manifestBinaryFIleName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
|
||||||
|
string manifestJsonFIleName = YooAssetSettingsData.GetManifestJsonFileName(packageName, packageVersion);
|
||||||
|
string reportFileName = YooAssetSettingsData.GetBuildReportFileName(packageName, packageVersion);
|
||||||
|
whiteFileList.Add(packageVersionFileName);
|
||||||
|
whiteFileList.Add(packageHashFileName);
|
||||||
|
whiteFileList.Add(manifestBinaryFIleName);
|
||||||
|
whiteFileList.Add(manifestJsonFIleName);
|
||||||
|
whiteFileList.Add(reportFileName);
|
||||||
|
|
||||||
// 记录所有内置资源文件
|
// 记录所有内置资源文件
|
||||||
DirectoryInfo rootDirectory = new DirectoryInfo(packageDirectory);
|
DirectoryInfo rootDirectory = new DirectoryInfo(packageDirectory);
|
||||||
@@ -113,6 +118,34 @@ namespace YooAsset
|
|||||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
||||||
return true;
|
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
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ namespace YooAsset
|
|||||||
protected IFileSystem _unpackFileSystem;
|
protected IFileSystem _unpackFileSystem;
|
||||||
protected string _packageRoot;
|
protected string _packageRoot;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载后台接口
|
||||||
|
/// </summary>
|
||||||
|
public IDownloadBackend DownloadBackend { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 包裹名称
|
/// 包裹名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -66,7 +71,7 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int FileVerifyMaxConcurrency { private set; get; } = int.MaxValue;
|
public int FileVerifyMaxConcurrency { private set; get; } = 32;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:数据文件追加文件格式
|
/// 自定义参数:数据文件追加文件格式
|
||||||
@@ -90,7 +95,12 @@ namespace YooAsset
|
|||||||
public string CopyBuildinPackageManifestDestRoot { private set; get; }
|
public string CopyBuildinPackageManifestDestRoot { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:解密方法类
|
/// 自定义参数:解压文件系统的根目录
|
||||||
|
/// </summary>
|
||||||
|
public string UnpackFileSystemRoot { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义参数:解密服务接口的实例类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDecryptionServices DecryptionServices { private set; get; }
|
public IDecryptionServices DecryptionServices { private set; get; }
|
||||||
|
|
||||||
@@ -100,7 +110,7 @@ namespace YooAsset
|
|||||||
public IManifestRestoreServices ManifestServices { private set; get; }
|
public IManifestRestoreServices ManifestServices { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:拷贝内置文件服务类
|
/// 自定义参数:拷贝内置文件接口的实例类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
|
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
|
||||||
#endregion
|
#endregion
|
||||||
@@ -151,6 +161,13 @@ namespace YooAsset
|
|||||||
var operation = new DBFSLoadRawBundleOperation(this, bundle);
|
var operation = new DBFSLoadRawBundleOperation(this, bundle);
|
||||||
return operation;
|
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
|
else
|
||||||
{
|
{
|
||||||
string error = $"{nameof(DefaultBuildinFileSystem)} not support load bundle type : {bundle.BundleType}";
|
string error = $"{nameof(DefaultBuildinFileSystem)} not support load bundle type : {bundle.BundleType}";
|
||||||
@@ -190,6 +207,10 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
CopyBuildinPackageManifestDestRoot = (string)value;
|
CopyBuildinPackageManifestDestRoot = (string)value;
|
||||||
}
|
}
|
||||||
|
else if (name == FileSystemParametersDefine.UNPACK_FILE_SYSTEM_ROOT)
|
||||||
|
{
|
||||||
|
UnpackFileSystemRoot = (string)value;
|
||||||
|
}
|
||||||
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
|
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
|
||||||
{
|
{
|
||||||
DecryptionServices = (IDecryptionServices)value;
|
DecryptionServices = (IDecryptionServices)value;
|
||||||
@@ -216,6 +237,10 @@ namespace YooAsset
|
|||||||
else
|
else
|
||||||
_packageRoot = packageRoot;
|
_packageRoot = packageRoot;
|
||||||
|
|
||||||
|
// 创建默认的下载后台接口
|
||||||
|
if (DownloadBackend == null)
|
||||||
|
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||||
|
|
||||||
// 创建解压文件系统
|
// 创建解压文件系统
|
||||||
var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
|
var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
|
||||||
_unpackFileSystem = new DefaultUnpackFileSystem();
|
_unpackFileSystem = new DefaultUnpackFileSystem();
|
||||||
@@ -226,7 +251,7 @@ namespace YooAsset
|
|||||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
|
||||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
|
||||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES, CopyLocalFileServices);
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES, CopyLocalFileServices);
|
||||||
_unpackFileSystem.OnCreate(packageName, null);
|
_unpackFileSystem.OnCreate(packageName, UnpackFileSystemRoot);
|
||||||
}
|
}
|
||||||
public virtual void OnDestroy()
|
public virtual void OnDestroy()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ namespace YooAsset
|
|||||||
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||||
string destFilePath = GetCopyPackageHashDestPath(packageVersion);
|
string destFilePath = GetCopyPackageHashDestPath(packageVersion);
|
||||||
string sourceFilePath = _fileSystem.GetBuildinPackageHashFilePath(packageVersion);
|
string sourceFilePath = _fileSystem.GetBuildinPackageHashFilePath(packageVersion);
|
||||||
_copyBuildinHashFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
|
_copyBuildinHashFileOp = new CopyBuildinFileOperation(_fileSystem, sourceFilePath, destFilePath);
|
||||||
_copyBuildinHashFileOp.StartOperation();
|
_copyBuildinHashFileOp.StartOperation();
|
||||||
AddChildOperation(_copyBuildinHashFileOp);
|
AddChildOperation(_copyBuildinHashFileOp);
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ namespace YooAsset
|
|||||||
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||||
string destFilePath = GetCopyPackageManifestDestPath(packageVersion);
|
string destFilePath = GetCopyPackageManifestDestPath(packageVersion);
|
||||||
string sourceFilePath = _fileSystem.GetBuildinPackageManifestFilePath(packageVersion);
|
string sourceFilePath = _fileSystem.GetBuildinPackageManifestFilePath(packageVersion);
|
||||||
_copyBuildinManifestFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
|
_copyBuildinManifestFileOp = new CopyBuildinFileOperation(_fileSystem, sourceFilePath, destFilePath);
|
||||||
_copyBuildinManifestFileOp.StartOperation();
|
_copyBuildinManifestFileOp.StartOperation();
|
||||||
AddChildOperation(_copyBuildinManifestFileOp);
|
AddChildOperation(_copyBuildinManifestFileOp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,15 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private UnityWebFileRequestOperation _webFileRequestOp;
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
private readonly string _sourceFilePath;
|
private readonly string _sourceFilePath;
|
||||||
private readonly string _destFilePath;
|
private readonly string _destFilePath;
|
||||||
|
private IDownloadFileRequest _webFileRequestOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public CopyBuildinFileOperation(string sourceFilePath, string destFilePath)
|
public CopyBuildinFileOperation(DefaultBuildinFileSystem fileSystem, string sourceFilePath, string destFilePath)
|
||||||
{
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
_sourceFilePath = sourceFilePath;
|
_sourceFilePath = sourceFilePath;
|
||||||
_destFilePath = destFilePath;
|
_destFilePath = destFilePath;
|
||||||
}
|
}
|
||||||
@@ -76,16 +78,15 @@ namespace YooAsset
|
|||||||
if (_webFileRequestOp == null)
|
if (_webFileRequestOp == null)
|
||||||
{
|
{
|
||||||
string url = DownloadSystemHelper.ConvertToWWWPath(_sourceFilePath);
|
string url = DownloadSystemHelper.ConvertToWWWPath(_sourceFilePath);
|
||||||
_webFileRequestOp = new UnityWebFileRequestOperation(url, _destFilePath, 60);
|
var args = new DownloadFileRequestArgs(url, _destFilePath, 60, 0);
|
||||||
_webFileRequestOp.StartOperation();
|
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||||
AddChildOperation(_webFileRequestOp);
|
_webFileRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webFileRequestOp.UpdateOperation();
|
|
||||||
if (_webFileRequestOp.IsDone == false)
|
if (_webFileRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
|
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeed;
|
Status = EOperationStatus.Succeed;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
private IDownloadBytesRequest _webDataRequestOp;
|
||||||
private byte[] _fileData;
|
private byte[] _fileData;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
@@ -57,16 +57,15 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, 60);
|
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||||
_webDataRequestOp.StartOperation();
|
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||||
AddChildOperation(_webDataRequestOp);
|
_webDataRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webDataRequestOp.UpdateOperation();
|
|
||||||
if (_webDataRequestOp.IsDone == false)
|
if (_webDataRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
_fileData = _webDataRequestOp.Result;
|
_fileData = _webDataRequestOp.Result;
|
||||||
_steps = ESteps.LoadCatalog;
|
_steps = ESteps.LoadCatalog;
|
||||||
@@ -87,11 +86,11 @@ namespace YooAsset
|
|||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeed;
|
Status = EOperationStatus.Succeed;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
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 DefaultBuildinFileSystem _fileSystem;
|
||||||
private readonly string _packageVersion;
|
private readonly string _packageVersion;
|
||||||
private readonly string _packageHash;
|
private readonly string _packageHash;
|
||||||
private UnityWebDataRequestOperation _webDataRequestOp;
|
private IDownloadBytesRequest _webDataRequestOp;
|
||||||
private DeserializeManifestOperation _deserializer;
|
private DeserializeManifestOperation _deserializer;
|
||||||
private byte[] _fileData;
|
private byte[] _fileData;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
@@ -63,16 +63,15 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
|
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
|
||||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||||
_webDataRequestOp = new UnityWebDataRequestOperation(url, 60);
|
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||||
_webDataRequestOp.StartOperation();
|
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||||
AddChildOperation(_webDataRequestOp);
|
_webDataRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webDataRequestOp.UpdateOperation();
|
|
||||||
if (_webDataRequestOp.IsDone == false)
|
if (_webDataRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
_fileData = _webDataRequestOp.Result;
|
_fileData = _webDataRequestOp.Result;
|
||||||
_steps = ESteps.VerifyFileData;
|
_steps = ESteps.VerifyFileData;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
|||||||
|
|
||||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
private readonly string _packageVersion;
|
private readonly string _packageVersion;
|
||||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
private IDownloadTextRequest _webTextRequestOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -58,16 +58,15 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
string filePath = _fileSystem.GetBuildinPackageHashFilePath(_packageVersion);
|
string filePath = _fileSystem.GetBuildinPackageHashFilePath(_packageVersion);
|
||||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, 60);
|
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||||
_webTextRequestOp.StartOperation();
|
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||||
AddChildOperation(_webTextRequestOp);
|
_webTextRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webTextRequestOp.UpdateOperation();
|
|
||||||
if (_webTextRequestOp.IsDone == false)
|
if (_webTextRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
PackageHash = _webTextRequestOp.Result;
|
PackageHash = _webTextRequestOp.Result;
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.CheckResult;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
private IDownloadTextRequest _webTextRequestOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -56,16 +56,15 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
string filePath = _fileSystem.GetBuildinPackageVersionFilePath();
|
string filePath = _fileSystem.GetBuildinPackageVersionFilePath();
|
||||||
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, 60);
|
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||||
_webTextRequestOp.StartOperation();
|
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||||
AddChildOperation(_webTextRequestOp);
|
_webTextRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webTextRequestOp.UpdateOperation();
|
|
||||||
if (_webTextRequestOp.IsDone == false)
|
if (_webTextRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
PackageVersion = _webTextRequestOp.Result;
|
PackageVersion = _webTextRequestOp.Result;
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.CheckResult;
|
||||||
|
|||||||
@@ -23,10 +23,14 @@ namespace YooAsset
|
|||||||
protected string _cacheManifestFilesRoot;
|
protected string _cacheManifestFilesRoot;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载中心
|
/// 下载调度器
|
||||||
/// 说明:当异步操作任务终止的时候,所有下载子任务都会一同被终止!
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DownloadCenterOperation DownloadCenter { set; get; }
|
public DownloadSchedulerOperation DownloadScheduler { set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载后台接口
|
||||||
|
/// </summary>
|
||||||
|
public IDownloadBackend DownloadBackend { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 包裹名称
|
/// 包裹名称
|
||||||
@@ -57,7 +61,7 @@ namespace YooAsset
|
|||||||
|
|
||||||
#region 自定义参数
|
#region 自定义参数
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:远程服务接口
|
/// 自定义参数:远程服务接口的实例类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IRemoteServices RemoteServices { private set; get; }
|
public IRemoteServices RemoteServices { private set; get; }
|
||||||
|
|
||||||
@@ -73,8 +77,10 @@ namespace YooAsset
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
||||||
|
/// 默认值:32(推荐范围 1-128)
|
||||||
|
/// 说明:过大的值可能导致线程池任务过多,影响系统稳定性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int FileVerifyMaxConcurrency { private set; get; } = int.MaxValue;
|
public int FileVerifyMaxConcurrency { private set; get; } = 32;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:数据文件追加文件格式
|
/// 自定义参数:数据文件追加文件格式
|
||||||
@@ -88,18 +94,22 @@ namespace YooAsset
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:最大并发连接数
|
/// 自定义参数:最大并发连接数
|
||||||
|
/// 默认值:10(推荐范围 1-32)
|
||||||
|
/// 说明:过大的并发数可能被服务器限流,也会增加本地资源消耗
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DownloadMaxConcurrency { private set; get; } = int.MaxValue;
|
public int DownloadMaxConcurrency { private set; get; } = 10;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:每帧发起的最大请求数
|
/// 自定义参数:每帧发起的最大请求数
|
||||||
|
/// 默认值:5(推荐范围 1-10)
|
||||||
|
/// 说明:避免单帧发起过多请求导致卡顿
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DownloadMaxRequestPerFrame { private set; get; } = int.MaxValue;
|
public int DownloadMaxRequestPerFrame { private set; get; } = 5;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:下载任务的看门狗机制监控时间
|
/// 自定义参数:下载任务的看门狗机制监控时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DownloadWatchDogTime { private set; get; } = int.MaxValue;
|
public int DownloadWatchDogTime { private set; get; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:启用断点续传的最小尺寸
|
/// 自定义参数:启用断点续传的最小尺寸
|
||||||
@@ -112,7 +122,7 @@ namespace YooAsset
|
|||||||
public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
|
public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:解密方法类
|
/// 自定义参数:解密服务接口的实例类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDecryptionServices DecryptionServices { private set; get; }
|
public IDecryptionServices DecryptionServices { private set; get; }
|
||||||
|
|
||||||
@@ -122,7 +132,7 @@ namespace YooAsset
|
|||||||
public IManifestRestoreServices ManifestServices { private set; get; }
|
public IManifestRestoreServices ManifestServices { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义参数:拷贝内置文件服务类
|
/// 自定义参数:拷贝内置文件接口的实例类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
|
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
|
||||||
#endregion
|
#endregion
|
||||||
@@ -158,6 +168,11 @@ namespace YooAsset
|
|||||||
var operation = new ClearUnusedCacheBundleFilesOperation(this, manifest);
|
var operation = new ClearUnusedCacheBundleFilesOperation(this, manifest);
|
||||||
return operation;
|
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())
|
else if (options.ClearMode == EFileClearMode.ClearBundleFilesByTags.ToString())
|
||||||
{
|
{
|
||||||
var operation = new ClearCacheBundleFilesByTagsOperaiton(this, manifest, options.ClearParam);
|
var operation = new ClearCacheBundleFilesByTagsOperaiton(this, manifest, options.ClearParam);
|
||||||
@@ -237,7 +252,14 @@ namespace YooAsset
|
|||||||
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
|
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
|
||||||
{
|
{
|
||||||
int convertValue = Convert.ToInt32(value);
|
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)
|
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
|
||||||
{
|
{
|
||||||
@@ -250,17 +272,27 @@ namespace YooAsset
|
|||||||
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
|
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
|
||||||
{
|
{
|
||||||
int convertValue = Convert.ToInt32(value);
|
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)
|
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME)
|
||||||
{
|
{
|
||||||
int convertValue = Convert.ToInt32(value);
|
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)
|
else if (name == FileSystemParametersDefine.DOWNLOAD_WATCH_DOG_TIME)
|
||||||
{
|
{
|
||||||
int convertValue = Convert.ToInt32(value);
|
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)
|
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE)
|
||||||
{
|
{
|
||||||
@@ -299,13 +331,17 @@ namespace YooAsset
|
|||||||
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
|
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
|
||||||
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
||||||
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
|
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
|
||||||
|
|
||||||
|
// 创建默认的下载后台接口
|
||||||
|
if (DownloadBackend == null)
|
||||||
|
DownloadBackend = new UnityWebRequestBackend(DownloadSystemHelper.UnityWebRequestCreater);
|
||||||
}
|
}
|
||||||
public virtual void OnDestroy()
|
public virtual void OnDestroy()
|
||||||
{
|
{
|
||||||
if (DownloadCenter != null)
|
if (DownloadScheduler != null)
|
||||||
{
|
{
|
||||||
DownloadCenter.AbortOperation();
|
DownloadScheduler.Dispose();
|
||||||
DownloadCenter = null;
|
DownloadScheduler = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +507,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
if (_records.ContainsKey(bundle.BundleGUID))
|
if (_records.ContainsKey(bundle.BundleGUID))
|
||||||
{
|
{
|
||||||
throw new Exception("Should never get here !");
|
throw new YooInternalException();
|
||||||
}
|
}
|
||||||
|
|
||||||
string infoFilePath = GetBundleInfoFilePath(bundle);
|
string infoFilePath = GetBundleInfoFilePath(bundle);
|
||||||
@@ -493,9 +529,9 @@ namespace YooAsset
|
|||||||
// 写入文件信息
|
// 写入文件信息
|
||||||
WriteBundleInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ namespace YooAsset
|
|||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
Directory.Delete(FileRootPath, true);
|
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,
|
CheckAppFootPrint,
|
||||||
SearchCacheFiles,
|
SearchCacheFiles,
|
||||||
VerifyCacheFiles,
|
VerifyCacheFiles,
|
||||||
CreateDownloadCenter,
|
CreateDownloadScheduler,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_verifyCacheFilesOp.Status == EOperationStatus.Succeed)
|
if (_verifyCacheFilesOp.Status == EOperationStatus.Succeed)
|
||||||
{
|
{
|
||||||
_steps = ESteps.CreateDownloadCenter;
|
_steps = ESteps.CreateDownloadScheduler;
|
||||||
YooLogger.Log($"Package '{_fileSystem.PackageName}' '{_fileSystem.GetType().Name}' cached files count : {_fileSystem.FileCount}");
|
YooLogger.Log($"Package '{_fileSystem.PackageName}' '{_fileSystem.GetType().Name}' cached files count : {_fileSystem.FileCount}");
|
||||||
}
|
}
|
||||||
else
|
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);
|
_fileSystem.DownloadScheduler = new DownloadSchedulerOperation(_fileSystem);
|
||||||
OperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadCenter);
|
OperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace YooAsset
|
|||||||
None,
|
None,
|
||||||
CheckExist,
|
CheckExist,
|
||||||
DownloadFile,
|
DownloadFile,
|
||||||
|
AbortDownload,
|
||||||
LoadAssetBundle,
|
LoadAssetBundle,
|
||||||
CheckResult,
|
CheckResult,
|
||||||
Done,
|
Done,
|
||||||
@@ -63,6 +64,17 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.DownloadFile)
|
||||||
|
{
|
||||||
|
// 中断下载
|
||||||
|
if (AbortDownloadFile)
|
||||||
|
{
|
||||||
|
if (_downloadFileOp != null)
|
||||||
|
_downloadFileOp.AbortOperation();
|
||||||
|
_steps = ESteps.AbortDownload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.DownloadFile)
|
if (_steps == ESteps.DownloadFile)
|
||||||
{
|
{
|
||||||
if (_downloadFileOp == null)
|
if (_downloadFileOp == null)
|
||||||
@@ -94,6 +106,23 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.AbortDownload)
|
||||||
|
{
|
||||||
|
if (_downloadFileOp != null)
|
||||||
|
{
|
||||||
|
if (IsWaitForAsyncComplete)
|
||||||
|
_downloadFileOp.WaitForAsyncComplete();
|
||||||
|
|
||||||
|
_downloadFileOp.UpdateOperation();
|
||||||
|
if (_downloadFileOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = "Abort download file !";
|
||||||
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.LoadAssetBundle)
|
if (_steps == ESteps.LoadAssetBundle)
|
||||||
{
|
{
|
||||||
if (_bundle.Encrypted)
|
if (_bundle.Encrypted)
|
||||||
@@ -251,6 +280,7 @@ namespace YooAsset
|
|||||||
None,
|
None,
|
||||||
CheckExist,
|
CheckExist,
|
||||||
DownloadFile,
|
DownloadFile,
|
||||||
|
AbortDownload,
|
||||||
LoadCacheRawBundle,
|
LoadCacheRawBundle,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
@@ -290,11 +320,11 @@ namespace YooAsset
|
|||||||
File.Move(recordFileElement.DataFilePath, filePath);
|
File.Move(recordFileElement.DataFilePath, filePath);
|
||||||
_steps = ESteps.LoadCacheRawBundle;
|
_steps = ESteps.LoadCacheRawBundle;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Faild rename raw data file : {e.Message}";
|
Error = $"Faild rename raw data file : {ex.Message}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -310,6 +340,17 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.DownloadFile)
|
||||||
|
{
|
||||||
|
// 中断下载
|
||||||
|
if (AbortDownloadFile)
|
||||||
|
{
|
||||||
|
if (_downloadFileOp != null)
|
||||||
|
_downloadFileOp.AbortOperation();
|
||||||
|
_steps = ESteps.AbortDownload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.DownloadFile)
|
if (_steps == ESteps.DownloadFile)
|
||||||
{
|
{
|
||||||
if (_downloadFileOp == null)
|
if (_downloadFileOp == null)
|
||||||
@@ -341,6 +382,23 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.AbortDownload)
|
||||||
|
{
|
||||||
|
if (_downloadFileOp != null)
|
||||||
|
{
|
||||||
|
if (IsWaitForAsyncComplete)
|
||||||
|
_downloadFileOp.WaitForAsyncComplete();
|
||||||
|
|
||||||
|
_downloadFileOp.UpdateOperation();
|
||||||
|
if (_downloadFileOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = "Abort download file !";
|
||||||
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.LoadCacheRawBundle)
|
if (_steps == ESteps.LoadCacheRawBundle)
|
||||||
{
|
{
|
||||||
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||||
|
|||||||
@@ -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
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
@@ -17,10 +18,10 @@ namespace YooAsset
|
|||||||
// 下载参数
|
// 下载参数
|
||||||
protected readonly DefaultCacheFileSystem _fileSystem;
|
protected readonly DefaultCacheFileSystem _fileSystem;
|
||||||
protected readonly DownloadFileOptions _options;
|
protected readonly DownloadFileOptions _options;
|
||||||
private UnityDownloadFileOperation _unityDownloadFileOp;
|
private DownloadAndCacheFileOperation _downloadFileOp;
|
||||||
|
|
||||||
protected int _requestCount = 0;
|
protected int _requestCount = 0;
|
||||||
protected float _tryAgainTimer;
|
protected float _tryAgainTimer = 0;
|
||||||
protected int _failedTryAgain;
|
protected int _failedTryAgain;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
string url = GetRequestURL();
|
string url = GetRequestURL();
|
||||||
_unityDownloadFileOp = _fileSystem.DownloadCenter.DownloadFileAsync(Bundle, url);
|
_downloadFileOp = _fileSystem.DownloadScheduler.DownloadAndCacheFileAsync(Bundle, url);
|
||||||
_steps = ESteps.CheckRequest;
|
_steps = ESteps.CheckRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,20 +76,16 @@ namespace YooAsset
|
|||||||
if (_steps == ESteps.CheckRequest)
|
if (_steps == ESteps.CheckRequest)
|
||||||
{
|
{
|
||||||
if (IsWaitForAsyncComplete)
|
if (IsWaitForAsyncComplete)
|
||||||
_unityDownloadFileOp.WaitForAsyncComplete();
|
_downloadFileOp.WaitForAsyncComplete();
|
||||||
|
|
||||||
// 因为并发数量限制,下载器可能被挂起!
|
_downloadFileOp.UpdateOperation();
|
||||||
if (_unityDownloadFileOp.Status == EOperationStatus.None)
|
Progress = _downloadFileOp.Progress;
|
||||||
|
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||||
|
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||||
|
if (_downloadFileOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_unityDownloadFileOp.UpdateOperation();
|
if (_downloadFileOp.Status == EOperationStatus.Succeed)
|
||||||
Progress = _unityDownloadFileOp.Progress;
|
|
||||||
DownloadedBytes = _unityDownloadFileOp.DownloadedBytes;
|
|
||||||
DownloadProgress = _unityDownloadFileOp.DownloadProgress;
|
|
||||||
if (_unityDownloadFileOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_unityDownloadFileOp.Status == EOperationStatus.Succeed)
|
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeed;
|
Status = EOperationStatus.Succeed;
|
||||||
@@ -98,13 +95,13 @@ namespace YooAsset
|
|||||||
if (IsWaitForAsyncComplete == false && _failedTryAgain > 0)
|
if (IsWaitForAsyncComplete == false && _failedTryAgain > 0)
|
||||||
{
|
{
|
||||||
_steps = ESteps.TryAgain;
|
_steps = ESteps.TryAgain;
|
||||||
YooLogger.Warning($"Failed download : {_unityDownloadFileOp.URL} Try again !");
|
YooLogger.Warning($"Failed download : {_downloadFileOp.URL} Try again !");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = _unityDownloadFileOp.Error;
|
Error = _downloadFileOp.Error;
|
||||||
YooLogger.Error(Error);
|
YooLogger.Error(Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,9 +138,9 @@ namespace YooAsset
|
|||||||
// 注意:取消下载任务的时候引用计数减一
|
// 注意:取消下载任务的时候引用计数减一
|
||||||
if (_steps != ESteps.Done)
|
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 DefaultCacheFileSystem _fileSystem;
|
||||||
private readonly string _packageVersion;
|
private readonly string _packageVersion;
|
||||||
private readonly int _timeout;
|
private readonly int _timeout;
|
||||||
private UnityWebFileRequestOperation _webFileRequestOp;
|
private IDownloadFileRequest _webFileRequestOp;
|
||||||
private int _requestCount = 0;
|
private int _requestCount = 0;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
@@ -57,16 +57,16 @@ namespace YooAsset
|
|||||||
string savePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
string savePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
||||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
|
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
|
||||||
string webURL = GetWebRequestURL(fileName);
|
string webURL = GetWebRequestURL(fileName);
|
||||||
_webFileRequestOp = new UnityWebFileRequestOperation(webURL, savePath, _timeout);
|
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||||
_webFileRequestOp.StartOperation();
|
var args = new DownloadFileRequestArgs(webURL, savePath, _timeout, watchdogTime);
|
||||||
AddChildOperation(_webFileRequestOp);
|
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||||
|
_webFileRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webFileRequestOp.UpdateOperation();
|
|
||||||
if (_webFileRequestOp.IsDone == false)
|
if (_webFileRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
|
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeed;
|
Status = EOperationStatus.Succeed;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace YooAsset
|
|||||||
private readonly DefaultCacheFileSystem _fileSystem;
|
private readonly DefaultCacheFileSystem _fileSystem;
|
||||||
private readonly string _packageVersion;
|
private readonly string _packageVersion;
|
||||||
private readonly int _timeout;
|
private readonly int _timeout;
|
||||||
private UnityWebFileRequestOperation _webFileRequestOp;
|
private IDownloadFileRequest _webFileRequestOp;
|
||||||
private int _requestCount = 0;
|
private int _requestCount = 0;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
@@ -57,16 +57,16 @@ namespace YooAsset
|
|||||||
string savePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
string savePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
||||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
|
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
|
||||||
string webURL = GetDownloadRequestURL(fileName);
|
string webURL = GetDownloadRequestURL(fileName);
|
||||||
_webFileRequestOp = new UnityWebFileRequestOperation(webURL, savePath, _timeout);
|
int watchdogTime = _fileSystem.DownloadWatchDogTime;
|
||||||
_webFileRequestOp.StartOperation();
|
var args = new DownloadFileRequestArgs(webURL, savePath, _timeout, watchdogTime);
|
||||||
AddChildOperation(_webFileRequestOp);
|
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||||
|
_webFileRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webFileRequestOp.UpdateOperation();
|
|
||||||
if (_webFileRequestOp.IsDone == false)
|
if (_webFileRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
|
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeed;
|
Status = EOperationStatus.Succeed;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace YooAsset
|
|||||||
private readonly DefaultCacheFileSystem _fileSystem;
|
private readonly DefaultCacheFileSystem _fileSystem;
|
||||||
private readonly bool _appendTimeTicks;
|
private readonly bool _appendTimeTicks;
|
||||||
private readonly int _timeout;
|
private readonly int _timeout;
|
||||||
private UnityWebTextRequestOperation _webTextRequestOp;
|
private IDownloadTextRequest _webTextRequestOp;
|
||||||
private int _requestCount = 0;
|
private int _requestCount = 0;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
@@ -45,17 +45,17 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
|
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
|
||||||
string url = GetWebRequestURL(fileName);
|
string url = GetWebRequestURL(fileName);
|
||||||
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
|
int watchDogTime = _fileSystem.DownloadWatchDogTime;
|
||||||
_webTextRequestOp.StartOperation();
|
var args = new DownloadDataRequestArgs(url, _timeout, watchDogTime);
|
||||||
AddChildOperation(_webTextRequestOp);
|
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||||
|
_webTextRequestOp.SendRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webTextRequestOp.UpdateOperation();
|
Progress = _webTextRequestOp.DownloadProgress;
|
||||||
Progress = _webTextRequestOp.Progress;
|
|
||||||
if (_webTextRequestOp.IsDone == false)
|
if (_webTextRequestOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
|
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||||
{
|
{
|
||||||
PackageVersion = _webTextRequestOp.Result;
|
PackageVersion = _webTextRequestOp.Result;
|
||||||
if (string.IsNullOrEmpty(PackageVersion))
|
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 System.IO;
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
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 VerifyTempFileOperation _verifyOperation;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
internal UnityDownloadLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url)
|
internal DownloadAndCacheLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string url) : base(url)
|
||||||
: base(fileSystem, bundle, url)
|
|
||||||
{
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_bundle = bundle;
|
||||||
|
_tempFilePath = _fileSystem.GetTempFilePath(_bundle);
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
if (_fileSystem.CopyLocalFileServices != null)
|
_steps = ESteps.CheckCopy;
|
||||||
_steps = ESteps.CopyLocalFile;
|
|
||||||
else
|
|
||||||
_steps = ESteps.CreateRequest;
|
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
{
|
{
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 创建下载器
|
// 检测文件拷贝
|
||||||
if (_steps == ESteps.CreateRequest)
|
if (_steps == ESteps.CheckCopy)
|
||||||
{
|
{
|
||||||
|
// 删除历史缓存文件
|
||||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||||
if (File.Exists(_tempFilePath))
|
if (File.Exists(_tempFilePath))
|
||||||
File.Delete(_tempFilePath);
|
File.Delete(_tempFilePath);
|
||||||
|
|
||||||
CreateWebRequest();
|
if (_fileSystem.CopyLocalFileServices != null)
|
||||||
_steps = ESteps.Download;
|
_steps = ESteps.CopyLocalFile;
|
||||||
}
|
|
||||||
|
|
||||||
// 检测下载结果
|
|
||||||
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
|
else
|
||||||
{
|
_steps = ESteps.CreateRequest;
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注意:最终释放请求器
|
|
||||||
DisposeRequest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拷贝内置文件
|
// 拷贝本地文件
|
||||||
if (_steps == ESteps.CopyLocalFile)
|
if (_steps == ESteps.CopyLocalFile)
|
||||||
{
|
{
|
||||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
|
||||||
if (File.Exists(_tempFilePath))
|
|
||||||
File.Delete(_tempFilePath);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//TODO 团结引擎,在某些机型(红米),拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。
|
//TODO 团结引擎,在某些机型(红米),拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。
|
||||||
var localFileInfo = new LocalFileInfo();
|
var localFileInfo = new LocalFileInfo();
|
||||||
localFileInfo.PackageName = _fileSystem.PackageName;
|
localFileInfo.PackageName = _fileSystem.PackageName;
|
||||||
localFileInfo.BundleName = _bundle.BundleName;
|
localFileInfo.BundleName = _bundle.BundleName;
|
||||||
localFileInfo.SourceFileURL = _requestURL;
|
localFileInfo.SourceFileURL = URL;
|
||||||
_fileSystem.CopyLocalFileServices.CopyFile(localFileInfo, _tempFilePath);
|
_fileSystem.CopyLocalFileServices.CopyFile(localFileInfo, _tempFilePath);
|
||||||
if (File.Exists(_tempFilePath))
|
if (File.Exists(_tempFilePath))
|
||||||
{
|
{
|
||||||
DownloadProgress = 1f;
|
DownloadProgress = 1f;
|
||||||
DownloadedBytes = _bundle.FileSize;
|
DownloadedBytes = _bundle.FileSize;
|
||||||
Progress = DownloadProgress;
|
_steps = ESteps.VerifyBundleFile;
|
||||||
_steps = ESteps.VerifyFile;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Failed copy local file : {_requestURL}";
|
Error = $"Failed copy local file : {URL}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
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)
|
if (_verifyOperation == null)
|
||||||
{
|
{
|
||||||
@@ -119,35 +140,51 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_verifyOperation.Status == EOperationStatus.Succeed)
|
if (_verifyOperation.Status == EOperationStatus.Succeed)
|
||||||
{
|
{
|
||||||
if (_fileSystem.WriteCacheBundleFile(_bundle, _tempFilePath))
|
_steps = ESteps.CacheBundleFile;
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"{_fileSystem.GetType().FullName} failed to write file !";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = _verifyOperation.Error;
|
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))
|
if (File.Exists(_tempFilePath))
|
||||||
File.Delete(_tempFilePath);
|
File.Delete(_tempFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal override void InternalAbort()
|
||||||
|
{
|
||||||
|
if (_request != null)
|
||||||
|
_request.AbortRequest();
|
||||||
|
}
|
||||||
internal override void InternalWaitForAsyncComplete()
|
internal override void InternalWaitForAsyncComplete()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
//TODO 等待导入或解压本地文件完毕,该操作会挂起主线程!
|
//TODO 等待导入或解压本地文件完毕,该操作会挂起主线程!
|
||||||
|
_fileSystem.DownloadBackend.Update();
|
||||||
InternalUpdate();
|
InternalUpdate();
|
||||||
if (IsDone)
|
if (IsDone)
|
||||||
break;
|
break;
|
||||||
@@ -156,15 +193,5 @@ namespace YooAsset
|
|||||||
System.Threading.Thread.Sleep(1);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user