mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-14 19:40:47 +00:00
Compare commits
57 Commits
2.1.2
...
2.2.3-prev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d34d1117a0 | ||
|
|
a5f3767cbc | ||
|
|
3bdb339f54 | ||
|
|
22cb3c3942 | ||
|
|
e5f5241879 | ||
|
|
79ac231df2 | ||
|
|
b7b375092f | ||
|
|
f86ea04521 | ||
|
|
738c02f58f | ||
|
|
d017688416 | ||
|
|
6b56275f87 | ||
|
|
b89f00130e | ||
|
|
4f58c54eff | ||
|
|
9001be21ac | ||
|
|
b421e7d2f8 | ||
|
|
0e7c14abde | ||
|
|
caf072ed9b | ||
|
|
51f2709956 | ||
|
|
0d5558f29f | ||
|
|
c6377ce544 | ||
|
|
07d34891ef | ||
|
|
ddce031ee5 | ||
|
|
6680a6450b | ||
|
|
dc119b26c7 | ||
|
|
2cbfca4f3b | ||
|
|
7d8fce6f46 | ||
|
|
13ad50aef5 | ||
|
|
30245b3668 | ||
|
|
589eea7cf3 | ||
|
|
24c5108ce1 | ||
|
|
21fbb01ce4 | ||
|
|
e664f20d34 | ||
|
|
b0ce14dc0e | ||
|
|
d2b38cbc1b | ||
|
|
a6d978090c | ||
|
|
f9d40987eb | ||
|
|
cab710493e | ||
|
|
9970cf704b | ||
|
|
260867b588 | ||
|
|
25231ecd32 | ||
|
|
b282515c39 | ||
|
|
bafd15571a | ||
|
|
481711fd75 | ||
|
|
d09b52301a | ||
|
|
0c77ef628f | ||
|
|
54f585c67a | ||
|
|
a9e5e7fdd3 | ||
|
|
b151f968d7 | ||
|
|
86ef93caa3 | ||
|
|
75511397d6 | ||
|
|
db8d09d0d6 | ||
|
|
02d70a476d | ||
|
|
9420f8561f | ||
|
|
d43eb821b9 | ||
|
|
b82ede8bde | ||
|
|
ff02da5c54 | ||
|
|
2987d356b6 |
@@ -2,6 +2,117 @@
|
|||||||
|
|
||||||
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.2.3-preview] - 2024-08-13
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- (#311) 修复了断点续传下载器极小概率报错 : “416 Range Not Satisfiable”
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- 原生文件构建管线支持原生文件加密。
|
||||||
|
|
||||||
|
- HostPlayMode模式下内置文件系统初始化参数可以为空。
|
||||||
|
|
||||||
|
- 场景加载增加了LocalPhysicsMode参数来控制物理运行模式。
|
||||||
|
|
||||||
|
- 默认的内置文件系统和缓存文件系统增加解密方法。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
/// <summary>
|
||||||
|
/// 创建默认的内置文件系统参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="decryptionServices">加密文件解密服务类</param>
|
||||||
|
/// <param name="verifyLevel">缓存文件的校验等级</param>
|
||||||
|
/// <param name="rootDirectory">内置文件的根路径</param>
|
||||||
|
public static FileSystemParameters CreateDefaultBuildinFileSystemParameters(IDecryptionServices decryptionServices, EFileVerifyLevel verifyLevel, string rootDirectory);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建默认的缓存文件系统参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="remoteServices">远端资源地址查询服务类</param>
|
||||||
|
/// <param name="decryptionServices">加密文件解密服务类</param>
|
||||||
|
/// <param name="verifyLevel">缓存文件的校验等级</param>
|
||||||
|
/// <param name="rootDirectory">文件系统的根目录</param>
|
||||||
|
public static FileSystemParameters CreateDefaultCacheFileSystemParameters(IRemoteServices remoteServices, IDecryptionServices decryptionServices, EFileVerifyLevel verifyLevel, string rootDirectory);
|
||||||
|
```
|
||||||
|
|
||||||
|
## [2.2.2-preview] - 2024-07-31
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- (#321) 修复了在Unity2022里编辑器下离线模式运行失败的问题。
|
||||||
|
- (#325) 修复了在Unity2019里编译报错问题。
|
||||||
|
|
||||||
|
## [2.2.1-preview] - 2024-07-10
|
||||||
|
|
||||||
|
统一了所有PlayMode的初始化逻辑,EditorSimulateMode和OfflinePlayMode初始化不再主动加载资源清单!
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- 新增了IFileSystem.ReadFileData方法,支持原生文件自定义获取文本和二进制数据。
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- 优化了DefaultWebFileSystem和DefaultBuildFileSystem文件系统的内部初始化逻辑。
|
||||||
|
|
||||||
|
## [2.2.0-preview] - 2024-07-07
|
||||||
|
|
||||||
|
重构了运行时代码,新增了文件系统接口(IFileSystem)方便开发者扩展特殊需求。
|
||||||
|
|
||||||
|
新增微信小游戏文件系统示例代码,详细见Extension Sample/Runtime/WechatFileSystem
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- 新增了ResourcePackage.DestroyAsync方法
|
||||||
|
|
||||||
|
- 新增了FileSystemParameters类帮助初始化文件系统
|
||||||
|
|
||||||
|
内置了编辑器文件系统参数,内置文件系统参数,缓存文件系统参数,Web文件系统参数。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class FileSystemParameters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件系统类
|
||||||
|
/// </summary>
|
||||||
|
public string FileSystemClass { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件系统的根目录
|
||||||
|
/// </summary>
|
||||||
|
public string RootDirectory { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加自定义参数
|
||||||
|
/// </summary>
|
||||||
|
public void AddParameter(string name, object value)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- 重构了InitializeParameters初始化参数
|
||||||
|
- 重命名YooAssets.DestroyPackage方法为RemovePackage
|
||||||
|
- 重命名ResourcePackage.UpdatePackageVersionAsync方法为RequestPackageVersionAsync
|
||||||
|
- 重命名ResourcePackage.UnloadUnusedAssets方法为UnloadUnusedAssetsAsync
|
||||||
|
- 重命名ResourcePackage.ForceUnloadAllAssets方法为UnloadAllAssetsAsync
|
||||||
|
- 重命名ResourcePackage.ClearUnusedCacheFilesAsync方法为ClearUnusedBundleFilesAsync
|
||||||
|
- 重命名ResourcePackage.ClearAllCacheFilesAsync方法为ClearAllBundleFilesAsync
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- 移除了YooAssets.Destroy方法
|
||||||
|
- 移除了YooAssets.SetDownloadSystemClearFileResponseCode方法
|
||||||
|
- 移除了YooAssets.SetCacheSystemDisableCacheOnWebGL方法
|
||||||
|
- 移除了ResourcePackage.GetPackageBuildinRootDirectory方法
|
||||||
|
- 移除了ResourcePackage.GetPackageSandboxRootDirectory方法
|
||||||
|
- 移除了ResourcePackage.ClearPackageSandbox方法
|
||||||
|
- 移除了IBuildinQueryServices接口
|
||||||
|
- 移除了IDeliveryLoadServices接口
|
||||||
|
- 移除了IDeliveryQueryServices接口
|
||||||
|
|
||||||
|
|
||||||
## [2.1.2] - 2024-05-16
|
## [2.1.2] - 2024-05-16
|
||||||
|
|
||||||
SBP库依赖版本升级至2.1.3
|
SBP库依赖版本升级至2.1.3
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ namespace YooAsset.Editor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模拟构建
|
/// 模拟构建
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string SimulateBuild(string buildPipelineName, string packageName)
|
public static SimulateBuildResult SimulateBuild(string buildPipelineName, string packageName)
|
||||||
{
|
{
|
||||||
|
string packageVersion = "Simulate";
|
||||||
|
BuildResult buildResult;
|
||||||
|
|
||||||
if (buildPipelineName == EBuildPipeline.BuiltinBuildPipeline.ToString())
|
if (buildPipelineName == EBuildPipeline.BuiltinBuildPipeline.ToString())
|
||||||
{
|
{
|
||||||
BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
|
BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
|
||||||
@@ -19,23 +22,13 @@ namespace YooAsset.Editor
|
|||||||
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||||
buildParameters.BuildMode = EBuildMode.SimulateBuild;
|
buildParameters.BuildMode = EBuildMode.SimulateBuild;
|
||||||
buildParameters.PackageName = packageName;
|
buildParameters.PackageName = packageName;
|
||||||
buildParameters.PackageVersion = "Simulate";
|
buildParameters.PackageVersion = packageVersion;
|
||||||
buildParameters.FileNameStyle = EFileNameStyle.HashName;
|
buildParameters.FileNameStyle = EFileNameStyle.HashName;
|
||||||
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
|
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
|
||||||
buildParameters.BuildinFileCopyParams = string.Empty;
|
buildParameters.BuildinFileCopyParams = string.Empty;
|
||||||
|
|
||||||
BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
|
BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
|
||||||
var buildResult = pipeline.Run(buildParameters, false);
|
buildResult = pipeline.Run(buildParameters, false);
|
||||||
if (buildResult.Success)
|
|
||||||
{
|
|
||||||
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
|
||||||
string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
|
|
||||||
return manifestFilePath;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (buildPipelineName == EBuildPipeline.ScriptableBuildPipeline.ToString())
|
else if (buildPipelineName == EBuildPipeline.ScriptableBuildPipeline.ToString())
|
||||||
{
|
{
|
||||||
@@ -46,23 +39,13 @@ namespace YooAsset.Editor
|
|||||||
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||||
buildParameters.BuildMode = EBuildMode.SimulateBuild;
|
buildParameters.BuildMode = EBuildMode.SimulateBuild;
|
||||||
buildParameters.PackageName = packageName;
|
buildParameters.PackageName = packageName;
|
||||||
buildParameters.PackageVersion = "Simulate";
|
buildParameters.PackageVersion = packageVersion;
|
||||||
buildParameters.FileNameStyle = EFileNameStyle.HashName;
|
buildParameters.FileNameStyle = EFileNameStyle.HashName;
|
||||||
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
|
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
|
||||||
buildParameters.BuildinFileCopyParams = string.Empty;
|
buildParameters.BuildinFileCopyParams = string.Empty;
|
||||||
|
|
||||||
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
|
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
|
||||||
var buildResult = pipeline.Run(buildParameters, true);
|
buildResult = pipeline.Run(buildParameters, true);
|
||||||
if (buildResult.Success)
|
|
||||||
{
|
|
||||||
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
|
||||||
string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
|
|
||||||
return manifestFilePath;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (buildPipelineName == EBuildPipeline.RawFileBuildPipeline.ToString())
|
else if (buildPipelineName == EBuildPipeline.RawFileBuildPipeline.ToString())
|
||||||
{
|
{
|
||||||
@@ -73,28 +56,30 @@ namespace YooAsset.Editor
|
|||||||
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||||
buildParameters.BuildMode = EBuildMode.SimulateBuild;
|
buildParameters.BuildMode = EBuildMode.SimulateBuild;
|
||||||
buildParameters.PackageName = packageName;
|
buildParameters.PackageName = packageName;
|
||||||
buildParameters.PackageVersion = "Simulate";
|
buildParameters.PackageVersion = packageVersion;
|
||||||
buildParameters.FileNameStyle = EFileNameStyle.HashName;
|
buildParameters.FileNameStyle = EFileNameStyle.HashName;
|
||||||
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
|
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
|
||||||
buildParameters.BuildinFileCopyParams = string.Empty;
|
buildParameters.BuildinFileCopyParams = string.Empty;
|
||||||
|
|
||||||
RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
|
RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
|
||||||
var buildResult = pipeline.Run(buildParameters, true);
|
buildResult = pipeline.Run(buildParameters, true);
|
||||||
if (buildResult.Success)
|
|
||||||
{
|
|
||||||
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
|
||||||
string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
|
|
||||||
return manifestFilePath;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException(buildPipelineName);
|
throw new System.NotImplementedException(buildPipelineName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 返回结果
|
||||||
|
if (buildResult.Success)
|
||||||
|
{
|
||||||
|
SimulateBuildResult reulst = new SimulateBuildResult();
|
||||||
|
reulst.PackageRootDirectory = buildResult.OutputPackageDirectory;
|
||||||
|
return reulst;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,9 +180,9 @@ namespace YooAsset.Editor
|
|||||||
for (int index = 0; index < manifest.BundleList.Count; index++)
|
for (int index = 0; index < manifest.BundleList.Count; index++)
|
||||||
{
|
{
|
||||||
var packageBundle = manifest.BundleList[index];
|
var packageBundle = manifest.BundleList[index];
|
||||||
if (_cacheBundleTags.ContainsKey(index))
|
if (_cacheBundleTags.TryGetValue(index, out var value))
|
||||||
{
|
{
|
||||||
packageBundle.Tags = _cacheBundleTags[index].ToArray();
|
packageBundle.Tags = value.ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
EncryptFileInfo fileInfo = new EncryptFileInfo();
|
EncryptFileInfo fileInfo = new EncryptFileInfo();
|
||||||
fileInfo.BundleName = bundleInfo.BundleName;
|
fileInfo.BundleName = bundleInfo.BundleName;
|
||||||
fileInfo.FilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
fileInfo.FileLoadPath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||||
var encryptResult = encryptionServices.Encrypt(fileInfo);
|
var encryptResult = encryptionServices.Encrypt(fileInfo);
|
||||||
if (encryptResult.Encrypted)
|
if (encryptResult.Encrypted)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ namespace YooAsset.Editor
|
|||||||
string bundleName = collectAssetInfo.BundleName;
|
string bundleName = collectAssetInfo.BundleName;
|
||||||
foreach (var dependAsset in collectAssetInfo.DependAssets)
|
foreach (var dependAsset in collectAssetInfo.DependAssets)
|
||||||
{
|
{
|
||||||
if (allBuildAssetInfos.ContainsKey(dependAsset.AssetPath))
|
if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out var value))
|
||||||
{
|
{
|
||||||
allBuildAssetInfos[dependAsset.AssetPath].AddReferenceBundleName(bundleName);
|
value.AddReferenceBundleName(bundleName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace YooAsset.Editor
|
namespace YooAsset.Editor
|
||||||
{
|
{
|
||||||
public class TaskEncryption_BBP : TaskEncryption, IBuildTask
|
public class TaskEncryption_BBP : TaskEncryption, IBuildTask
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
||||||
{
|
{
|
||||||
return new string[] { };
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
namespace YooAsset.Editor
|
||||||
|
{
|
||||||
|
public class TaskEncryption_RFBP : TaskEncryption, IBuildTask
|
||||||
|
{
|
||||||
|
void IBuildTask.Run(BuildContext context)
|
||||||
|
{
|
||||||
|
var buildParameters = context.GetContextObject<BuildParametersContext>();
|
||||||
|
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||||
|
|
||||||
|
var buildMode = buildParameters.Parameters.BuildMode;
|
||||||
|
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||||
|
{
|
||||||
|
EncryptingBundleFiles(buildParameters, buildMapContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 02ad351eb8539da47a0c789e2f8c468f
|
guid: b3e156139dcc25f4c9440ec3d6cb96d2
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -32,6 +32,7 @@ namespace YooAsset.Editor
|
|||||||
new TaskPrepare_RFBP(),
|
new TaskPrepare_RFBP(),
|
||||||
new TaskGetBuildMap_RFBP(),
|
new TaskGetBuildMap_RFBP(),
|
||||||
new TaskBuilding_RFBP(),
|
new TaskBuilding_RFBP(),
|
||||||
|
new TaskEncryption_RFBP(),
|
||||||
new TaskUpdateBundleInfo_RFBP(),
|
new TaskUpdateBundleInfo_RFBP(),
|
||||||
new TaskCreateManifest_RFBP(),
|
new TaskCreateManifest_RFBP(),
|
||||||
new TaskCreateReport_RFBP(),
|
new TaskCreateReport_RFBP(),
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace YooAsset.Editor
|
namespace YooAsset.Editor
|
||||||
{
|
{
|
||||||
public class TaskEncryption_SBP : TaskEncryption, IBuildTask
|
public class TaskEncryption_SBP : TaskEncryption, IBuildTask
|
||||||
|
|||||||
@@ -28,7 +28,13 @@ namespace UnityEditor.Build.Pipeline.Tasks
|
|||||||
#endif
|
#endif
|
||||||
buildTasks.Add(new CalculateAssetDependencyData());
|
buildTasks.Add(new CalculateAssetDependencyData());
|
||||||
buildTasks.Add(new StripUnusedSpriteSources());
|
buildTasks.Add(new StripUnusedSpriteSources());
|
||||||
|
|
||||||
|
#if TUANJIE_1_0_OR_NEWER
|
||||||
|
buildTasks.Add(new CreateBuiltInShadersBundle(builtInShaderBundleName));
|
||||||
|
#else
|
||||||
buildTasks.Add(new CreateBuiltInBundle(builtInShaderBundleName));
|
buildTasks.Add(new CreateBuiltInBundle(builtInShaderBundleName));
|
||||||
|
#endif
|
||||||
|
|
||||||
buildTasks.Add(new PostDependencyCallback());
|
buildTasks.Add(new PostDependencyCallback());
|
||||||
|
|
||||||
// Packing
|
// Packing
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
public interface IBuildPipeline
|
public interface IBuildPipeline
|
||||||
{
|
{
|
||||||
public BuildResult Run(BuildParameters buildParameters, bool enableLog);
|
BuildResult Run(BuildParameters buildParameters, bool enableLog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
private static readonly Dictionary<string, System.Type> _cacheIgnoreRuleTypes = new Dictionary<string, System.Type>();
|
private static readonly Dictionary<string, System.Type> _cacheIgnoreRuleTypes = new Dictionary<string, System.Type>();
|
||||||
private static readonly Dictionary<string, IIgnoreRule> _cacheIgnoreRuleInstance = new Dictionary<string, IIgnoreRule>();
|
private static readonly Dictionary<string, IIgnoreRule> _cacheIgnoreRuleInstance = new Dictionary<string, IIgnoreRule>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置数据是否被修改
|
/// 配置数据是否被修改
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -275,23 +275,23 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
public static bool HasActiveRuleName(string ruleName)
|
public static bool HasActiveRuleName(string ruleName)
|
||||||
{
|
{
|
||||||
return _cacheActiveRuleTypes.Keys.Contains(ruleName);
|
return _cacheActiveRuleTypes.ContainsKey(ruleName);
|
||||||
}
|
}
|
||||||
public static bool HasAddressRuleName(string ruleName)
|
public static bool HasAddressRuleName(string ruleName)
|
||||||
{
|
{
|
||||||
return _cacheAddressRuleTypes.Keys.Contains(ruleName);
|
return _cacheAddressRuleTypes.ContainsKey(ruleName);
|
||||||
}
|
}
|
||||||
public static bool HasPackRuleName(string ruleName)
|
public static bool HasPackRuleName(string ruleName)
|
||||||
{
|
{
|
||||||
return _cachePackRuleTypes.Keys.Contains(ruleName);
|
return _cachePackRuleTypes.ContainsKey(ruleName);
|
||||||
}
|
}
|
||||||
public static bool HasFilterRuleName(string ruleName)
|
public static bool HasFilterRuleName(string ruleName)
|
||||||
{
|
{
|
||||||
return _cacheFilterRuleTypes.Keys.Contains(ruleName);
|
return _cacheFilterRuleTypes.ContainsKey(ruleName);
|
||||||
}
|
}
|
||||||
public static bool HasIgnoreRuleName(string ruleName)
|
public static bool HasIgnoreRuleName(string ruleName)
|
||||||
{
|
{
|
||||||
return _cacheIgnoreRuleTypes.Keys.Contains(ruleName);
|
return _cacheIgnoreRuleTypes.ContainsKey(ruleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IActiveRule GetActiveRuleInstance(string ruleName)
|
public static IActiveRule GetActiveRuleInstance(string ruleName)
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
public bool IsCollectAsset(FilterRuleData data)
|
public bool IsCollectAsset(FilterRuleData data)
|
||||||
{
|
{
|
||||||
return Path.GetExtension(data.AssetPath) == ".unity";
|
string extension = Path.GetExtension(data.AssetPath);
|
||||||
|
return extension == ".unity" || extension == ".scene";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ namespace YooAsset.Editor
|
|||||||
|
|
||||||
// Status
|
// Status
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
if (bundleInfo.Status == BundleLoaderBase.EStatus.Failed.ToString())
|
if (bundleInfo.Status == EOperationStatus.Failed)
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = label1.style.color;
|
textColor = label1.style.color;
|
||||||
|
|||||||
@@ -559,6 +559,21 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
return path.Replace('\\', '/').Replace("\\", "/"); //替换为Linux路径格式
|
return path.Replace('\\', '/').Replace("\\", "/"); //替换为Linux路径格式
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除路径里的后缀名
|
||||||
|
/// </summary>
|
||||||
|
public static string RemoveExtension(string str)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(str))
|
||||||
|
return str;
|
||||||
|
|
||||||
|
int index = str.LastIndexOf('.');
|
||||||
|
if (index == -1)
|
||||||
|
return str;
|
||||||
|
else
|
||||||
|
return str.Remove(index); //"assets/config/test.unity3d" --> "assets/config/test"
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取项目工程路径
|
/// 获取项目工程路径
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
public class CacheFileInfo
|
|
||||||
{
|
|
||||||
public string RemoteFileName { private set; get; }
|
|
||||||
public string FilePath { private set; get; }
|
|
||||||
public string FileCRC { private set; get; }
|
|
||||||
public long FileSize { private set; get; }
|
|
||||||
|
|
||||||
public CacheFileInfo(string remoteFileName, string filePath, string fileCRC, long fileSize)
|
|
||||||
{
|
|
||||||
RemoteFileName = remoteFileName;
|
|
||||||
FilePath = filePath;
|
|
||||||
FileCRC = fileCRC;
|
|
||||||
FileSize = fileSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal static class CacheHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 禁用Unity缓存系统在WebGL平台
|
|
||||||
/// </summary>
|
|
||||||
public static bool DisableUnityCacheOnWebGL = false;
|
|
||||||
|
|
||||||
#region 资源信息文件相关
|
|
||||||
private static readonly BufferWriter SharedBuffer = new BufferWriter(1024);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入资源包信息
|
|
||||||
/// </summary>
|
|
||||||
public static void WriteInfoToFile(string filePath, string dataFileCRC, long dataFileSize)
|
|
||||||
{
|
|
||||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
|
||||||
{
|
|
||||||
SharedBuffer.Clear();
|
|
||||||
SharedBuffer.WriteUTF8(dataFileCRC);
|
|
||||||
SharedBuffer.WriteInt64(dataFileSize);
|
|
||||||
SharedBuffer.WriteToStream(fs);
|
|
||||||
fs.Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取资源包信息
|
|
||||||
/// </summary>
|
|
||||||
public static void ReadInfoFromFile(string filePath, out string dataFileCRC, out long dataFileSize)
|
|
||||||
{
|
|
||||||
byte[] binaryData = FileUtility.ReadAllBytes(filePath);
|
|
||||||
BufferReader buffer = new BufferReader(binaryData);
|
|
||||||
dataFileCRC = buffer.ReadUTF8();
|
|
||||||
dataFileSize = buffer.ReadInt64();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 资源文件验证相关
|
|
||||||
/// <summary>
|
|
||||||
/// 验证缓存文件(子线程内操作)
|
|
||||||
/// </summary>
|
|
||||||
public static EVerifyResult VerifyingCacheFile(VerifyCacheFileElement element, EVerifyLevel verifyLevel)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (verifyLevel == EVerifyLevel.Low)
|
|
||||||
{
|
|
||||||
if (File.Exists(element.InfoFilePath) == false)
|
|
||||||
return EVerifyResult.InfoFileNotExisted;
|
|
||||||
if (File.Exists(element.DataFilePath) == false)
|
|
||||||
return EVerifyResult.DataFileNotExisted;
|
|
||||||
return EVerifyResult.Succeed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (File.Exists(element.InfoFilePath) == false)
|
|
||||||
return EVerifyResult.InfoFileNotExisted;
|
|
||||||
|
|
||||||
// 解析信息文件获取验证数据
|
|
||||||
CacheHelper.ReadInfoFromFile(element.InfoFilePath, out element.DataFileCRC, out element.DataFileSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return EVerifyResult.Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
return VerifyingInternal(element.DataFilePath, element.DataFileSize, element.DataFileCRC, verifyLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 验证下载文件(子线程内操作)
|
|
||||||
/// </summary>
|
|
||||||
public static EVerifyResult VerifyingTempFile(VerifyTempFileElement element)
|
|
||||||
{
|
|
||||||
return VerifyingInternal(element.TempDataFilePath, element.FileSize, element.FileCRC, EVerifyLevel.High);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 验证记录文件(主线程内操作)
|
|
||||||
/// </summary>
|
|
||||||
public static EVerifyResult VerifyingRecordFile(CacheManager cache, string cacheGUID)
|
|
||||||
{
|
|
||||||
var wrapper = cache.TryGetWrapper(cacheGUID);
|
|
||||||
if (wrapper == null)
|
|
||||||
return EVerifyResult.CacheNotFound;
|
|
||||||
|
|
||||||
EVerifyResult result = VerifyingInternal(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EVerifyLevel.High);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EVerifyResult VerifyingInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (File.Exists(filePath) == false)
|
|
||||||
return EVerifyResult.DataFileNotExisted;
|
|
||||||
|
|
||||||
// 先验证文件大小
|
|
||||||
long size = FileUtility.GetFileSize(filePath);
|
|
||||||
if (size < fileSize)
|
|
||||||
return EVerifyResult.FileNotComplete;
|
|
||||||
else if (size > fileSize)
|
|
||||||
return EVerifyResult.FileOverflow;
|
|
||||||
|
|
||||||
// 再验证文件CRC
|
|
||||||
if (verifyLevel == EVerifyLevel.High)
|
|
||||||
{
|
|
||||||
string crc = HashUtility.FileCRC32Safely(filePath);
|
|
||||||
if (crc == fileCRC)
|
|
||||||
return EVerifyResult.Succeed;
|
|
||||||
else
|
|
||||||
return EVerifyResult.FileCrcError;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return EVerifyResult.Succeed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return EVerifyResult.Exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class CacheManager
|
|
||||||
{
|
|
||||||
internal class RecordWrapper
|
|
||||||
{
|
|
||||||
public string InfoFilePath { private set; get; }
|
|
||||||
public string DataFilePath { private set; get; }
|
|
||||||
public string DataFileCRC { private set; get; }
|
|
||||||
public long DataFileSize { private set; get; }
|
|
||||||
|
|
||||||
public RecordWrapper(string infoFilePath, string dataFilePath, string dataFileCRC, long dataFileSize)
|
|
||||||
{
|
|
||||||
InfoFilePath = infoFilePath;
|
|
||||||
DataFilePath = dataFilePath;
|
|
||||||
DataFileCRC = dataFileCRC;
|
|
||||||
DataFileSize = dataFileSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly Dictionary<string, RecordWrapper> _wrappers = new Dictionary<string, RecordWrapper>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所属包裹
|
|
||||||
/// </summary>
|
|
||||||
public readonly string PackageName;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 验证级别
|
|
||||||
/// </summary>
|
|
||||||
public readonly EVerifyLevel BootVerifyLevel;
|
|
||||||
|
|
||||||
|
|
||||||
public CacheManager(string packageName, EVerifyLevel bootVerifyLevel)
|
|
||||||
{
|
|
||||||
PackageName = packageName;
|
|
||||||
BootVerifyLevel = bootVerifyLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 清空所有数据
|
|
||||||
/// </summary>
|
|
||||||
public void ClearAll()
|
|
||||||
{
|
|
||||||
_wrappers.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查询缓存记录
|
|
||||||
/// </summary>
|
|
||||||
public bool IsCached(string cacheGUID)
|
|
||||||
{
|
|
||||||
return _wrappers.ContainsKey(cacheGUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 记录验证结果
|
|
||||||
/// </summary>
|
|
||||||
public void Record(string cacheGUID, RecordWrapper wrapper)
|
|
||||||
{
|
|
||||||
if (_wrappers.ContainsKey(cacheGUID) == false)
|
|
||||||
{
|
|
||||||
_wrappers.Add(cacheGUID, wrapper);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Should never get here !");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 丢弃验证结果并删除缓存文件
|
|
||||||
/// </summary>
|
|
||||||
public void Discard(string cacheGUID)
|
|
||||||
{
|
|
||||||
var wrapper = TryGetWrapper(cacheGUID);
|
|
||||||
if (wrapper != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string dataFilePath = wrapper.DataFilePath;
|
|
||||||
FileInfo fileInfo = new FileInfo(dataFilePath);
|
|
||||||
if (fileInfo.Exists)
|
|
||||||
fileInfo.Directory.Delete(true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_wrappers.ContainsKey(cacheGUID))
|
|
||||||
{
|
|
||||||
_wrappers.Remove(cacheGUID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取记录对象
|
|
||||||
/// </summary>
|
|
||||||
public RecordWrapper TryGetWrapper(string cacheGUID)
|
|
||||||
{
|
|
||||||
if (_wrappers.TryGetValue(cacheGUID, out RecordWrapper value))
|
|
||||||
return value;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取缓存文件总数
|
|
||||||
/// </summary>
|
|
||||||
public int GetAllCachedFilesCount()
|
|
||||||
{
|
|
||||||
return _wrappers.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取缓存GUID集合
|
|
||||||
/// </summary>
|
|
||||||
public List<string> GetAllCachedGUIDs()
|
|
||||||
{
|
|
||||||
List<string> keys = new List<string>(_wrappers.Keys.Count);
|
|
||||||
var keyCollection = _wrappers.Keys;
|
|
||||||
foreach (var key in keyCollection)
|
|
||||||
{
|
|
||||||
keys.Add(key);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 65584a0568d40b14582a3c4aaf947b98
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4eb0b0eafee709d478ab6d81faacb304
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 清理本地包裹未使用的缓存文件
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ClearUnusedCacheFilesOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
GetUnusedCacheFiles,
|
|
||||||
ClearUnusedCacheFiles,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly ResourcePackage _package;
|
|
||||||
private readonly CacheManager _cache;
|
|
||||||
private List<string> _unusedCacheGUIDs;
|
|
||||||
private int _unusedFileTotalCount = 0;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
internal ClearUnusedCacheFilesOperation(ResourcePackage package, CacheManager cache)
|
|
||||||
{
|
|
||||||
_package = package;
|
|
||||||
_cache = cache;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.GetUnusedCacheFiles;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.GetUnusedCacheFiles)
|
|
||||||
{
|
|
||||||
_unusedCacheGUIDs = GetUnusedCacheGUIDs();
|
|
||||||
_unusedFileTotalCount = _unusedCacheGUIDs.Count;
|
|
||||||
YooLogger.Log($"Found unused cache file count : {_unusedFileTotalCount}");
|
|
||||||
_steps = ESteps.ClearUnusedCacheFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.ClearUnusedCacheFiles)
|
|
||||||
{
|
|
||||||
for (int i = _unusedCacheGUIDs.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
string cacheGUID = _unusedCacheGUIDs[i];
|
|
||||||
_cache.Discard(cacheGUID);
|
|
||||||
_unusedCacheGUIDs.RemoveAt(i);
|
|
||||||
|
|
||||||
if (OperationSystem.IsBusy)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_unusedFileTotalCount == 0)
|
|
||||||
Progress = 1.0f;
|
|
||||||
else
|
|
||||||
Progress = 1.0f - (_unusedCacheGUIDs.Count / _unusedFileTotalCount);
|
|
||||||
|
|
||||||
if (_unusedCacheGUIDs.Count == 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetUnusedCacheGUIDs()
|
|
||||||
{
|
|
||||||
var allCacheGUIDs = _cache.GetAllCachedGUIDs();
|
|
||||||
List<string> result = new List<string>(allCacheGUIDs.Count);
|
|
||||||
foreach (var cacheGUID in allCacheGUIDs)
|
|
||||||
{
|
|
||||||
if (_package.IsIncludeBundleFile(cacheGUID) == false)
|
|
||||||
{
|
|
||||||
result.Add(cacheGUID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5d188c50fd00bf941b2eeebb374dc0d1
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
public class GetAllCacheFileInfosOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
TryLoadCacheManifest,
|
|
||||||
GetCacheFileInfos,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly PersistentManager _persistent;
|
|
||||||
private readonly CacheManager _cache;
|
|
||||||
private readonly string _packageVersion;
|
|
||||||
private LoadCacheManifestOperation _tryLoadCacheManifestOp;
|
|
||||||
private PackageManifest _manifest;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
private List<CacheFileInfo> _cacheFileInfos;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 搜索结果
|
|
||||||
/// </summary>
|
|
||||||
public List<CacheFileInfo> Result
|
|
||||||
{
|
|
||||||
get { return _cacheFileInfos; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal GetAllCacheFileInfosOperation(PersistentManager persistent, CacheManager cache, string packageVersion)
|
|
||||||
{
|
|
||||||
_persistent = persistent;
|
|
||||||
_cache = cache;
|
|
||||||
_packageVersion = packageVersion;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.TryLoadCacheManifest;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.TryLoadCacheManifest)
|
|
||||||
{
|
|
||||||
if (_tryLoadCacheManifestOp == null)
|
|
||||||
{
|
|
||||||
_tryLoadCacheManifestOp = new LoadCacheManifestOperation(_persistent, _packageVersion);
|
|
||||||
OperationSystem.StartOperation(_cache.PackageName, _tryLoadCacheManifestOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_tryLoadCacheManifestOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_tryLoadCacheManifestOp.Status == EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
_manifest = _tryLoadCacheManifestOp.Manifest;
|
|
||||||
_steps = ESteps.GetCacheFileInfos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = _tryLoadCacheManifestOp.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.GetCacheFileInfos)
|
|
||||||
{
|
|
||||||
var allCachedGUIDs = _cache.GetAllCachedGUIDs();
|
|
||||||
_cacheFileInfos = new List<CacheFileInfo>(allCachedGUIDs.Count);
|
|
||||||
for (int i = 0; i < allCachedGUIDs.Count; i++)
|
|
||||||
{
|
|
||||||
var cachedGUID = allCachedGUIDs[i];
|
|
||||||
var wrapper = _cache.TryGetWrapper(cachedGUID);
|
|
||||||
if (wrapper != null)
|
|
||||||
{
|
|
||||||
if (_manifest.TryGetPackageBundleByCacheGUID(cachedGUID, out var packageBundle))
|
|
||||||
{
|
|
||||||
var cacheFileInfo = new CacheFileInfo(packageBundle.FileName, wrapper.DataFilePath, wrapper.DataFileCRC, wrapper.DataFileSize);
|
|
||||||
_cacheFileInfos.Add(cacheFileInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注意:总是返回成功
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d37e37f5d78ddf8468adcf2dff1edfbb
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 00ec004354d75ac499606d6959192f9b
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal abstract class VerifyCacheFilesOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
public static VerifyCacheFilesOperation CreateOperation(CacheManager cache, List<VerifyCacheFileElement> elements)
|
|
||||||
{
|
|
||||||
#if UNITY_WEBGL
|
|
||||||
var operation = new VerifyCacheFilesWithoutThreadOperation(cache, elements);
|
|
||||||
#else
|
|
||||||
var operation = new VerifyCacheFilesWithThreadOperation(cache, elements);
|
|
||||||
#endif
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 本地缓存文件验证(线程版)
|
|
||||||
/// </summary>
|
|
||||||
internal class VerifyCacheFilesWithThreadOperation : VerifyCacheFilesOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
InitVerify,
|
|
||||||
UpdateVerify,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
|
|
||||||
private readonly CacheManager _cache;
|
|
||||||
private List<VerifyCacheFileElement> _waitingList;
|
|
||||||
private List<VerifyCacheFileElement> _verifyingList;
|
|
||||||
private int _verifyMaxNum;
|
|
||||||
private int _verifyTotalCount;
|
|
||||||
private float _verifyStartTime;
|
|
||||||
private int _succeedCount;
|
|
||||||
private int _failedCount;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public VerifyCacheFilesWithThreadOperation(CacheManager cache, List<VerifyCacheFileElement> elements)
|
|
||||||
{
|
|
||||||
_cache = cache;
|
|
||||||
_waitingList = elements;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.InitVerify;
|
|
||||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.InitVerify)
|
|
||||||
{
|
|
||||||
int fileCount = _waitingList.Count;
|
|
||||||
|
|
||||||
// 设置同时验证的最大数
|
|
||||||
ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
|
|
||||||
YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
|
|
||||||
_verifyMaxNum = Math.Min(workerThreads, ioThreads);
|
|
||||||
_verifyTotalCount = fileCount;
|
|
||||||
if (_verifyMaxNum < 1)
|
|
||||||
_verifyMaxNum = 1;
|
|
||||||
|
|
||||||
_verifyingList = new List<VerifyCacheFileElement>(_verifyMaxNum);
|
|
||||||
_steps = ESteps.UpdateVerify;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.UpdateVerify)
|
|
||||||
{
|
|
||||||
_syncContext.Update();
|
|
||||||
|
|
||||||
Progress = GetProgress();
|
|
||||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
|
||||||
YooLogger.Log($"Verify cache files elapsed time {costTime:f1} seconds");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (OperationSystem.IsBusy)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (_verifyingList.Count >= _verifyMaxNum)
|
|
||||||
break;
|
|
||||||
|
|
||||||
var element = _waitingList[i];
|
|
||||||
if (BeginVerifyFileWithThread(element))
|
|
||||||
{
|
|
||||||
_waitingList.RemoveAt(i);
|
|
||||||
_verifyingList.Add(element);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
YooLogger.Warning("The thread pool is failed queued.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetProgress()
|
|
||||||
{
|
|
||||||
if (_verifyTotalCount == 0)
|
|
||||||
return 1f;
|
|
||||||
return (float)(_succeedCount + _failedCount) / _verifyTotalCount;
|
|
||||||
}
|
|
||||||
private bool BeginVerifyFileWithThread(VerifyCacheFileElement element)
|
|
||||||
{
|
|
||||||
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), element);
|
|
||||||
}
|
|
||||||
private void VerifyInThread(object obj)
|
|
||||||
{
|
|
||||||
VerifyCacheFileElement element = (VerifyCacheFileElement)obj;
|
|
||||||
element.Result = CacheHelper.VerifyingCacheFile(element, _cache.BootVerifyLevel);
|
|
||||||
_syncContext.Post(VerifyCallback, element);
|
|
||||||
}
|
|
||||||
private void VerifyCallback(object obj)
|
|
||||||
{
|
|
||||||
VerifyCacheFileElement element = (VerifyCacheFileElement)obj;
|
|
||||||
_verifyingList.Remove(element);
|
|
||||||
|
|
||||||
if (element.Result == EVerifyResult.Succeed)
|
|
||||||
{
|
|
||||||
_succeedCount++;
|
|
||||||
var wrapper = new CacheManager.RecordWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
|
||||||
_cache.Record(element.CacheGUID, wrapper);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_failedCount++;
|
|
||||||
|
|
||||||
YooLogger.Warning($"Failed verify file and delete files : {element.FileRootPath}");
|
|
||||||
element.DeleteFiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 本地缓存文件验证(非线程版)
|
|
||||||
/// </summary>
|
|
||||||
internal class VerifyCacheFilesWithoutThreadOperation : VerifyCacheFilesOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
InitVerify,
|
|
||||||
UpdateVerify,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly CacheManager _cache;
|
|
||||||
private List<VerifyCacheFileElement> _waitingList;
|
|
||||||
private List<VerifyCacheFileElement> _verifyingList;
|
|
||||||
private int _verifyMaxNum;
|
|
||||||
private int _verifyTotalCount;
|
|
||||||
private float _verifyStartTime;
|
|
||||||
private int _succeedCount;
|
|
||||||
private int _failedCount;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public VerifyCacheFilesWithoutThreadOperation(CacheManager cache, List<VerifyCacheFileElement> elements)
|
|
||||||
{
|
|
||||||
_cache = cache;
|
|
||||||
_waitingList = elements;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.InitVerify;
|
|
||||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.InitVerify)
|
|
||||||
{
|
|
||||||
int fileCount = _waitingList.Count;
|
|
||||||
|
|
||||||
// 设置同时验证的最大数
|
|
||||||
_verifyMaxNum = fileCount;
|
|
||||||
_verifyTotalCount = fileCount;
|
|
||||||
|
|
||||||
_verifyingList = new List<VerifyCacheFileElement>(_verifyMaxNum);
|
|
||||||
_steps = ESteps.UpdateVerify;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.UpdateVerify)
|
|
||||||
{
|
|
||||||
Progress = GetProgress();
|
|
||||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
|
||||||
YooLogger.Log($"Package verify elapsed time {costTime:f1} seconds");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (OperationSystem.IsBusy)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (_verifyingList.Count >= _verifyMaxNum)
|
|
||||||
break;
|
|
||||||
|
|
||||||
var element = _waitingList[i];
|
|
||||||
BeginVerifyFileWithoutThread(element);
|
|
||||||
_waitingList.RemoveAt(i);
|
|
||||||
_verifyingList.Add(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主线程内验证,可以清空列表
|
|
||||||
_verifyingList.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetProgress()
|
|
||||||
{
|
|
||||||
if (_verifyTotalCount == 0)
|
|
||||||
return 1f;
|
|
||||||
return (float)(_succeedCount + _failedCount) / _verifyTotalCount;
|
|
||||||
}
|
|
||||||
private void BeginVerifyFileWithoutThread(VerifyCacheFileElement element)
|
|
||||||
{
|
|
||||||
element.Result = CacheHelper.VerifyingCacheFile(element, _cache.BootVerifyLevel);
|
|
||||||
if (element.Result == EVerifyResult.Succeed)
|
|
||||||
{
|
|
||||||
_succeedCount++;
|
|
||||||
var wrapper = new CacheManager.RecordWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
|
||||||
_cache.Record(element.CacheGUID, wrapper);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_failedCount++;
|
|
||||||
|
|
||||||
YooLogger.Warning($"Failed verify file and delete files : {element.FileRootPath}");
|
|
||||||
element.DeleteFiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal abstract class VerifyTempFileOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
public EVerifyResult VerifyResult { protected set; get; }
|
|
||||||
|
|
||||||
public static VerifyTempFileOperation CreateOperation(VerifyTempFileElement element)
|
|
||||||
{
|
|
||||||
#if UNITY_WEBGL
|
|
||||||
var operation = new VerifyTempFileWithoutThreadOperation(element);
|
|
||||||
#else
|
|
||||||
var operation = new VerifyTempFileWithThreadOperation(element);
|
|
||||||
#endif
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载文件验证(线程版)
|
|
||||||
/// </summary>
|
|
||||||
internal class VerifyTempFileWithThreadOperation : VerifyTempFileOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
VerifyFile,
|
|
||||||
Waiting,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly VerifyTempFileElement _element;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public VerifyTempFileWithThreadOperation(VerifyTempFileElement element)
|
|
||||||
{
|
|
||||||
_element = element;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.VerifyFile;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.VerifyFile)
|
|
||||||
{
|
|
||||||
if (BeginVerifyFileWithThread(_element))
|
|
||||||
{
|
|
||||||
_steps = ESteps.Waiting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.Waiting)
|
|
||||||
{
|
|
||||||
int result = _element.Result;
|
|
||||||
if (result == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
VerifyResult = (EVerifyResult)result;
|
|
||||||
if (VerifyResult == EVerifyResult.Succeed)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Failed verify file : {_element.TempDataFilePath} ! ErrorCode : {VerifyResult}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool BeginVerifyFileWithThread(VerifyTempFileElement element)
|
|
||||||
{
|
|
||||||
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), element);
|
|
||||||
}
|
|
||||||
private void VerifyInThread(object obj)
|
|
||||||
{
|
|
||||||
VerifyTempFileElement element = (VerifyTempFileElement)obj;
|
|
||||||
int result = (int)CacheHelper.VerifyingTempFile(element);
|
|
||||||
element.Result = result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载文件验证(非线程版)
|
|
||||||
/// </summary>
|
|
||||||
internal class VerifyTempFileWithoutThreadOperation : VerifyTempFileOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
VerifyFile,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly VerifyTempFileElement _element;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public VerifyTempFileWithoutThreadOperation(VerifyTempFileElement element)
|
|
||||||
{
|
|
||||||
_element = element;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.VerifyFile;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.VerifyFile)
|
|
||||||
{
|
|
||||||
_element.Result = (int)CacheHelper.VerifyingTempFile(_element);
|
|
||||||
|
|
||||||
VerifyResult = (EVerifyResult)_element.Result;
|
|
||||||
if (VerifyResult == EVerifyResult.Succeed)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Failed verify file : {_element.TempDataFilePath} ! ErrorCode : {VerifyResult}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class PackageCachingOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
FindCacheFiles,
|
|
||||||
VerifyCacheFiles,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly PersistentManager _persistent;
|
|
||||||
private readonly CacheManager _cache;
|
|
||||||
private FindCacheFilesOperation _findCacheFilesOp;
|
|
||||||
private VerifyCacheFilesOperation _verifyCacheFilesOp;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public PackageCachingOperation(PersistentManager persistent, CacheManager cache)
|
|
||||||
{
|
|
||||||
_persistent = persistent;
|
|
||||||
_cache = cache;
|
|
||||||
}
|
|
||||||
internal override void InternalOnStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.FindCacheFiles;
|
|
||||||
}
|
|
||||||
internal override void InternalOnUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.FindCacheFiles)
|
|
||||||
{
|
|
||||||
if (_findCacheFilesOp == null)
|
|
||||||
{
|
|
||||||
_findCacheFilesOp = new FindCacheFilesOperation(_persistent, _cache);
|
|
||||||
OperationSystem.StartOperation(_cache.PackageName, _findCacheFilesOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Progress = _findCacheFilesOp.Progress;
|
|
||||||
if (_findCacheFilesOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_steps = ESteps.VerifyCacheFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.VerifyCacheFiles)
|
|
||||||
{
|
|
||||||
if (_verifyCacheFilesOp == null)
|
|
||||||
{
|
|
||||||
_verifyCacheFilesOp = VerifyCacheFilesOperation.CreateOperation(_cache, _findCacheFilesOp.VerifyElements);
|
|
||||||
OperationSystem.StartOperation(_cache.PackageName, _verifyCacheFilesOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Progress = _verifyCacheFilesOp.Progress;
|
|
||||||
if (_verifyCacheFilesOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 注意:总是返回成功
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeed;
|
|
||||||
|
|
||||||
int totalCount = _cache.GetAllCachedFilesCount();
|
|
||||||
YooLogger.Log($"Package '{_cache.PackageName}' cached files count : {totalCount}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4ff95e7516dbfa148b4fe16eaab783fb
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal static class PersistentHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取WWW加载本地资源的路径
|
|
||||||
/// </summary>
|
|
||||||
public static string ConvertToWWWPath(string path)
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
return StringUtility.Format("file:///{0}", path);
|
|
||||||
#elif UNITY_WEBGL
|
|
||||||
return path;
|
|
||||||
#elif UNITY_IPHONE
|
|
||||||
return StringUtility.Format("file://{0}", path);
|
|
||||||
#elif UNITY_ANDROID
|
|
||||||
if (path.StartsWith("jar:file://"))
|
|
||||||
return path;
|
|
||||||
else
|
|
||||||
return StringUtility.Format("jar:file://{0}", path);
|
|
||||||
#elif UNITY_STANDALONE_OSX
|
|
||||||
return new System.Uri(path).ToString();
|
|
||||||
#elif UNITY_STANDALONE
|
|
||||||
return StringUtility.Format("file:///{0}", path);
|
|
||||||
#elif UNITY_OPENHARMONY
|
|
||||||
return path;
|
|
||||||
#else
|
|
||||||
return path;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9581e7c53fe081749ab849ec6e2be3d6
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class PersistentManager
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, string> _cachedDataFilePaths = new Dictionary<string, string>(10000);
|
|
||||||
private readonly Dictionary<string, string> _cachedInfoFilePaths = new Dictionary<string, string>(10000);
|
|
||||||
private readonly Dictionary<string, string> _tempDataFilePaths = new Dictionary<string, string>(10000);
|
|
||||||
private readonly Dictionary<string, string> _buildinFilePaths = new Dictionary<string, string>(10000);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所属包裹
|
|
||||||
/// </summary>
|
|
||||||
public readonly string PackageName;
|
|
||||||
|
|
||||||
public string BuildinRoot { private set; get; }
|
|
||||||
public string BuildinPackageRoot { private set; get; }
|
|
||||||
|
|
||||||
public string SandboxRoot { private set; get; }
|
|
||||||
public string SandboxPackageRoot { private set; get; }
|
|
||||||
public string SandboxCacheFilesRoot { private set; get; }
|
|
||||||
public string SandboxManifestFilesRoot { private set; get; }
|
|
||||||
public string SandboxAppFootPrintFilePath { private set; get; }
|
|
||||||
|
|
||||||
public bool AppendFileExtension { private set; get; }
|
|
||||||
|
|
||||||
|
|
||||||
public PersistentManager(string packageName)
|
|
||||||
{
|
|
||||||
PackageName = packageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化
|
|
||||||
/// </summary>
|
|
||||||
public void Initialize(string buildinRoot, string sandboxRoot, bool appendFileExtension)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(buildinRoot))
|
|
||||||
BuildinRoot = CreateDefaultBuildinRoot();
|
|
||||||
else
|
|
||||||
BuildinRoot = buildinRoot;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(sandboxRoot))
|
|
||||||
SandboxRoot = CreateDefaultSandboxRoot();
|
|
||||||
else
|
|
||||||
SandboxRoot = sandboxRoot;
|
|
||||||
|
|
||||||
BuildinPackageRoot = PathUtility.Combine(BuildinRoot, PackageName);
|
|
||||||
SandboxPackageRoot = PathUtility.Combine(SandboxRoot, PackageName);
|
|
||||||
SandboxCacheFilesRoot = PathUtility.Combine(SandboxPackageRoot, YooAssetSettings.CacheFilesFolderName);
|
|
||||||
SandboxManifestFilesRoot = PathUtility.Combine(SandboxPackageRoot, YooAssetSettings.ManifestFolderName);
|
|
||||||
SandboxAppFootPrintFilePath = PathUtility.Combine(SandboxPackageRoot, YooAssetSettings.AppFootPrintFileName);
|
|
||||||
AppendFileExtension = appendFileExtension;
|
|
||||||
}
|
|
||||||
private static string CreateDefaultBuildinRoot()
|
|
||||||
{
|
|
||||||
string path = PathUtility.Combine(UnityEngine.Application.streamingAssetsPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
|
||||||
#if UNITY_OPENHARMONY
|
|
||||||
return $"file://{path}";
|
|
||||||
#else
|
|
||||||
return path;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private static string CreateDefaultSandboxRoot()
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
// 注意:为了方便调试查看,编辑器下把存储目录放到项目里。
|
|
||||||
string projectPath = Path.GetDirectoryName(UnityEngine.Application.dataPath);
|
|
||||||
projectPath = PathUtility.RegularPath(projectPath);
|
|
||||||
return PathUtility.Combine(projectPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
|
||||||
#elif UNITY_STANDALONE
|
|
||||||
return PathUtility.Combine(UnityEngine.Application.dataPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
|
||||||
#else
|
|
||||||
return PathUtility.Combine(UnityEngine.Application.persistentDataPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetCachedDataFilePath(PackageBundle bundle)
|
|
||||||
{
|
|
||||||
if (_cachedDataFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
|
||||||
{
|
|
||||||
string folderName = bundle.FileHash.Substring(0, 2);
|
|
||||||
filePath = PathUtility.Combine(SandboxCacheFilesRoot, folderName, bundle.CacheGUID, YooAssetSettings.CacheBundleDataFileName);
|
|
||||||
if (AppendFileExtension)
|
|
||||||
filePath += bundle.FileExtension;
|
|
||||||
_cachedDataFilePaths.Add(bundle.CacheGUID, filePath);
|
|
||||||
}
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
public string GetCachedInfoFilePath(PackageBundle bundle)
|
|
||||||
{
|
|
||||||
if (_cachedInfoFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
|
||||||
{
|
|
||||||
string folderName = bundle.FileHash.Substring(0, 2);
|
|
||||||
filePath = PathUtility.Combine(SandboxCacheFilesRoot, folderName, bundle.CacheGUID, YooAssetSettings.CacheBundleInfoFileName);
|
|
||||||
_cachedInfoFilePaths.Add(bundle.CacheGUID, filePath);
|
|
||||||
}
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
public string GetTempDataFilePath(PackageBundle bundle)
|
|
||||||
{
|
|
||||||
if (_tempDataFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
|
||||||
{
|
|
||||||
string cachedDataFilePath = GetCachedDataFilePath(bundle);
|
|
||||||
filePath = $"{cachedDataFilePath}.temp";
|
|
||||||
_tempDataFilePaths.Add(bundle.CacheGUID, filePath);
|
|
||||||
}
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
public string GetBuildinFilePath(PackageBundle bundle)
|
|
||||||
{
|
|
||||||
if (_buildinFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
|
||||||
{
|
|
||||||
filePath = PathUtility.Combine(BuildinPackageRoot, bundle.FileName);
|
|
||||||
_buildinFilePaths.Add(bundle.CacheGUID, filePath);
|
|
||||||
}
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除沙盒里的包裹目录
|
|
||||||
/// </summary>
|
|
||||||
public void DeleteSandboxPackageFolder()
|
|
||||||
{
|
|
||||||
if (Directory.Exists(SandboxPackageRoot))
|
|
||||||
Directory.Delete(SandboxPackageRoot, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除沙盒内的缓存文件夹
|
|
||||||
/// </summary>
|
|
||||||
public void DeleteSandboxCacheFilesFolder()
|
|
||||||
{
|
|
||||||
if (Directory.Exists(SandboxCacheFilesRoot))
|
|
||||||
Directory.Delete(SandboxCacheFilesRoot, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除沙盒内的清单文件夹
|
|
||||||
/// </summary>
|
|
||||||
public void DeleteSandboxManifestFilesFolder()
|
|
||||||
{
|
|
||||||
if (Directory.Exists(SandboxManifestFilesRoot))
|
|
||||||
Directory.Delete(SandboxManifestFilesRoot, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取沙盒内包裹的清单文件的路径
|
|
||||||
/// </summary>
|
|
||||||
public string GetSandboxPackageManifestFilePath(string packageVersion)
|
|
||||||
{
|
|
||||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
|
||||||
return PathUtility.Combine(SandboxManifestFilesRoot, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取沙盒内包裹的哈希文件的路径
|
|
||||||
/// </summary>
|
|
||||||
public string GetSandboxPackageHashFilePath(string packageVersion)
|
|
||||||
{
|
|
||||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
|
||||||
return PathUtility.Combine(SandboxManifestFilesRoot, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取沙盒内包裹的版本文件的路径
|
|
||||||
/// </summary>
|
|
||||||
public string GetSandboxPackageVersionFilePath()
|
|
||||||
{
|
|
||||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
|
||||||
return PathUtility.Combine(SandboxManifestFilesRoot, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 保存沙盒内默认的包裹版本
|
|
||||||
/// </summary>
|
|
||||||
public void SaveSandboxPackageVersionFile(string version)
|
|
||||||
{
|
|
||||||
YooLogger.Log($"Save package version : {version}");
|
|
||||||
string filePath = GetSandboxPackageVersionFilePath();
|
|
||||||
FileUtility.WriteAllText(filePath, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取APP内包裹的清单文件的路径
|
|
||||||
/// </summary>
|
|
||||||
public string GetBuildinPackageManifestFilePath(string packageVersion)
|
|
||||||
{
|
|
||||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
|
||||||
return PathUtility.Combine(BuildinPackageRoot, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取APP内包裹的哈希文件的路径
|
|
||||||
/// </summary>
|
|
||||||
public string GetBuildinPackageHashFilePath(string packageVersion)
|
|
||||||
{
|
|
||||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
|
||||||
return PathUtility.Combine(BuildinPackageRoot, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取APP内包裹的版本文件的路径
|
|
||||||
/// </summary>
|
|
||||||
public string GetBuildinPackageVersionFilePath()
|
|
||||||
{
|
|
||||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
|
||||||
return PathUtility.Combine(BuildinPackageRoot, fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 62ee5fd2821fe85488efff3f8242b703
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存文件验证元素
|
|
||||||
/// </summary>
|
|
||||||
internal class VerifyCacheFileElement
|
|
||||||
{
|
|
||||||
public string PackageName { private set; get; }
|
|
||||||
public string CacheGUID { private set; get; }
|
|
||||||
public string FileRootPath { private set; get; }
|
|
||||||
public string DataFilePath { private set; get; }
|
|
||||||
public string InfoFilePath { private set; get; }
|
|
||||||
|
|
||||||
public EVerifyResult Result;
|
|
||||||
public string DataFileCRC;
|
|
||||||
public long DataFileSize;
|
|
||||||
|
|
||||||
public VerifyCacheFileElement(string packageName, string cacheGUID, string fileRootPath, string dataFilePath, string infoFilePath)
|
|
||||||
{
|
|
||||||
PackageName = packageName;
|
|
||||||
CacheGUID = cacheGUID;
|
|
||||||
FileRootPath = fileRootPath;
|
|
||||||
DataFilePath = dataFilePath;
|
|
||||||
InfoFilePath = infoFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteFiles()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(FileRootPath, true);
|
|
||||||
}
|
|
||||||
catch (System.Exception e)
|
|
||||||
{
|
|
||||||
YooLogger.Warning($"Failed delete cache bundle folder : {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载文件验证元素
|
|
||||||
/// </summary>
|
|
||||||
internal class VerifyTempFileElement
|
|
||||||
{
|
|
||||||
public string TempDataFilePath { private set; get; }
|
|
||||||
public string FileCRC { private set; get; }
|
|
||||||
public long FileSize { private set; get; }
|
|
||||||
|
|
||||||
public int Result = 0; // 注意:原子操作对象
|
|
||||||
|
|
||||||
public VerifyTempFileElement(string tempDataFilePath, string fileCRC, long fileSize)
|
|
||||||
{
|
|
||||||
TempDataFilePath = tempDataFilePath;
|
|
||||||
FileCRC = fileCRC;
|
|
||||||
FileSize = fileSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5a4b96484bd701f4289b2f74c38abaa8
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -25,7 +25,7 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载状态
|
/// 加载状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Status;
|
public EOperationStatus Status;
|
||||||
|
|
||||||
public int CompareTo(DebugBundleInfo other)
|
public int CompareTo(DebugBundleInfo other)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 自定义下载器的请求委托
|
|
||||||
/// </summary>
|
|
||||||
public delegate UnityWebRequest DownloadRequestDelegate(string url);
|
|
||||||
|
|
||||||
|
|
||||||
internal static class DownloadHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 下载失败后清理文件的HTTP错误码
|
|
||||||
/// </summary>
|
|
||||||
public static List<long> ClearFileResponseCodes { set; get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 自定义下载器的请求委托
|
|
||||||
/// </summary>
|
|
||||||
public static DownloadRequestDelegate RequestDelegate = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建一个新的网络请求
|
|
||||||
/// </summary>
|
|
||||||
public static UnityWebRequest NewRequest(string requestURL)
|
|
||||||
{
|
|
||||||
UnityWebRequest webRequest;
|
|
||||||
if (RequestDelegate != null)
|
|
||||||
webRequest = RequestDelegate.Invoke(requestURL);
|
|
||||||
else
|
|
||||||
webRequest = new UnityWebRequest(requestURL, UnityWebRequest.kHttpVerbGET);
|
|
||||||
return webRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d19eae1f43ecf6347925a06730a6c846
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 1. 保证每一时刻资源文件只存在一个下载器
|
|
||||||
/// 2. 保证下载器下载完成后立刻验证并缓存
|
|
||||||
/// 3. 保证资源文件不会被重复下载
|
|
||||||
/// </summary>
|
|
||||||
internal class DownloadManager
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, DownloaderBase> _downloaders = new Dictionary<string, DownloaderBase>(1000);
|
|
||||||
private readonly List<string> _removeList = new List<string>(1000);
|
|
||||||
|
|
||||||
private uint _breakpointResumeFileSize;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所属包裹
|
|
||||||
/// </summary>
|
|
||||||
public readonly string PackageName;
|
|
||||||
|
|
||||||
|
|
||||||
public DownloadManager(string packageName)
|
|
||||||
{
|
|
||||||
PackageName = packageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化
|
|
||||||
/// </summary>
|
|
||||||
public void Initialize(uint breakpointResumeFileSize)
|
|
||||||
{
|
|
||||||
_breakpointResumeFileSize = breakpointResumeFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 更新下载器
|
|
||||||
/// </summary>
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
// 更新下载器
|
|
||||||
_removeList.Clear();
|
|
||||||
foreach (var valuePair in _downloaders)
|
|
||||||
{
|
|
||||||
var downloader = valuePair.Value;
|
|
||||||
downloader.Update();
|
|
||||||
if (downloader.IsDone())
|
|
||||||
{
|
|
||||||
_removeList.Add(valuePair.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除下载器
|
|
||||||
foreach (var key in _removeList)
|
|
||||||
{
|
|
||||||
_downloaders.Remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 销毁所有下载器
|
|
||||||
/// </summary>
|
|
||||||
public void DestroyAll()
|
|
||||||
{
|
|
||||||
foreach (var valuePair in _downloaders)
|
|
||||||
{
|
|
||||||
var downloader = valuePair.Value;
|
|
||||||
downloader.Abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
_downloaders.Clear();
|
|
||||||
_removeList.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建下载器
|
|
||||||
/// 注意:只有第一次请求的参数才有效
|
|
||||||
/// </summary>
|
|
||||||
public DownloaderBase CreateDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60)
|
|
||||||
{
|
|
||||||
// 查询存在的下载器
|
|
||||||
if (_downloaders.TryGetValue(bundleInfo.CachedDataFilePath, out var downloader))
|
|
||||||
{
|
|
||||||
downloader.Reference();
|
|
||||||
return downloader;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果资源已经缓存
|
|
||||||
if (bundleInfo.IsCached())
|
|
||||||
{
|
|
||||||
var completedDownloader = new CompletedDownloader(bundleInfo);
|
|
||||||
return completedDownloader;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建新的下载器
|
|
||||||
DownloaderBase newDownloader = null;
|
|
||||||
YooLogger.Log($"Beginning to download bundle : {bundleInfo.Bundle.BundleName} URL : {bundleInfo.RemoteMainURL}");
|
|
||||||
#if UNITY_WEBGL
|
|
||||||
if (bundleInfo.Bundle.Buildpipeline == EDefaultBuildPipeline.RawFileBuildPipeline.ToString())
|
|
||||||
{
|
|
||||||
FileUtility.CreateFileDirectory(bundleInfo.CachedDataFilePath);
|
|
||||||
System.Type requesterType = typeof(FileGeneralRequest);
|
|
||||||
newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Type requesterType = typeof(AssetBundleWebRequest);
|
|
||||||
newDownloader = new WebDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
FileUtility.CreateFileDirectory(bundleInfo.CachedDataFilePath);
|
|
||||||
bool resumeDownload = bundleInfo.Bundle.FileSize >= _breakpointResumeFileSize;
|
|
||||||
if (resumeDownload)
|
|
||||||
{
|
|
||||||
System.Type requesterType = typeof(FileResumeRequest);
|
|
||||||
newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Type requesterType = typeof(FileGeneralRequest);
|
|
||||||
newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 返回新创建的下载器
|
|
||||||
_downloaders.Add(bundleInfo.CachedDataFilePath, newDownloader);
|
|
||||||
newDownloader.Reference();
|
|
||||||
return newDownloader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 停止不再使用的下载器
|
|
||||||
/// </summary>
|
|
||||||
public void AbortUnusedDownloader()
|
|
||||||
{
|
|
||||||
foreach (var valuePair in _downloaders)
|
|
||||||
{
|
|
||||||
var downloader = valuePair.Value;
|
|
||||||
if (downloader.RefCount <= 0)
|
|
||||||
{
|
|
||||||
downloader.Abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6fbbbfe01e018b241bf33469f870a4b8
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
30
Assets/YooAsset/Runtime/DownloadSystem/DownloadParam.cs
Normal file
30
Assets/YooAsset/Runtime/DownloadSystem/DownloadParam.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class DownloadParam
|
||||||
|
{
|
||||||
|
public readonly int FailedTryAgain;
|
||||||
|
public readonly int Timeout;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导入的本地文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string ImportFilePath { set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主资源地址
|
||||||
|
/// </summary>
|
||||||
|
public string MainURL { set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 备用资源地址
|
||||||
|
/// </summary>
|
||||||
|
public string FallbackURL { set; get; }
|
||||||
|
|
||||||
|
public DownloadParam(int failedTryAgain, int timeout)
|
||||||
|
{
|
||||||
|
FailedTryAgain = failedTryAgain;
|
||||||
|
Timeout = timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8616c7550a7890141af598898a12df1b
|
guid: 56ea224b45d314e4a86b558404e9b6c8
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义下载器的请求委托
|
||||||
|
/// </summary>
|
||||||
|
public delegate UnityWebRequest UnityWebRequestDelegate(string url);
|
||||||
|
|
||||||
|
internal class DownloadSystemHelper
|
||||||
|
{
|
||||||
|
public static UnityWebRequestDelegate UnityWebRequestCreater = null;
|
||||||
|
public static UnityWebRequest NewUnityWebRequestGet(string requestURL)
|
||||||
|
{
|
||||||
|
UnityWebRequest webRequest;
|
||||||
|
if (UnityWebRequestCreater != null)
|
||||||
|
webRequest = UnityWebRequestCreater.Invoke(requestURL);
|
||||||
|
else
|
||||||
|
webRequest = new UnityWebRequest(requestURL, UnityWebRequest.kHttpVerbGET);
|
||||||
|
return webRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取WWW加载本地资源的路径
|
||||||
|
/// </summary>
|
||||||
|
public static string ConvertToWWWPath(string path)
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
return StringUtility.Format("file:///{0}", path);
|
||||||
|
#elif UNITY_WEBGL
|
||||||
|
return path;
|
||||||
|
#elif UNITY_IPHONE
|
||||||
|
return StringUtility.Format("file://{0}", path);
|
||||||
|
#elif UNITY_ANDROID
|
||||||
|
if (path.StartsWith("jar:file://"))
|
||||||
|
return path;
|
||||||
|
else
|
||||||
|
return StringUtility.Format("jar:file://{0}", path);
|
||||||
|
#elif UNITY_STANDALONE_OSX
|
||||||
|
return new System.Uri(path).ToString();
|
||||||
|
#elif UNITY_STANDALONE
|
||||||
|
return StringUtility.Format("file:///{0}", path);
|
||||||
|
#elif UNITY_OPENHARMONY
|
||||||
|
return StringUtility.Format("file://{0}", path);
|
||||||
|
#else
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e4a97c06e069c1146a881fcb359f9b4b
|
guid: 5bacfa8c42e283a45a2d21cbb93d6e5d
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal sealed class CompletedDownloader : DownloaderBase
|
|
||||||
{
|
|
||||||
public CompletedDownloader(BundleInfo bundleInfo) : base(bundleInfo, null, 0, 0)
|
|
||||||
{
|
|
||||||
DownloadProgress = 1f;
|
|
||||||
DownloadedBytes = (ulong)bundleInfo.Bundle.FileSize;
|
|
||||||
_status = EStatus.Succeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SendRequest(params object[] param)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override void Abort()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override AssetBundle GetAssetBundle()
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3c7907ead85e2f94786308b28c37a8aa
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal abstract class DownloaderBase
|
|
||||||
{
|
|
||||||
public enum EStatus
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Succeed,
|
|
||||||
Failed
|
|
||||||
}
|
|
||||||
|
|
||||||
protected readonly BundleInfo _bundleInfo;
|
|
||||||
protected readonly System.Type _requesterType;
|
|
||||||
protected readonly int _timeout;
|
|
||||||
protected int _failedTryAgain;
|
|
||||||
|
|
||||||
protected IWebRequester _requester;
|
|
||||||
protected EStatus _status = EStatus.None;
|
|
||||||
protected string _lastestNetError = string.Empty;
|
|
||||||
protected long _lastestHttpCode = 0;
|
|
||||||
|
|
||||||
// 请求次数
|
|
||||||
protected int _requestCount = 0;
|
|
||||||
protected string _requestURL;
|
|
||||||
|
|
||||||
// 超时相关
|
|
||||||
protected bool _isAbort = false;
|
|
||||||
protected ulong _latestDownloadBytes;
|
|
||||||
protected float _latestDownloadRealtime;
|
|
||||||
protected float _tryAgainTimer;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否等待异步结束
|
|
||||||
/// 警告:只能用于解压APP内部资源
|
|
||||||
/// </summary>
|
|
||||||
public bool WaitForAsyncComplete = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载进度(0f~1f)
|
|
||||||
/// </summary>
|
|
||||||
public float DownloadProgress { protected set; get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 已经下载的总字节数
|
|
||||||
/// </summary>
|
|
||||||
public ulong DownloadedBytes { protected set; get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 引用计数
|
|
||||||
/// </summary>
|
|
||||||
public int RefCount { private set; get; }
|
|
||||||
|
|
||||||
|
|
||||||
public DownloaderBase(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout)
|
|
||||||
{
|
|
||||||
_bundleInfo = bundleInfo;
|
|
||||||
_requesterType = requesterType;
|
|
||||||
_failedTryAgain = failedTryAgain;
|
|
||||||
_timeout = timeout;
|
|
||||||
}
|
|
||||||
public abstract void SendRequest(params object[] args);
|
|
||||||
public abstract void Update();
|
|
||||||
public abstract void Abort();
|
|
||||||
public abstract AssetBundle GetAssetBundle();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 引用(引用计数递加)
|
|
||||||
/// </summary>
|
|
||||||
public void Reference()
|
|
||||||
{
|
|
||||||
RefCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 释放(引用计数递减)
|
|
||||||
/// </summary>
|
|
||||||
public void Release()
|
|
||||||
{
|
|
||||||
RefCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测下载器是否已经完成(无论成功或失败)
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDone()
|
|
||||||
{
|
|
||||||
return _status == EStatus.Succeed || _status == EStatus.Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载过程是否发生错误
|
|
||||||
/// </summary>
|
|
||||||
public bool HasError()
|
|
||||||
{
|
|
||||||
return _status == EStatus.Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按照错误级别打印错误
|
|
||||||
/// </summary>
|
|
||||||
public void ReportError()
|
|
||||||
{
|
|
||||||
YooLogger.Error(GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按照警告级别打印错误
|
|
||||||
/// </summary>
|
|
||||||
public void ReportWarning()
|
|
||||||
{
|
|
||||||
YooLogger.Warning(GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取最近发生的错误信息
|
|
||||||
/// </summary>
|
|
||||||
public string GetLastError()
|
|
||||||
{
|
|
||||||
return $"Failed to download : {_requestURL} Error : {_lastestNetError} Code : {_lastestHttpCode}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取下载文件的大小
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public long GetDownloadFileSize()
|
|
||||||
{
|
|
||||||
return _bundleInfo.Bundle.FileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取下载的资源包名称
|
|
||||||
/// </summary>
|
|
||||||
public string GetDownloadBundleName()
|
|
||||||
{
|
|
||||||
return _bundleInfo.Bundle.BundleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取网络请求地址
|
|
||||||
/// </summary>
|
|
||||||
protected string GetRequestURL()
|
|
||||||
{
|
|
||||||
// 轮流返回请求地址
|
|
||||||
_requestCount++;
|
|
||||||
if (_requestCount % 2 == 0)
|
|
||||||
return _bundleInfo.RemoteFallbackURL;
|
|
||||||
else
|
|
||||||
return _bundleInfo.RemoteMainURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 超时判定方法
|
|
||||||
/// </summary>
|
|
||||||
protected void CheckTimeout()
|
|
||||||
{
|
|
||||||
// 注意:在连续时间段内无新增下载数据及判定为超时
|
|
||||||
if (_isAbort == false)
|
|
||||||
{
|
|
||||||
if (_latestDownloadBytes != DownloadedBytes)
|
|
||||||
{
|
|
||||||
_latestDownloadBytes = DownloadedBytes;
|
|
||||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
|
||||||
}
|
|
||||||
|
|
||||||
float offset = Time.realtimeSinceStartup - _latestDownloadRealtime;
|
|
||||||
if (offset > _timeout)
|
|
||||||
{
|
|
||||||
YooLogger.Warning($"Web file request timeout : {_requestURL}");
|
|
||||||
if (_requester != null)
|
|
||||||
_requester.Abort();
|
|
||||||
_isAbort = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: dda4d1eafa2c9f34fade509f8dae9c04
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 文件下载器
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class FileDownloader : DownloaderBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
PrepareDownload,
|
|
||||||
CreateDownloader,
|
|
||||||
CheckDownload,
|
|
||||||
VerifyTempFile,
|
|
||||||
WaitingVerifyTempFile,
|
|
||||||
CachingFile,
|
|
||||||
TryAgain,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private VerifyTempFileOperation _verifyFileOp = null;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public FileDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override void SendRequest(params object[] args)
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None)
|
|
||||||
{
|
|
||||||
_steps = ESteps.PrepareDownload;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None)
|
|
||||||
return;
|
|
||||||
if (IsDone())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 准备下载
|
|
||||||
if (_steps == ESteps.PrepareDownload)
|
|
||||||
{
|
|
||||||
// 获取请求地址
|
|
||||||
_requestURL = GetRequestURL();
|
|
||||||
|
|
||||||
// 重置变量
|
|
||||||
DownloadProgress = 0f;
|
|
||||||
DownloadedBytes = 0;
|
|
||||||
|
|
||||||
// 重置变量
|
|
||||||
_isAbort = false;
|
|
||||||
_latestDownloadBytes = 0;
|
|
||||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
|
||||||
|
|
||||||
// 重置计时器
|
|
||||||
if (_tryAgainTimer > 0f)
|
|
||||||
YooLogger.Warning($"Try again download : {_requestURL}");
|
|
||||||
_tryAgainTimer = 0f;
|
|
||||||
|
|
||||||
_steps = ESteps.CreateDownloader;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
if (_steps == ESteps.CreateDownloader)
|
|
||||||
{
|
|
||||||
_requester = (IWebRequester)Activator.CreateInstance(_requesterType);
|
|
||||||
_requester.Create(_requestURL, _bundleInfo);
|
|
||||||
_steps = ESteps.CheckDownload;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测下载结果
|
|
||||||
if (_steps == ESteps.CheckDownload)
|
|
||||||
{
|
|
||||||
_requester.Update();
|
|
||||||
DownloadedBytes = _requester.DownloadedBytes;
|
|
||||||
DownloadProgress = _requester.DownloadProgress;
|
|
||||||
if (_requester.IsDone() == false)
|
|
||||||
{
|
|
||||||
CheckTimeout();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastestNetError = _requester.RequestNetError;
|
|
||||||
_lastestHttpCode = _requester.RequestHttpCode;
|
|
||||||
if (_requester.Status != ERequestStatus.Success)
|
|
||||||
{
|
|
||||||
_steps = ESteps.TryAgain;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.VerifyTempFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证下载文件
|
|
||||||
if (_steps == ESteps.VerifyTempFile)
|
|
||||||
{
|
|
||||||
VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
|
|
||||||
_verifyFileOp = VerifyTempFileOperation.CreateOperation(element);
|
|
||||||
OperationSystem.StartOperation(_bundleInfo.Bundle.PackageName, _verifyFileOp);
|
|
||||||
_steps = ESteps.WaitingVerifyTempFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 等待验证完成
|
|
||||||
if (_steps == ESteps.WaitingVerifyTempFile)
|
|
||||||
{
|
|
||||||
if (WaitForAsyncComplete)
|
|
||||||
_verifyFileOp.InternalOnUpdate();
|
|
||||||
|
|
||||||
if (_verifyFileOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_verifyFileOp.Status == EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
_steps = ESteps.CachingFile;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string tempFilePath = _bundleInfo.TempDataFilePath;
|
|
||||||
if (File.Exists(tempFilePath))
|
|
||||||
File.Delete(tempFilePath);
|
|
||||||
|
|
||||||
_lastestNetError = _verifyFileOp.Error;
|
|
||||||
_steps = ESteps.TryAgain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存下载文件
|
|
||||||
if (_steps == ESteps.CachingFile)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CachingFile();
|
|
||||||
_status = EStatus.Succeed;
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_lastestNetError = e.Message;
|
|
||||||
_steps = ESteps.TryAgain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新尝试下载
|
|
||||||
if (_steps == ESteps.TryAgain)
|
|
||||||
{
|
|
||||||
if (_failedTryAgain <= 0)
|
|
||||||
{
|
|
||||||
ReportError();
|
|
||||||
_status = EStatus.Failed;
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
|
||||||
if (_tryAgainTimer > 1f)
|
|
||||||
{
|
|
||||||
_failedTryAgain--;
|
|
||||||
_steps = ESteps.PrepareDownload;
|
|
||||||
ReportWarning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Abort()
|
|
||||||
{
|
|
||||||
if (_requester != null)
|
|
||||||
_requester.Abort();
|
|
||||||
|
|
||||||
if (IsDone() == false)
|
|
||||||
{
|
|
||||||
_status = EStatus.Failed;
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
_lastestNetError = "user abort";
|
|
||||||
_lastestHttpCode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override AssetBundle GetAssetBundle()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 缓存下载文件
|
|
||||||
/// </summary>
|
|
||||||
private void CachingFile()
|
|
||||||
{
|
|
||||||
string tempFilePath = _bundleInfo.TempDataFilePath;
|
|
||||||
string infoFilePath = _bundleInfo.CachedInfoFilePath;
|
|
||||||
string dataFilePath = _bundleInfo.CachedDataFilePath;
|
|
||||||
string dataFileCRC = _bundleInfo.Bundle.FileCRC;
|
|
||||||
long dataFileSize = _bundleInfo.Bundle.FileSize;
|
|
||||||
|
|
||||||
if (File.Exists(infoFilePath))
|
|
||||||
File.Delete(infoFilePath);
|
|
||||||
if (File.Exists(dataFilePath))
|
|
||||||
File.Delete(dataFilePath);
|
|
||||||
|
|
||||||
// 移动临时文件路径
|
|
||||||
FileInfo fileInfo = new FileInfo(tempFilePath);
|
|
||||||
fileInfo.MoveTo(dataFilePath);
|
|
||||||
|
|
||||||
// 写入信息文件记录验证数据
|
|
||||||
CacheHelper.WriteInfoToFile(infoFilePath, dataFileCRC, dataFileSize);
|
|
||||||
|
|
||||||
// 记录缓存文件
|
|
||||||
_bundleInfo.CacheRecord();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4c6e1a8bc8d5e664395395daa772ddd7
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal sealed class WebDownloader : DownloaderBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
PrepareDownload,
|
|
||||||
CreateDownloader,
|
|
||||||
CheckDownload,
|
|
||||||
TryAgain,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
private bool _getAssetBundle = false;
|
|
||||||
|
|
||||||
public WebDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override void SendRequest(params object[] args)
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None)
|
|
||||||
{
|
|
||||||
if (args.Length > 0)
|
|
||||||
{
|
|
||||||
_getAssetBundle = (bool)args[0];
|
|
||||||
}
|
|
||||||
_steps = ESteps.PrepareDownload;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None)
|
|
||||||
return;
|
|
||||||
if (IsDone())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
if (_steps == ESteps.PrepareDownload)
|
|
||||||
{
|
|
||||||
// 获取请求地址
|
|
||||||
_requestURL = GetRequestURL();
|
|
||||||
|
|
||||||
// 重置变量
|
|
||||||
DownloadProgress = 0f;
|
|
||||||
DownloadedBytes = 0;
|
|
||||||
|
|
||||||
// 重置变量
|
|
||||||
_isAbort = false;
|
|
||||||
_latestDownloadBytes = 0;
|
|
||||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
|
||||||
|
|
||||||
// 重置计时器
|
|
||||||
if (_tryAgainTimer > 0f)
|
|
||||||
YooLogger.Warning($"Try again download : {_requestURL}");
|
|
||||||
_tryAgainTimer = 0f;
|
|
||||||
|
|
||||||
_steps = ESteps.CreateDownloader;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
if (_steps == ESteps.CreateDownloader)
|
|
||||||
{
|
|
||||||
_requester = (IWebRequester)Activator.CreateInstance(_requesterType);
|
|
||||||
_requester.Create(_requestURL, _bundleInfo, _getAssetBundle);
|
|
||||||
_steps = ESteps.CheckDownload;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测下载结果
|
|
||||||
if (_steps == ESteps.CheckDownload)
|
|
||||||
{
|
|
||||||
_requester.Update();
|
|
||||||
DownloadedBytes = _requester.DownloadedBytes;
|
|
||||||
DownloadProgress = _requester.DownloadProgress;
|
|
||||||
if (_requester.IsDone() == false)
|
|
||||||
{
|
|
||||||
CheckTimeout();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastestNetError = _requester.RequestNetError;
|
|
||||||
_lastestHttpCode = _requester.RequestHttpCode;
|
|
||||||
if (_requester.Status != ERequestStatus.Success)
|
|
||||||
{
|
|
||||||
_steps = ESteps.TryAgain;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_status = EStatus.Succeed;
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新尝试下载
|
|
||||||
if (_steps == ESteps.TryAgain)
|
|
||||||
{
|
|
||||||
if (_failedTryAgain <= 0)
|
|
||||||
{
|
|
||||||
ReportError();
|
|
||||||
_status = EStatus.Failed;
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
|
||||||
if (_tryAgainTimer > 1f)
|
|
||||||
{
|
|
||||||
_failedTryAgain--;
|
|
||||||
_steps = ESteps.PrepareDownload;
|
|
||||||
ReportWarning();
|
|
||||||
YooLogger.Warning($"Try again download : {_requestURL}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void Abort()
|
|
||||||
{
|
|
||||||
if (_requester != null)
|
|
||||||
_requester.Abort();
|
|
||||||
|
|
||||||
if (IsDone() == false)
|
|
||||||
{
|
|
||||||
_status = EStatus.Failed;
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
_lastestNetError = "user abort";
|
|
||||||
_lastestHttpCode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override AssetBundle GetAssetBundle()
|
|
||||||
{
|
|
||||||
return (AssetBundle)_requester.GetRequestObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 41bc4bc56f59ddb4b8925f9536bbbfbc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d29a9623b2b346e439b7a7e37fafa781
|
guid: a8f060786f8775b4a82cc3f55d9135e2
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a93a516506b2b5c4492fdefe26eb1175
|
guid: 4630dac2050606043bb146325fdce6ad
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using UnityEngine.Networking;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class UnityWebDataRequestOperation : UnityWebRequestOperation
|
||||||
|
{
|
||||||
|
private UnityWebRequestAsyncOperation _requestOperation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求结果
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Result { private set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
internal UnityWebDataRequestOperation(string url, int timeout = 60) : base(url, timeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.CreateRequest;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.CreateRequest)
|
||||||
|
{
|
||||||
|
_latestDownloadBytes = 0;
|
||||||
|
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
CreateWebRequest();
|
||||||
|
_steps = ESteps.Download;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.Download)
|
||||||
|
{
|
||||||
|
Progress = _requestOperation.progress;
|
||||||
|
if (_requestOperation.isDone == false)
|
||||||
|
{
|
||||||
|
CheckRequestTimeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckRequestResult())
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Result = _webRequest.downloadHandler.data;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:最终释放请求器
|
||||||
|
DisposeRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalOnAbort()
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
DisposeRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateWebRequest()
|
||||||
|
{
|
||||||
|
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||||
|
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||||
|
_webRequest.downloadHandler = handler;
|
||||||
|
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||||
|
_requestOperation = _webRequest.SendWebRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using UnityEngine.Networking;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class UnityWebFileRequestOperation : UnityWebRequestOperation
|
||||||
|
{
|
||||||
|
private UnityWebRequestAsyncOperation _requestOperation;
|
||||||
|
private readonly string _fileSavePath;
|
||||||
|
|
||||||
|
internal UnityWebFileRequestOperation(string url, string fileSavePath, int timeout = 60) : base(url, timeout)
|
||||||
|
{
|
||||||
|
_fileSavePath = fileSavePath;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.CreateRequest;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.CreateRequest)
|
||||||
|
{
|
||||||
|
_latestDownloadBytes = 0;
|
||||||
|
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
CreateWebRequest();
|
||||||
|
_steps = ESteps.Download;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.Download)
|
||||||
|
{
|
||||||
|
Progress = _requestOperation.progress;
|
||||||
|
if (_requestOperation.isDone == false)
|
||||||
|
{
|
||||||
|
CheckRequestTimeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckRequestResult())
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:最终释放请求器
|
||||||
|
DisposeRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalOnAbort()
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
DisposeRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateWebRequest()
|
||||||
|
{
|
||||||
|
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||||
|
DownloadHandlerFile handler = new DownloadHandlerFile(_fileSavePath);
|
||||||
|
handler.removeFileOnAbort = true;
|
||||||
|
_webRequest.downloadHandler = handler;
|
||||||
|
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||||
|
_requestOperation = _webRequest.SendWebRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,99 +6,58 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal abstract class UnityWebRequesterBase
|
internal abstract class UnityWebRequestOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
|
protected enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
CreateRequest,
|
||||||
|
Download,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
protected UnityWebRequest _webRequest;
|
protected UnityWebRequest _webRequest;
|
||||||
protected UnityWebRequestAsyncOperation _operationHandle;
|
protected readonly string _requestURL;
|
||||||
|
protected ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
// 超时相关
|
// 超时相关
|
||||||
private float _timeout;
|
protected readonly float _timeout;
|
||||||
|
protected ulong _latestDownloadBytes;
|
||||||
|
protected float _latestDownloadRealtime;
|
||||||
private bool _isAbort = false;
|
private bool _isAbort = false;
|
||||||
private ulong _latestDownloadBytes;
|
|
||||||
private float _latestDownloadRealtime;
|
|
||||||
|
|
||||||
/// <summary>
|
public string URL
|
||||||
/// 请求URL地址
|
|
||||||
/// </summary>
|
|
||||||
public string URL { protected set; get; }
|
|
||||||
|
|
||||||
|
|
||||||
protected void ResetTimeout(float timeout)
|
|
||||||
{
|
{
|
||||||
|
get { return _requestURL; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal UnityWebRequestOperation(string url, int timeout)
|
||||||
|
{
|
||||||
|
_requestURL = url;
|
||||||
_timeout = timeout;
|
_timeout = timeout;
|
||||||
_latestDownloadBytes = 0;
|
|
||||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 释放下载器
|
/// 释放下载器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
protected void DisposeRequest()
|
||||||
{
|
{
|
||||||
if (_webRequest != null)
|
if (_webRequest != null)
|
||||||
{
|
{
|
||||||
_webRequest.Dispose();
|
_webRequest.Dispose();
|
||||||
_webRequest = null;
|
_webRequest = null;
|
||||||
_operationHandle = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否完毕(无论成功失败)
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDone()
|
|
||||||
{
|
|
||||||
if (_operationHandle == null)
|
|
||||||
return false;
|
|
||||||
return _operationHandle.isDone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载进度
|
|
||||||
/// </summary>
|
|
||||||
public float Progress()
|
|
||||||
{
|
|
||||||
if (_operationHandle == null)
|
|
||||||
return 0;
|
|
||||||
return _operationHandle.progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载是否发生错误
|
|
||||||
/// </summary>
|
|
||||||
public bool HasError()
|
|
||||||
{
|
|
||||||
#if UNITY_2020_3_OR_NEWER
|
|
||||||
return _webRequest.result != UnityWebRequest.Result.Success;
|
|
||||||
#else
|
|
||||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取错误信息
|
|
||||||
/// </summary>
|
|
||||||
public string GetError()
|
|
||||||
{
|
|
||||||
if (_webRequest != null)
|
|
||||||
{
|
|
||||||
return $"URL : {URL} Error : {_webRequest.error}";
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检测超时
|
/// 检测超时
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CheckTimeout()
|
protected void CheckRequestTimeout()
|
||||||
{
|
{
|
||||||
// 注意:在连续时间段内无新增下载数据及判定为超时
|
// 注意:在连续时间段内无新增下载数据及判定为超时
|
||||||
if (_isAbort == false)
|
if (_isAbort == false)
|
||||||
{
|
{
|
||||||
if (_latestDownloadBytes != _webRequest.downloadedBytes)
|
if ( _latestDownloadBytes != _webRequest.downloadedBytes)
|
||||||
{
|
{
|
||||||
_latestDownloadBytes = _webRequest.downloadedBytes;
|
_latestDownloadBytes = _webRequest.downloadedBytes;
|
||||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||||
@@ -112,5 +71,33 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检测请求结果
|
||||||
|
/// </summary>
|
||||||
|
protected bool CheckRequestResult()
|
||||||
|
{
|
||||||
|
#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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using UnityEngine.Networking;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class UnityWebTextRequestOperation : UnityWebRequestOperation
|
||||||
|
{
|
||||||
|
private UnityWebRequestAsyncOperation _requestOperation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求结果
|
||||||
|
/// </summary>
|
||||||
|
public string Result { private set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
internal UnityWebTextRequestOperation(string url, int timeout = 60) : base(url, timeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.CreateRequest;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.CreateRequest)
|
||||||
|
{
|
||||||
|
_latestDownloadBytes = 0;
|
||||||
|
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
CreateWebRequest();
|
||||||
|
_steps = ESteps.Download;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.Download)
|
||||||
|
{
|
||||||
|
Progress = _requestOperation.progress;
|
||||||
|
if (_requestOperation.isDone == false)
|
||||||
|
{
|
||||||
|
CheckRequestTimeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckRequestResult())
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Result = _webRequest.downloadHandler.text;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:最终释放请求器
|
||||||
|
DisposeRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalOnAbort()
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
DisposeRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateWebRequest()
|
||||||
|
{
|
||||||
|
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||||
|
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||||
|
_webRequest.downloadHandler = handler;
|
||||||
|
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||||
|
_requestOperation = _webRequest.SendWebRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 08f3e92fdbd5d56459d8882be1f54f60
|
guid: a488de5dcd6f4c448a47c4b574d5c9bc
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8a97534752300584a9b8c60c04c6a6a8
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class AssetBundleWebRequest : IWebRequester
|
|
||||||
{
|
|
||||||
private UnityWebRequest _webRequest;
|
|
||||||
private DownloadHandlerAssetBundle _downloadhandler;
|
|
||||||
private AssetBundle _cacheAssetBundle;
|
|
||||||
private bool _getAssetBundle = false;
|
|
||||||
|
|
||||||
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
|
|
||||||
public float DownloadProgress { private set; get; }
|
|
||||||
public ulong DownloadedBytes { private set; get; }
|
|
||||||
public string RequestNetError { private set; get; }
|
|
||||||
public long RequestHttpCode { private set; get; }
|
|
||||||
|
|
||||||
public AssetBundleWebRequest() { }
|
|
||||||
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
|
|
||||||
{
|
|
||||||
if (Status != ERequestStatus.None)
|
|
||||||
throw new System.Exception("Should never get here !");
|
|
||||||
|
|
||||||
if (args.Length == 0)
|
|
||||||
throw new System.Exception("Not found param value");
|
|
||||||
|
|
||||||
// 解析附加参数
|
|
||||||
_getAssetBundle = (bool)args[0];
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
_webRequest = DownloadHelper.NewRequest(requestURL);
|
|
||||||
if (CacheHelper.DisableUnityCacheOnWebGL)
|
|
||||||
{
|
|
||||||
uint crc = bundleInfo.Bundle.UnityCRC;
|
|
||||||
_downloadhandler = new DownloadHandlerAssetBundle(requestURL, crc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint crc = bundleInfo.Bundle.UnityCRC;
|
|
||||||
var hash = Hash128.Parse(bundleInfo.Bundle.FileHash);
|
|
||||||
_downloadhandler = new DownloadHandlerAssetBundle(requestURL, hash, crc);
|
|
||||||
}
|
|
||||||
#if UNITY_2020_3_OR_NEWER
|
|
||||||
_downloadhandler.autoLoadAssetBundle = false;
|
|
||||||
#endif
|
|
||||||
_webRequest.downloadHandler = _downloadhandler;
|
|
||||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
|
||||||
_webRequest.SendWebRequest();
|
|
||||||
Status = ERequestStatus.InProgress;
|
|
||||||
}
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (Status == ERequestStatus.None)
|
|
||||||
return;
|
|
||||||
if (IsDone())
|
|
||||||
return;
|
|
||||||
|
|
||||||
DownloadProgress = _webRequest.downloadProgress;
|
|
||||||
DownloadedBytes = _webRequest.downloadedBytes;
|
|
||||||
if (_webRequest.isDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 检查网络错误
|
|
||||||
#if UNITY_2020_3_OR_NEWER
|
|
||||||
RequestHttpCode = _webRequest.responseCode;
|
|
||||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
|
||||||
{
|
|
||||||
RequestNetError = _webRequest.error;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = ERequestStatus.Success;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
RequestHttpCode = _webRequest.responseCode;
|
|
||||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
|
||||||
{
|
|
||||||
RequestNetError = _webRequest.error;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = ERequestStatus.Success;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 缓存加载的AssetBundle对象
|
|
||||||
if (Status == ERequestStatus.Success)
|
|
||||||
{
|
|
||||||
if (_getAssetBundle)
|
|
||||||
{
|
|
||||||
_cacheAssetBundle = _downloadhandler.assetBundle;
|
|
||||||
if (_cacheAssetBundle == null)
|
|
||||||
{
|
|
||||||
RequestNetError = "assetBundle is null";
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最终释放下载器
|
|
||||||
DisposeWebRequest();
|
|
||||||
}
|
|
||||||
public void Abort()
|
|
||||||
{
|
|
||||||
// 如果下载任务还未开始
|
|
||||||
if (Status == ERequestStatus.None)
|
|
||||||
{
|
|
||||||
RequestNetError = "user cancel";
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 注意:为了防止同一个文件强制停止之后立马创建新的请求,应该让进行中的请求自然终止。
|
|
||||||
if (_webRequest != null)
|
|
||||||
{
|
|
||||||
if (_webRequest.isDone == false)
|
|
||||||
_webRequest.Abort(); // If in progress, halts the UnityWebRequest as soon as possible.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool IsDone()
|
|
||||||
{
|
|
||||||
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public object GetRequestObject()
|
|
||||||
{
|
|
||||||
return _cacheAssetBundle;
|
|
||||||
}
|
|
||||||
private void DisposeWebRequest()
|
|
||||||
{
|
|
||||||
if (_webRequest != null)
|
|
||||||
{
|
|
||||||
_webRequest.Dispose();
|
|
||||||
_webRequest = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 34efa85440da15247b570a98b0971282
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class FileGeneralRequest : IWebRequester
|
|
||||||
{
|
|
||||||
private UnityWebRequest _webRequest;
|
|
||||||
|
|
||||||
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
|
|
||||||
public float DownloadProgress { private set; get; }
|
|
||||||
public ulong DownloadedBytes { private set; get; }
|
|
||||||
public string RequestNetError { private set; get; }
|
|
||||||
public long RequestHttpCode { private set; get; }
|
|
||||||
|
|
||||||
public FileGeneralRequest() { }
|
|
||||||
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
|
|
||||||
{
|
|
||||||
if (Status != ERequestStatus.None)
|
|
||||||
throw new System.Exception("Should never get here !");
|
|
||||||
|
|
||||||
string tempFilePath = bundleInfo.TempDataFilePath;
|
|
||||||
|
|
||||||
// 删除临时文件
|
|
||||||
if (File.Exists(tempFilePath))
|
|
||||||
File.Delete(tempFilePath);
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
_webRequest = DownloadHelper.NewRequest(requestURL);
|
|
||||||
DownloadHandlerFile handler = new DownloadHandlerFile(tempFilePath);
|
|
||||||
handler.removeFileOnAbort = true;
|
|
||||||
_webRequest.downloadHandler = handler;
|
|
||||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
|
||||||
_webRequest.SendWebRequest();
|
|
||||||
Status = ERequestStatus.InProgress;
|
|
||||||
}
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (Status == ERequestStatus.None)
|
|
||||||
return;
|
|
||||||
if (IsDone())
|
|
||||||
return;
|
|
||||||
|
|
||||||
DownloadProgress = _webRequest.downloadProgress;
|
|
||||||
DownloadedBytes = _webRequest.downloadedBytes;
|
|
||||||
if (_webRequest.isDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 检查网络错误
|
|
||||||
#if UNITY_2020_3_OR_NEWER
|
|
||||||
RequestHttpCode = _webRequest.responseCode;
|
|
||||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
|
||||||
{
|
|
||||||
RequestNetError = _webRequest.error;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = ERequestStatus.Success;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
RequestHttpCode = _webRequest.responseCode;
|
|
||||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
|
||||||
{
|
|
||||||
RequestNetError = _webRequest.error;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = ERequestStatus.Success;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 最终释放下载器
|
|
||||||
DisposeWebRequest();
|
|
||||||
}
|
|
||||||
public void Abort()
|
|
||||||
{
|
|
||||||
DisposeWebRequest();
|
|
||||||
if (IsDone() == false)
|
|
||||||
{
|
|
||||||
RequestNetError = "user abort";
|
|
||||||
RequestHttpCode = 0;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool IsDone()
|
|
||||||
{
|
|
||||||
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public object GetRequestObject()
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
private void DisposeWebRequest()
|
|
||||||
{
|
|
||||||
if (_webRequest != null)
|
|
||||||
{
|
|
||||||
//注意:引擎底层会自动调用Abort方法
|
|
||||||
_webRequest.Dispose();
|
|
||||||
_webRequest = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b2f339136a4269343a3b5ab80450b889
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class FileResumeRequest : IWebRequester
|
|
||||||
{
|
|
||||||
private string _tempFilePath;
|
|
||||||
private UnityWebRequest _webRequest;
|
|
||||||
private DownloadHandlerFileRange _downloadHandle;
|
|
||||||
private ulong _fileOriginLength = 0;
|
|
||||||
|
|
||||||
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
|
|
||||||
public float DownloadProgress { private set; get; }
|
|
||||||
public ulong DownloadedBytes { private set; get; }
|
|
||||||
public string RequestNetError { private set; get; }
|
|
||||||
public long RequestHttpCode { private set; get; }
|
|
||||||
|
|
||||||
public FileResumeRequest() { }
|
|
||||||
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
|
|
||||||
{
|
|
||||||
if (Status != ERequestStatus.None)
|
|
||||||
throw new System.Exception("Should never get here !");
|
|
||||||
|
|
||||||
_tempFilePath = bundleInfo.TempDataFilePath;
|
|
||||||
long fileBytes = bundleInfo.Bundle.FileSize;
|
|
||||||
|
|
||||||
// 获取下载的起始位置
|
|
||||||
long fileLength = -1;
|
|
||||||
if (File.Exists(_tempFilePath))
|
|
||||||
{
|
|
||||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
|
||||||
fileLength = fileInfo.Length;
|
|
||||||
_fileOriginLength = (ulong)fileLength;
|
|
||||||
DownloadedBytes = _fileOriginLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测下载起始位置是否有效
|
|
||||||
if (fileLength >= fileBytes)
|
|
||||||
{
|
|
||||||
if (File.Exists(_tempFilePath))
|
|
||||||
File.Delete(_tempFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
_webRequest = DownloadHelper.NewRequest(requestURL);
|
|
||||||
#if UNITY_2019_4_OR_NEWER
|
|
||||||
var handler = new DownloadHandlerFile(_tempFilePath, true);
|
|
||||||
handler.removeFileOnAbort = false;
|
|
||||||
#else
|
|
||||||
var handler = new DownloadHandlerFileRange(tempFilePath, _bundleInfo.Bundle.FileSize, _webRequest);
|
|
||||||
_downloadHandle = handler;
|
|
||||||
#endif
|
|
||||||
_webRequest.downloadHandler = handler;
|
|
||||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
|
||||||
if (fileLength > 0)
|
|
||||||
_webRequest.SetRequestHeader("Range", $"bytes={fileLength}-");
|
|
||||||
_webRequest.SendWebRequest();
|
|
||||||
Status = ERequestStatus.InProgress;
|
|
||||||
}
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (Status == ERequestStatus.None)
|
|
||||||
return;
|
|
||||||
if (IsDone())
|
|
||||||
return;
|
|
||||||
|
|
||||||
DownloadProgress = _webRequest.downloadProgress;
|
|
||||||
DownloadedBytes = _fileOriginLength + _webRequest.downloadedBytes;
|
|
||||||
if (_webRequest.isDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 检查网络错误
|
|
||||||
#if UNITY_2020_3_OR_NEWER
|
|
||||||
RequestHttpCode = _webRequest.responseCode;
|
|
||||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
|
||||||
{
|
|
||||||
RequestNetError = _webRequest.error;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = ERequestStatus.Success;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
RequestHttpCode = _webRequest.responseCode;
|
|
||||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
|
||||||
{
|
|
||||||
RequestNetError = _webRequest.error;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = ERequestStatus.Success;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 注意:下载断点续传文件发生特殊错误码之后删除文件
|
|
||||||
if (Status == ERequestStatus.Error)
|
|
||||||
{
|
|
||||||
if (DownloadHelper.ClearFileResponseCodes != null)
|
|
||||||
{
|
|
||||||
if (DownloadHelper.ClearFileResponseCodes.Contains(RequestHttpCode))
|
|
||||||
{
|
|
||||||
if (File.Exists(_tempFilePath))
|
|
||||||
File.Delete(_tempFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最终释放下载器
|
|
||||||
DisposeWebRequest();
|
|
||||||
}
|
|
||||||
public void Abort()
|
|
||||||
{
|
|
||||||
DisposeWebRequest();
|
|
||||||
if (IsDone() == false)
|
|
||||||
{
|
|
||||||
RequestNetError = "user abort";
|
|
||||||
RequestHttpCode = 0;
|
|
||||||
Status = ERequestStatus.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool IsDone()
|
|
||||||
{
|
|
||||||
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public object GetRequestObject()
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
private void DisposeWebRequest()
|
|
||||||
{
|
|
||||||
if (_downloadHandle != null)
|
|
||||||
{
|
|
||||||
_downloadHandle.Cleanup();
|
|
||||||
_downloadHandle = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_webRequest != null)
|
|
||||||
{
|
|
||||||
//注意:引擎底层会自动调用Abort方法
|
|
||||||
_webRequest.Dispose();
|
|
||||||
_webRequest = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 816bf5396d7570e4ab28f1af407bc10f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal enum ERequestStatus
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
InProgress,
|
|
||||||
Error,
|
|
||||||
Success,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal interface IWebRequester
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 任务状态
|
|
||||||
/// </summary>
|
|
||||||
ERequestStatus Status { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 下载进度(0f~1f)
|
|
||||||
/// </summary>
|
|
||||||
float DownloadProgress { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 已经下载的总字节数
|
|
||||||
/// </summary>
|
|
||||||
ulong DownloadedBytes { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 返回的网络错误
|
|
||||||
/// </summary>
|
|
||||||
string RequestNetError { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 返回的HTTP CODE
|
|
||||||
/// </summary>
|
|
||||||
long RequestHttpCode { get; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建任务
|
|
||||||
/// </summary>
|
|
||||||
void Create(string url, BundleInfo bundleInfo, params object[] args);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 更新任务
|
|
||||||
/// </summary>
|
|
||||||
void Update();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 终止任务
|
|
||||||
/// </summary>
|
|
||||||
void Abort();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否已经完成(无论成功或失败)
|
|
||||||
/// </summary>
|
|
||||||
bool IsDone();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取请求的对象
|
|
||||||
/// </summary>
|
|
||||||
object GetRequestObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4d80b965d56870b43af1bf6943015914
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class UnityWebDataRequester : UnityWebRequesterBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 发送GET请求
|
|
||||||
/// </summary>
|
|
||||||
public void SendRequest(string url, int timeout = 60)
|
|
||||||
{
|
|
||||||
if (_webRequest == null)
|
|
||||||
{
|
|
||||||
URL = url;
|
|
||||||
ResetTimeout(timeout);
|
|
||||||
|
|
||||||
_webRequest = DownloadHelper.NewRequest(URL);
|
|
||||||
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
|
||||||
_webRequest.downloadHandler = handler;
|
|
||||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
|
||||||
_operationHandle = _webRequest.SendWebRequest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取下载的字节数据
|
|
||||||
/// </summary>
|
|
||||||
public byte[] GetData()
|
|
||||||
{
|
|
||||||
if (_webRequest != null && IsDone())
|
|
||||||
return _webRequest.downloadHandler.data;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取下载的文本数据
|
|
||||||
/// </summary>
|
|
||||||
public string GetText()
|
|
||||||
{
|
|
||||||
if (_webRequest != null && IsDone())
|
|
||||||
return _webRequest.downloadHandler.text;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class UnityWebFileRequester : UnityWebRequesterBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 发送GET请求
|
|
||||||
/// </summary>
|
|
||||||
public void SendRequest(string url, string fileSavePath, int timeout = 60)
|
|
||||||
{
|
|
||||||
if (_webRequest == null)
|
|
||||||
{
|
|
||||||
URL = url;
|
|
||||||
ResetTimeout(timeout);
|
|
||||||
|
|
||||||
_webRequest = DownloadHelper.NewRequest(URL);
|
|
||||||
DownloadHandlerFile handler = new DownloadHandlerFile(fileSavePath);
|
|
||||||
handler.removeFileOnAbort = true;
|
|
||||||
_webRequest.downloadHandler = handler;
|
|
||||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
|
||||||
_operationHandle = _webRequest.SendWebRequest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
public class RequestHelper
|
internal class WebRequestCounter
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 记录网络请求失败事件的次数
|
/// 记录网络请求失败事件的次数
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 96a75a20111d6124696665e7aac3564c
|
guid: d7ac605758b151748980942c6d563fed
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a82eeb6a47cd02c4cb38e851c8ed8784
|
guid: 6f2f046660639e54cb2c40610189a91c
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置资源清单目录
|
||||||
|
/// </summary>
|
||||||
|
internal class DefaultBuildinFileCatalog : ScriptableObject
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class FileWrapper
|
||||||
|
{
|
||||||
|
public string BundleGUID;
|
||||||
|
public string FileName;
|
||||||
|
|
||||||
|
public FileWrapper(string bundleGUID, string fileName)
|
||||||
|
{
|
||||||
|
BundleGUID = bundleGUID;
|
||||||
|
FileName = fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹名称
|
||||||
|
/// </summary>
|
||||||
|
public string PackageName;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹版本
|
||||||
|
/// </summary>
|
||||||
|
public string PackageVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件列表
|
||||||
|
/// </summary>
|
||||||
|
public List<FileWrapper> Wrappers = new List<FileWrapper>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b05c83971e3dca94f9fa460d396385e5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,427 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件系统
|
||||||
|
/// </summary>
|
||||||
|
internal class DefaultBuildinFileSystem : IFileSystem
|
||||||
|
{
|
||||||
|
private class UnpackRemoteServices : IRemoteServices
|
||||||
|
{
|
||||||
|
private readonly string _buildinPackageRoot;
|
||||||
|
protected readonly Dictionary<string, string> _mapping = new Dictionary<string, string>(10000);
|
||||||
|
|
||||||
|
public UnpackRemoteServices(string buildinPackRoot)
|
||||||
|
{
|
||||||
|
_buildinPackageRoot = buildinPackRoot;
|
||||||
|
}
|
||||||
|
string IRemoteServices.GetRemoteMainURL(string fileName)
|
||||||
|
{
|
||||||
|
return GetFileLoadURL(fileName);
|
||||||
|
}
|
||||||
|
string IRemoteServices.GetRemoteFallbackURL(string fileName)
|
||||||
|
{
|
||||||
|
return GetFileLoadURL(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFileLoadURL(string fileName)
|
||||||
|
{
|
||||||
|
if (_mapping.TryGetValue(fileName, out string url) == false)
|
||||||
|
{
|
||||||
|
string filePath = PathUtility.Combine(_buildinPackageRoot, fileName);
|
||||||
|
url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||||
|
_mapping.Add(fileName, url);
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FileWrapper
|
||||||
|
{
|
||||||
|
public string FileName { private set; get; }
|
||||||
|
|
||||||
|
public FileWrapper(string fileName)
|
||||||
|
{
|
||||||
|
FileName = fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000);
|
||||||
|
protected readonly Dictionary<string, Stream> _loadedStream = new Dictionary<string, Stream>(10000);
|
||||||
|
protected readonly Dictionary<string, string> _buildinFilePaths = new Dictionary<string, string>(10000);
|
||||||
|
protected IFileSystem _unpackFileSystem;
|
||||||
|
protected string _packageRoot;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹名称
|
||||||
|
/// </summary>
|
||||||
|
public string PackageName { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件根目录
|
||||||
|
/// </summary>
|
||||||
|
public string FileRoot
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _packageRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件数量
|
||||||
|
/// </summary>
|
||||||
|
public int FileCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _wrappers.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 自定义参数
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义参数:初始化的时候缓存文件校验级别
|
||||||
|
/// </summary>
|
||||||
|
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义参数:数据文件追加文件格式
|
||||||
|
/// </summary>
|
||||||
|
public bool AppendFileExtension { private set; get; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义参数:原生文件构建管线
|
||||||
|
/// </summary>
|
||||||
|
public bool RawFileBuildPipeline { private set; get; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义参数:解密方法类
|
||||||
|
/// </summary>
|
||||||
|
public IDecryptionServices DecryptionServices { private set; get; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
public DefaultBuildinFileSystem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
|
||||||
|
{
|
||||||
|
var operation = new DBFSInitializeOperation(this);
|
||||||
|
OperationSystem.StartOperation(PackageName, operation);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
|
||||||
|
{
|
||||||
|
var operation = new DBFSLoadPackageManifestOperation(this, packageVersion);
|
||||||
|
OperationSystem.StartOperation(PackageName, operation);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
|
||||||
|
{
|
||||||
|
var operation = new DBFSRequestPackageVersionOperation(this);
|
||||||
|
OperationSystem.StartOperation(PackageName, operation);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
public virtual FSClearAllBundleFilesOperation ClearAllBundleFilesAsync()
|
||||||
|
{
|
||||||
|
return _unpackFileSystem.ClearAllBundleFilesAsync();
|
||||||
|
}
|
||||||
|
public virtual FSClearUnusedBundleFilesOperation ClearUnusedBundleFilesAsync(PackageManifest manifest)
|
||||||
|
{
|
||||||
|
return _unpackFileSystem.ClearUnusedBundleFilesAsync(manifest);
|
||||||
|
}
|
||||||
|
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
|
||||||
|
{
|
||||||
|
param.ImportFilePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
return _unpackFileSystem.DownloadFileAsync(bundle, param);
|
||||||
|
}
|
||||||
|
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
if (NeedUnpack(bundle))
|
||||||
|
{
|
||||||
|
return _unpackFileSystem.LoadBundleFile(bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RawFileBuildPipeline)
|
||||||
|
{
|
||||||
|
var operation = new DBFSLoadRawBundleOperation(this, bundle);
|
||||||
|
OperationSystem.StartOperation(PackageName, operation);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var operation = new DBFSLoadAssetBundleOperation(this, bundle);
|
||||||
|
OperationSystem.StartOperation(PackageName, operation);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public virtual void UnloadBundleFile(PackageBundle bundle, object result)
|
||||||
|
{
|
||||||
|
AssetBundle assetBundle = result as AssetBundle;
|
||||||
|
if (assetBundle == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_unpackFileSystem.Exists(bundle))
|
||||||
|
{
|
||||||
|
_unpackFileSystem.UnloadBundleFile(bundle, assetBundle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (assetBundle != null)
|
||||||
|
assetBundle.Unload(true);
|
||||||
|
|
||||||
|
if (_loadedStream.TryGetValue(bundle.BundleGUID, out Stream managedStream))
|
||||||
|
{
|
||||||
|
if (managedStream != null)
|
||||||
|
{
|
||||||
|
managedStream.Close();
|
||||||
|
managedStream.Dispose();
|
||||||
|
}
|
||||||
|
_loadedStream.Remove(bundle.BundleGUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetParameter(string name, object value)
|
||||||
|
{
|
||||||
|
if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
|
||||||
|
{
|
||||||
|
FileVerifyLevel = (EFileVerifyLevel)value;
|
||||||
|
}
|
||||||
|
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
|
||||||
|
{
|
||||||
|
AppendFileExtension = (bool)value;
|
||||||
|
}
|
||||||
|
else if (name == FileSystemParametersDefine.RAW_FILE_BUILD_PIPELINE)
|
||||||
|
{
|
||||||
|
RawFileBuildPipeline = (bool)value;
|
||||||
|
}
|
||||||
|
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
|
||||||
|
{
|
||||||
|
DecryptionServices = (IDecryptionServices)value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
YooLogger.Warning($"Invalid parameter : {name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public virtual void OnCreate(string packageName, string rootDirectory)
|
||||||
|
{
|
||||||
|
PackageName = packageName;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(rootDirectory))
|
||||||
|
rootDirectory = GetDefaultRoot();
|
||||||
|
|
||||||
|
_packageRoot = PathUtility.Combine(rootDirectory, packageName);
|
||||||
|
|
||||||
|
// 创建解压文件系统
|
||||||
|
var remoteServices = new UnpackRemoteServices(_packageRoot);
|
||||||
|
_unpackFileSystem = new DefaultUnpackFileSystem();
|
||||||
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
|
||||||
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
|
||||||
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
|
||||||
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.RAW_FILE_BUILD_PIPELINE, RawFileBuildPipeline);
|
||||||
|
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
|
||||||
|
_unpackFileSystem.OnCreate(packageName, null);
|
||||||
|
}
|
||||||
|
public virtual void OnUpdate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool Belong(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
return _wrappers.ContainsKey(bundle.BundleGUID);
|
||||||
|
}
|
||||||
|
public virtual bool Exists(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
return _wrappers.ContainsKey(bundle.BundleGUID);
|
||||||
|
}
|
||||||
|
public virtual bool NeedDownload(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public virtual bool NeedUnpack(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
if (Belong(bundle) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
return RawFileBuildPipeline || bundle.Encrypted;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
public virtual bool NeedImport(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual byte[] ReadFileData(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
if (NeedUnpack(bundle))
|
||||||
|
return _unpackFileSystem.ReadFileData(bundle);
|
||||||
|
|
||||||
|
if (Exists(bundle) == false)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (bundle.Encrypted)
|
||||||
|
{
|
||||||
|
if (DecryptionServices == null)
|
||||||
|
{
|
||||||
|
YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string filePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
var fileInfo = new DecryptFileInfo()
|
||||||
|
{
|
||||||
|
BundleName = bundle.BundleName,
|
||||||
|
FileLoadCRC = bundle.UnityCRC,
|
||||||
|
FileLoadPath = filePath,
|
||||||
|
};
|
||||||
|
return DecryptionServices.ReadFileData(fileInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
return FileUtility.ReadAllBytes(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public virtual string ReadFileText(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
if (NeedUnpack(bundle))
|
||||||
|
return _unpackFileSystem.ReadFileText(bundle);
|
||||||
|
|
||||||
|
if (Exists(bundle) == false)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (bundle.Encrypted)
|
||||||
|
{
|
||||||
|
if (DecryptionServices == null)
|
||||||
|
{
|
||||||
|
YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string filePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
var fileInfo = new DecryptFileInfo()
|
||||||
|
{
|
||||||
|
BundleName = bundle.BundleName,
|
||||||
|
FileLoadCRC = bundle.UnityCRC,
|
||||||
|
FileLoadPath = filePath,
|
||||||
|
};
|
||||||
|
return DecryptionServices.ReadFileText(fileInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
return FileUtility.ReadAllText(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 内部方法
|
||||||
|
protected string GetDefaultRoot()
|
||||||
|
{
|
||||||
|
return PathUtility.Combine(Application.streamingAssetsPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
||||||
|
}
|
||||||
|
public string GetBuildinFileLoadPath(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
if (_buildinFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||||
|
{
|
||||||
|
filePath = PathUtility.Combine(_packageRoot, bundle.FileName);
|
||||||
|
_buildinFilePaths.Add(bundle.BundleGUID, filePath);
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
public string GetBuildinCatalogFileLoadPath()
|
||||||
|
{
|
||||||
|
string fileName = Path.GetFileNameWithoutExtension(DefaultBuildinFileSystemDefine.BuildinCatalogFileName);
|
||||||
|
return PathUtility.Combine(YooAssetSettingsData.Setting.DefaultYooFolderName, PackageName, fileName);
|
||||||
|
}
|
||||||
|
public string GetBuildinPackageVersionFilePath()
|
||||||
|
{
|
||||||
|
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
||||||
|
return PathUtility.Combine(FileRoot, fileName);
|
||||||
|
}
|
||||||
|
public string GetBuildinPackageHashFilePath(string packageVersion)
|
||||||
|
{
|
||||||
|
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||||
|
return PathUtility.Combine(FileRoot, fileName);
|
||||||
|
}
|
||||||
|
public string GetBuildinPackageManifestFilePath(string packageVersion)
|
||||||
|
{
|
||||||
|
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||||
|
return PathUtility.Combine(FileRoot, fileName);
|
||||||
|
}
|
||||||
|
public string GetStreamingAssetsPackageRoot()
|
||||||
|
{
|
||||||
|
string rootPath = PathUtility.Combine(Application.dataPath, "StreamingAssets", YooAssetSettingsData.Setting.DefaultYooFolderName);
|
||||||
|
return PathUtility.Combine(rootPath, PackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录文件信息
|
||||||
|
/// </summary>
|
||||||
|
public bool RecordFile(string bundleGUID, FileWrapper wrapper)
|
||||||
|
{
|
||||||
|
if (_wrappers.ContainsKey(bundleGUID))
|
||||||
|
{
|
||||||
|
YooLogger.Error($"{nameof(DefaultBuildinFileSystem)} has element : {bundleGUID}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_wrappers.Add(bundleGUID, wrapper);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化解压文件系统
|
||||||
|
/// </summary>
|
||||||
|
public FSInitializeFileSystemOperation InitializeUpackFileSystem()
|
||||||
|
{
|
||||||
|
return _unpackFileSystem.InitializeFileSystemAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载加密资源文件
|
||||||
|
/// </summary>
|
||||||
|
public AssetBundle LoadEncryptedAssetBundle(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
string filePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
var fileInfo = new DecryptFileInfo()
|
||||||
|
{
|
||||||
|
BundleName = bundle.BundleName,
|
||||||
|
FileLoadCRC = bundle.UnityCRC,
|
||||||
|
FileLoadPath = filePath,
|
||||||
|
};
|
||||||
|
|
||||||
|
var assetBundle = DecryptionServices.LoadAssetBundle(fileInfo, out var managedStream);
|
||||||
|
_loadedStream.Add(bundle.BundleGUID, managedStream);
|
||||||
|
return assetBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载加密资源文件
|
||||||
|
/// </summary>
|
||||||
|
public AssetBundleCreateRequest LoadEncryptedAssetBundleAsync(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
string filePath = GetBuildinFileLoadPath(bundle);
|
||||||
|
var fileInfo = new DecryptFileInfo()
|
||||||
|
{
|
||||||
|
BundleName = bundle.BundleName,
|
||||||
|
FileLoadCRC = bundle.UnityCRC,
|
||||||
|
FileLoadPath = filePath,
|
||||||
|
};
|
||||||
|
|
||||||
|
var createRequest = DecryptionServices.LoadAssetBundleAsync(fileInfo, out var managedStream);
|
||||||
|
_loadedStream.Add(bundle.BundleGUID, managedStream);
|
||||||
|
return createRequest;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 98465b987635afc479022ec358477491
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
public class DefaultBuildinFileSystemBuild : UnityEditor.Build.IPreprocessBuildWithReport
|
||||||
|
{
|
||||||
|
public int callbackOrder { get { return 0; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在构建应用程序前自动生成内置资源目录文件。
|
||||||
|
/// 原理:搜索StreamingAssets目录下的所有资源文件,然后将这些文件信息写入文件,并存储在Resources目录下。
|
||||||
|
/// </summary>
|
||||||
|
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
|
||||||
|
{
|
||||||
|
YooLogger.Log("Begin to create catalog file !");
|
||||||
|
|
||||||
|
string savePath = $"Assets/Resources/{YooAssetSettingsData.Setting.DefaultYooFolderName}";
|
||||||
|
DirectoryInfo saveDirectory = new DirectoryInfo(savePath);
|
||||||
|
if (saveDirectory.Exists)
|
||||||
|
saveDirectory.Delete(true);
|
||||||
|
|
||||||
|
string rootPath = $"{Application.dataPath}/StreamingAssets/{YooAssetSettingsData.Setting.DefaultYooFolderName}";
|
||||||
|
DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);
|
||||||
|
if (rootDirectory.Exists == false)
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Can not found StreamingAssets root directory : {rootPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索所有Package目录
|
||||||
|
DirectoryInfo[] subDirectories = rootDirectory.GetDirectories();
|
||||||
|
foreach (var subDirectory in subDirectories)
|
||||||
|
{
|
||||||
|
CreateBuildinCatalogFile(subDirectory.Name, subDirectory.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成包裹的内置资源目录文件
|
||||||
|
/// </summary>
|
||||||
|
public static void CreateBuildinCatalogFile(string packageName, string pacakgeDirectory)
|
||||||
|
{
|
||||||
|
// 获取资源清单版本
|
||||||
|
string packageVersion;
|
||||||
|
{
|
||||||
|
string versionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
||||||
|
string versionFilePath = $"{pacakgeDirectory}/{versionFileName}";
|
||||||
|
if (File.Exists(versionFilePath) == false)
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Can not found package version file : {versionFilePath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
packageVersion = FileUtility.ReadAllText(versionFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载资源清单文件
|
||||||
|
PackageManifest packageManifest;
|
||||||
|
{
|
||||||
|
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
|
||||||
|
string manifestFilePath = $"{pacakgeDirectory}/{manifestFileName}";
|
||||||
|
if (File.Exists(manifestFilePath) == false)
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Can not found package manifest file : {manifestFilePath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
|
||||||
|
packageManifest = ManifestTools.DeserializeFromBinary(binaryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件名映射关系
|
||||||
|
Dictionary<string, string> fileMapping = new Dictionary<string, string>();
|
||||||
|
{
|
||||||
|
foreach (var packageBundle in packageManifest.BundleList)
|
||||||
|
{
|
||||||
|
fileMapping.Add(packageBundle.FileName, packageBundle.BundleGUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建内置清单实例
|
||||||
|
var buildinFileCatalog = ScriptableObject.CreateInstance<DefaultBuildinFileCatalog>();
|
||||||
|
buildinFileCatalog.PackageName = packageName;
|
||||||
|
buildinFileCatalog.PackageVersion = packageVersion;
|
||||||
|
|
||||||
|
// 记录所有内置资源文件
|
||||||
|
DirectoryInfo rootDirectory = new DirectoryInfo(pacakgeDirectory);
|
||||||
|
FileInfo[] fileInfos = rootDirectory.GetFiles();
|
||||||
|
foreach (var fileInfo in fileInfos)
|
||||||
|
{
|
||||||
|
if (fileInfo.Extension == ".meta" || fileInfo.Extension == ".version" ||
|
||||||
|
fileInfo.Extension == ".hash" || fileInfo.Extension == ".bytes" ||
|
||||||
|
fileInfo.Extension == ".json")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string fileName = fileInfo.Name;
|
||||||
|
if (fileMapping.TryGetValue(fileName, out string bundleGUID))
|
||||||
|
{
|
||||||
|
var wrapper = new DefaultBuildinFileCatalog.FileWrapper(bundleGUID, fileName);
|
||||||
|
buildinFileCatalog.Wrappers.Add(wrapper);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Failed mapping file : {fileName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string saveFilePath = $"Assets/Resources/{YooAssetSettingsData.Setting.DefaultYooFolderName}/{packageName}/{DefaultBuildinFileSystemDefine.BuildinCatalogFileName}";
|
||||||
|
FileUtility.CreateFileDirectory(saveFilePath);
|
||||||
|
|
||||||
|
UnityEditor.AssetDatabase.CreateAsset(buildinFileCatalog, saveFilePath);
|
||||||
|
UnityEditor.EditorUtility.SetDirty(buildinFileCatalog);
|
||||||
|
#if UNITY_2019
|
||||||
|
UnityEditor.AssetDatabase.SaveAssets();
|
||||||
|
#else
|
||||||
|
UnityEditor.AssetDatabase.SaveAssetIfDirty(buildinFileCatalog);
|
||||||
|
#endif
|
||||||
|
Debug.Log($"Succeed to save buildin file catalog : {saveFilePath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6b5abe115ebfe1344b674db78b2edf6c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class DefaultBuildinFileSystemDefine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置清单文件名称
|
||||||
|
/// </summary>
|
||||||
|
public const string BuildinCatalogFileName = "BuildinCatalog.asset";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4aa038f71ffd2394abc5daee917fbc66
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 06f6a75331ed07a4a9e5e8f46dcf157e
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class DBFSInitializeOperation : FSInitializeFileSystemOperation
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
InitUnpackFileSystem,
|
||||||
|
LoadCatalogFile,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private FSInitializeFileSystemOperation _initUnpackFIleSystemOp;
|
||||||
|
private LoadBuildinCatalogFileOperation _loadCatalogFileOp;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
internal DBFSInitializeOperation(DefaultBuildinFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.InitUnpackFileSystem;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.InitUnpackFileSystem)
|
||||||
|
{
|
||||||
|
if (_initUnpackFIleSystemOp == null)
|
||||||
|
_initUnpackFIleSystemOp = _fileSystem.InitializeUpackFileSystem();
|
||||||
|
|
||||||
|
Progress = _initUnpackFIleSystemOp.Progress;
|
||||||
|
if (_initUnpackFIleSystemOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_initUnpackFIleSystemOp.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.LoadCatalogFile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _initUnpackFIleSystemOp.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadCatalogFile)
|
||||||
|
{
|
||||||
|
if (_loadCatalogFileOp == null)
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
// 兼容性初始化
|
||||||
|
// 说明:内置文件系统在编辑器下运行时需要动态生成
|
||||||
|
string packageRoot = _fileSystem.GetStreamingAssetsPackageRoot();
|
||||||
|
DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.PackageName, packageRoot);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_loadCatalogFileOp = new LoadBuildinCatalogFileOperation(_fileSystem);
|
||||||
|
OperationSystem.StartOperation(_fileSystem.PackageName, _loadCatalogFileOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_loadCatalogFileOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_loadCatalogFileOp.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _loadCatalogFileOp.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a15804d2ba6172a4b91f6c17245495a6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载AssetBundle文件
|
||||||
|
/// </summary>
|
||||||
|
internal class DBFSLoadAssetBundleOperation : FSLoadBundleOperation
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
LoadAssetBundle,
|
||||||
|
CheckResult,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private readonly PackageBundle _bundle;
|
||||||
|
private AssetBundleCreateRequest _createRequest;
|
||||||
|
private bool _isWaitForAsyncComplete = false;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
|
||||||
|
internal DBFSLoadAssetBundleOperation(DefaultBuildinFileSystem fileSystem, PackageBundle bundle)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_bundle = bundle;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
DownloadProgress = 1f;
|
||||||
|
DownloadedBytes = _bundle.FileSize;
|
||||||
|
_steps = ESteps.LoadAssetBundle;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadAssetBundle)
|
||||||
|
{
|
||||||
|
if (_bundle.Encrypted)
|
||||||
|
{
|
||||||
|
if (_fileSystem.DecryptionServices == null)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"The {nameof(IDecryptionServices)} is null !";
|
||||||
|
YooLogger.Error(Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isWaitForAsyncComplete)
|
||||||
|
{
|
||||||
|
if (_bundle.Encrypted)
|
||||||
|
{
|
||||||
|
Result = _fileSystem.LoadEncryptedAssetBundle(_bundle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
|
||||||
|
Result = AssetBundle.LoadFromFile(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_bundle.Encrypted)
|
||||||
|
{
|
||||||
|
_createRequest = _fileSystem.LoadEncryptedAssetBundleAsync(_bundle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
|
||||||
|
_createRequest = AssetBundle.LoadFromFileAsync(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_steps = ESteps.CheckResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.CheckResult)
|
||||||
|
{
|
||||||
|
if (_createRequest != null)
|
||||||
|
{
|
||||||
|
if (_isWaitForAsyncComplete)
|
||||||
|
{
|
||||||
|
// 强制挂起主线程(注意:该操作会很耗时)
|
||||||
|
YooLogger.Warning("Suspend the main thread to load unity bundle.");
|
||||||
|
Result = _createRequest.assetBundle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_createRequest.isDone == false)
|
||||||
|
return;
|
||||||
|
Result = _createRequest.assetBundle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Result != null)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_bundle.Encrypted)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Failed to load encrypted buildin asset bundle file : {_bundle.BundleName}";
|
||||||
|
YooLogger.Error(Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Failed to load buildin asset bundle file : {_bundle.BundleName}";
|
||||||
|
YooLogger.Error(Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalWaitForAsyncComplete()
|
||||||
|
{
|
||||||
|
_isWaitForAsyncComplete = true;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (ExecuteWhileDone())
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void AbortDownloadOperation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载原生文件
|
||||||
|
/// </summary>
|
||||||
|
internal class DBFSLoadRawBundleOperation : FSLoadBundleOperation
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
LoadBuildinRawBundle,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private readonly PackageBundle _bundle;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
|
||||||
|
internal DBFSLoadRawBundleOperation(DefaultBuildinFileSystem fileSystem, PackageBundle bundle)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_bundle = bundle;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
DownloadProgress = 1f;
|
||||||
|
DownloadedBytes = _bundle.FileSize;
|
||||||
|
_steps = ESteps.LoadBuildinRawBundle;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadBuildinRawBundle)
|
||||||
|
{
|
||||||
|
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Result = new RawBundle(_fileSystem, _bundle, filePath);
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Can not found buildin raw bundle file : {filePath}";
|
||||||
|
YooLogger.Error(Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalWaitForAsyncComplete()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (ExecuteWhileDone())
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void AbortDownloadOperation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 99fc95c784d960c45ba9373f31fbc7fe
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class DBFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
RequestBuildinPackageHash,
|
||||||
|
LoadBuildinPackageManifest,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private readonly string _packageVersion;
|
||||||
|
private RequestBuildinPackageHashOperation _requestBuildinPackageHashOp;
|
||||||
|
private LoadBuildinPackageManifestOperation _loadBuildinPackageManifestOp;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
|
||||||
|
public DBFSLoadPackageManifestOperation(DefaultBuildinFileSystem fileSystem, string packageVersion)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_packageVersion = packageVersion;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.RequestBuildinPackageHash;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.RequestBuildinPackageHash)
|
||||||
|
{
|
||||||
|
if (_requestBuildinPackageHashOp == null)
|
||||||
|
{
|
||||||
|
_requestBuildinPackageHashOp = new RequestBuildinPackageHashOperation(_fileSystem, _packageVersion);
|
||||||
|
OperationSystem.StartOperation(_fileSystem.PackageName, _requestBuildinPackageHashOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_requestBuildinPackageHashOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_requestBuildinPackageHashOp.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.LoadBuildinPackageManifest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _requestBuildinPackageHashOp.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadBuildinPackageManifest)
|
||||||
|
{
|
||||||
|
if (_loadBuildinPackageManifestOp == null)
|
||||||
|
{
|
||||||
|
string packageHash = _requestBuildinPackageHashOp.PackageHash;
|
||||||
|
_loadBuildinPackageManifestOp = new LoadBuildinPackageManifestOperation(_fileSystem, _packageVersion, packageHash);
|
||||||
|
OperationSystem.StartOperation(_fileSystem.PackageName, _loadBuildinPackageManifestOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_loadBuildinPackageManifestOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_loadBuildinPackageManifestOp.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Manifest = _loadBuildinPackageManifestOp.Manifest;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _loadBuildinPackageManifestOp.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b55b3624add2db6489954d999b13a9ec
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class DBFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
RequestPackageVersion,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private RequestBuildinPackageVersionOperation _requestBuildinPackageVersionOp;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
|
||||||
|
internal DBFSRequestPackageVersionOperation(DefaultBuildinFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.RequestPackageVersion;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.RequestPackageVersion)
|
||||||
|
{
|
||||||
|
if (_requestBuildinPackageVersionOp == null)
|
||||||
|
{
|
||||||
|
_requestBuildinPackageVersionOp = new RequestBuildinPackageVersionOperation(_fileSystem);
|
||||||
|
OperationSystem.StartOperation(_fileSystem.PackageName, _requestBuildinPackageVersionOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_requestBuildinPackageVersionOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
PackageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _requestBuildinPackageVersionOp.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f0b6ec24639af3741847a6a7ef09986a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: be1c19353672bb34ca3e4ddcb462402f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal sealed class LoadBuildinCatalogFileOperation : AsyncOperationBase
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
LoadCatalog,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
|
||||||
|
internal LoadBuildinCatalogFileOperation(DefaultBuildinFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.LoadCatalog;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadCatalog)
|
||||||
|
{
|
||||||
|
string catalogFilePath = _fileSystem.GetBuildinCatalogFileLoadPath();
|
||||||
|
var catalog = Resources.Load<DefaultBuildinFileCatalog>(catalogFilePath);
|
||||||
|
if (catalog == null)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Failed to load catalog file : {catalogFilePath}";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (catalog.PackageName != _fileSystem.PackageName)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var wrapper in catalog.Wrappers)
|
||||||
|
{
|
||||||
|
var fileWrapper = new DefaultBuildinFileSystem.FileWrapper(wrapper.FileName);
|
||||||
|
_fileSystem.RecordFile(wrapper.BundleGUID, fileWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a4113df346bbd1b4ead918b52ac46f55
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class LoadBuildinPackageManifestOperation : AsyncOperationBase
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
RequestFileData,
|
||||||
|
VerifyFileData,
|
||||||
|
LoadManifest,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||||
|
private readonly string _packageVersion;
|
||||||
|
private readonly string _packageHash;
|
||||||
|
private UnityWebDataRequestOperation _webDataRequestOp;
|
||||||
|
private DeserializeManifestOperation _deserializer;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹清单
|
||||||
|
/// </summary>
|
||||||
|
public PackageManifest Manifest { private set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
internal LoadBuildinPackageManifestOperation(DefaultBuildinFileSystem fileSystem, string packageVersion, string packageHash)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_packageVersion = packageVersion;
|
||||||
|
_packageHash = packageHash;
|
||||||
|
}
|
||||||
|
internal override void InternalOnStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.RequestFileData;
|
||||||
|
}
|
||||||
|
internal override void InternalOnUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.RequestFileData)
|
||||||
|
{
|
||||||
|
if (_webDataRequestOp == null)
|
||||||
|
{
|
||||||
|
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
|
||||||
|
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
|
||||||
|
_webDataRequestOp = new UnityWebDataRequestOperation(url);
|
||||||
|
OperationSystem.StartOperation(_fileSystem.PackageName, _webDataRequestOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_webDataRequestOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.VerifyFileData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _webDataRequestOp.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.VerifyFileData)
|
||||||
|
{
|
||||||
|
string fileHash = HashUtility.BytesMD5(_webDataRequestOp.Result);
|
||||||
|
if (fileHash == _packageHash)
|
||||||
|
{
|
||||||
|
_steps = ESteps.LoadManifest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = "Failed to verify buildin package manifest file !";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadManifest)
|
||||||
|
{
|
||||||
|
if (_deserializer == null)
|
||||||
|
{
|
||||||
|
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
|
||||||
|
OperationSystem.StartOperation(_fileSystem.PackageName, _deserializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress = _deserializer.Progress;
|
||||||
|
if (_deserializer.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_deserializer.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Manifest = _deserializer.Manifest;
|
||||||
|
Status = EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _deserializer.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user