refactor : 重构代码

This commit is contained in:
何冠峰
2026-02-03 14:02:38 +08:00
parent c2d8b8efcb
commit 0ec07033f7
130 changed files with 1448 additions and 1111 deletions

Binary file not shown.

View File

@@ -83,7 +83,7 @@ namespace YooAsset.Editor
public static string GetPackageManifestProcessServicesClassName(string packageName, string buildPipeline) public static string GetPackageManifestProcessServicesClassName(string packageName, string buildPipeline)
{ {
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestProcessServicesClassName"; string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestProcessServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(ManifestProcessNone).FullName}"); return EditorPrefs.GetString(key, $"{typeof(ManifestEncryptorNone).FullName}");
} }
public static void SetPackageManifestProcessServicesClassName(string packageName, string buildPipeline, string encyptionClassName) public static void SetPackageManifestProcessServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{ {
@@ -95,7 +95,7 @@ namespace YooAsset.Editor
public static string GetPackageManifestRestoreServicesClassName(string packageName, string buildPipeline) public static string GetPackageManifestRestoreServicesClassName(string packageName, string buildPipeline)
{ {
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestRestoreServicesClassName"; string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestRestoreServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(ManifestRestoreNone).FullName}"); return EditorPrefs.GetString(key, $"{typeof(ManifestDecryptorNone).FullName}");
} }
public static void SetPackageManifestRestoreServicesClassName(string packageName, string buildPipeline, string encyptionClassName) public static void SetPackageManifestRestoreServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{ {

View File

@@ -94,19 +94,19 @@ namespace YooAsset.Editor
public string BuildinFileCopyParams; public string BuildinFileCopyParams;
/// <summary> /// <summary>
/// 资源包加密服务类 /// 资源包加密
/// </summary> /// </summary>
public IBundleEncryptionServices EncryptionServices; public IBundleEncryptor BundleEncryptor;
/// <summary> /// <summary>
/// 资源清单加密服务类 /// 资源清单加密
/// </summary> /// </summary>
public IManifestProcessServices ManifestProcessServices; public IManifestEncryptor ManifestEncryptor;
/// <summary> /// <summary>
/// 资源清单解密服务类 /// 资源清单解密
/// </summary> /// </summary>
public IManifestRestoreServices ManifestRestoreServices; public IManifestDecryptor ManifestDecryptor;
private string _pipelineOutputDirectory = string.Empty; private string _pipelineOutputDirectory = string.Empty;
private string _packageOutputDirectory = string.Empty; private string _packageOutputDirectory = string.Empty;

View File

@@ -14,7 +14,7 @@ namespace YooAsset.Editor
{ {
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory(); string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
string buildPackageName = buildParametersContext.Parameters.PackageName; string buildPackageName = buildParametersContext.Parameters.PackageName;
var manifestServices = buildParametersContext.Parameters.ManifestRestoreServices; var manifestServices = buildParametersContext.Parameters.ManifestDecryptor;
BuiltinFileCatalogTools.CreateFile(manifestServices, buildPackageName, buildinRootDirectory); BuiltinFileCatalogTools.CreateFile(manifestServices, buildPackageName, buildinRootDirectory);
// 刷新目录 // 刷新目录

View File

@@ -81,7 +81,7 @@ namespace YooAsset.Editor
{ {
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion); string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
packagePath = $"{packageOutputDirectory}/{fileName}"; packagePath = $"{packageOutputDirectory}/{fileName}";
PackageManifestTools.SerializeManifestToBinary(packagePath, manifest, buildParameters.ManifestProcessServices); PackageManifestTools.SerializeManifestToBinary(packagePath, manifest, buildParameters.ManifestEncryptor);
packageHash = HashUtility.ComputeFileCRC32(packagePath); packageHash = HashUtility.ComputeFileCRC32(packagePath);
BuildLogger.Log($"Create package manifest file: {packagePath}"); BuildLogger.Log($"Create package manifest file: {packagePath}");
} }
@@ -106,7 +106,7 @@ namespace YooAsset.Editor
{ {
ManifestContext manifestContext = new ManifestContext(); ManifestContext manifestContext = new ManifestContext();
byte[] bytesData = FileUtility.ReadAllBytes(packagePath); byte[] bytesData = FileUtility.ReadAllBytes(packagePath);
manifestContext.Manifest = PackageManifestTools.DeserializeManifestFromBinary(bytesData, buildParameters.ManifestRestoreServices); manifestContext.Manifest = PackageManifestTools.DeserializeManifestFromBinary(bytesData, buildParameters.ManifestDecryptor);
context.SetContextObject(manifestContext); context.SetContextObject(manifestContext);
} }
} }

View File

@@ -44,9 +44,9 @@ namespace YooAsset.Editor
buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule; buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule;
buildReport.Summary.SingleReferencedPackAlone = buildParameters.SingleReferencedPackAlone; buildReport.Summary.SingleReferencedPackAlone = buildParameters.SingleReferencedPackAlone;
buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle; buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
buildReport.Summary.EncryptionServicesClassName = buildParameters.EncryptionServices == null ? "null" : buildParameters.EncryptionServices.GetType().FullName; buildReport.Summary.EncryptionServicesClassName = buildParameters.BundleEncryptor == null ? "null" : buildParameters.BundleEncryptor.GetType().FullName;
buildReport.Summary.ManifestProcessServicesClassName = buildParameters.ManifestProcessServices == null ? "null" : buildParameters.ManifestProcessServices.GetType().FullName; buildReport.Summary.ManifestProcessServicesClassName = buildParameters.ManifestEncryptor == null ? "null" : buildParameters.ManifestEncryptor.GetType().FullName;
buildReport.Summary.ManifestRestoreServicesClassName = buildParameters.ManifestRestoreServices == null ? "null" : buildParameters.ManifestRestoreServices.GetType().FullName; buildReport.Summary.ManifestRestoreServicesClassName = buildParameters.ManifestDecryptor == null ? "null" : buildParameters.ManifestDecryptor.GetType().FullName;
if (buildParameters is BuiltinBuildParameters) if (buildParameters is BuiltinBuildParameters)
{ {

View File

@@ -13,7 +13,7 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public void EncryptingBundleFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext) public void EncryptingBundleFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
{ {
var encryptionServices = buildParametersContext.Parameters.EncryptionServices; var encryptionServices = buildParametersContext.Parameters.BundleEncryptor;
if (encryptionServices == null) if (encryptionServices == null)
return; return;
@@ -24,14 +24,14 @@ namespace YooAsset.Editor
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory(); string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
foreach (var bundleInfo in buildMapContext.Collection) foreach (var bundleInfo in buildMapContext.Collection)
{ {
BundleEncryptionContext fileInfo = new BundleEncryptionContext(); BundleEncryptArgs args = new BundleEncryptArgs();
fileInfo.BundleName = bundleInfo.BundleName; args.BundleName = bundleInfo.BundleName;
fileInfo.FileLoadPath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}"; args.FilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
var encryptResult = encryptionServices.Encrypt(fileInfo); var encryptResult = encryptionServices.Encrypt(args);
if (encryptResult.Encrypted) if (encryptResult.Encrypted)
{ {
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt"; string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt";
FileUtility.WriteAllBytes(filePath, encryptResult.EncryptedData); FileUtility.WriteAllBytes(filePath, encryptResult.EncryptedFileData);
bundleInfo.EncryptedFilePath = filePath; bundleInfo.EncryptedFilePath = filePath;
bundleInfo.Encrypted = true; bundleInfo.Encrypted = true;
BuildLogger.Log($"Bundle file encryption complete: {filePath}"); BuildLogger.Log($"Bundle file encryption complete: {filePath}");

View File

@@ -1,9 +1,9 @@
 
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
public class EncryptionNone : IBundleEncryptionServices public class EncryptionNone : IBundleEncryptor
{ {
public BundleEncryptionResult Encrypt(BundleEncryptionContext fileInfo) public BundleEncryptResult Encrypt(BundleEncryptArgs fileInfo)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@@ -1,17 +1,17 @@
 
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
public class ManifestProcessNone : IManifestProcessServices public class ManifestEncryptorNone : IManifestEncryptor
{ {
byte[] IManifestProcessServices.ProcessManifest(byte[] fileData) byte[] IManifestEncryptor.Encrypt(byte[] fileData)
{ {
return fileData; return fileData;
} }
} }
public class ManifestRestoreNone : IManifestRestoreServices public class ManifestDecryptorNone : IManifestDecryptor
{ {
byte[] IManifestRestoreServices.RestoreManifest(byte[] fileData) byte[] IManifestDecryptor.Decrypt(byte[] fileData)
{ {
return fileData; return fileData;
} }

View File

@@ -44,43 +44,43 @@ namespace YooAsset.Editor
} }
/// <summary> /// <summary>
/// 创建资源包加密服务类实例 /// 创建资源包加密实例
/// </summary> /// </summary>
protected IBundleEncryptionServices CreateEncryptionServicesInstance() protected IBundleEncryptor CreateBundleEncryptorInstance()
{ {
var className = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, PipelineName); var className = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, PipelineName);
var classTypes = EditorTools.GetAssignableTypes(typeof(IBundleEncryptionServices)); var classTypes = EditorTools.GetAssignableTypes(typeof(IBundleEncryptor));
var classType = classTypes.Find(x => x.FullName.Equals(className)); var classType = classTypes.Find(x => x.FullName.Equals(className));
if (classType != null) if (classType != null)
return (IBundleEncryptionServices)Activator.CreateInstance(classType); return (IBundleEncryptor)Activator.CreateInstance(classType);
else else
return null; return null;
} }
/// <summary> /// <summary>
/// 创建资源清单加密服务类实例 /// 创建资源清单加密实例
/// </summary> /// </summary>
protected IManifestProcessServices CreateManifestProcessServicesInstance() protected IManifestEncryptor CreateManifestEncryptorInstance()
{ {
var className = AssetBundleBuilderSetting.GetPackageManifestProcessServicesClassName(PackageName, PipelineName); var className = AssetBundleBuilderSetting.GetPackageManifestProcessServicesClassName(PackageName, PipelineName);
var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestProcessServices)); var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestEncryptor));
var classType = classTypes.Find(x => x.FullName.Equals(className)); var classType = classTypes.Find(x => x.FullName.Equals(className));
if (classType != null) if (classType != null)
return (IManifestProcessServices)Activator.CreateInstance(classType); return (IManifestEncryptor)Activator.CreateInstance(classType);
else else
return null; return null;
} }
/// <summary> /// <summary>
/// 创建资源清单解密服务类实例 /// 创建资源清单解密实例
/// </summary> /// </summary>
protected IManifestRestoreServices CreateManifestRestoreServicesInstance() protected IManifestDecryptor CreateManifestDecryptorInstance()
{ {
var className = AssetBundleBuilderSetting.GetPackageManifestRestoreServicesClassName(PackageName, PipelineName); var className = AssetBundleBuilderSetting.GetPackageManifestRestoreServicesClassName(PackageName, PipelineName);
var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestRestoreServices)); var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestDecryptor));
var classType = classTypes.Find(x => x.FullName.Equals(className)); var classType = classTypes.Find(x => x.FullName.Equals(className));
if (classType != null) if (classType != null)
return (IManifestRestoreServices)Activator.CreateInstance(classType); return (IManifestDecryptor)Activator.CreateInstance(classType);
else else
return null; return null;
} }
@@ -184,7 +184,7 @@ namespace YooAsset.Editor
protected PopupField<Type> CreateEncryptionServicesField(VisualElement container) protected PopupField<Type> CreateEncryptionServicesField(VisualElement container)
{ {
// 资源包加密服务类 // 资源包加密服务类
var classTypes = EditorTools.GetAssignableTypes(typeof(IBundleEncryptionServices)); var classTypes = EditorTools.GetAssignableTypes(typeof(IBundleEncryptor));
if (classTypes.Count > 0) if (classTypes.Count > 0)
{ {
var className = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, PipelineName); var className = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, PipelineName);
@@ -215,7 +215,7 @@ namespace YooAsset.Editor
protected PopupField<Type> CreateManifestProcessServicesField(VisualElement container) protected PopupField<Type> CreateManifestProcessServicesField(VisualElement container)
{ {
// 资源清单加密服务类 // 资源清单加密服务类
var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestProcessServices)); var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestEncryptor));
if (classTypes.Count > 0) if (classTypes.Count > 0)
{ {
var className = AssetBundleBuilderSetting.GetPackageManifestProcessServicesClassName(PackageName, PipelineName); var className = AssetBundleBuilderSetting.GetPackageManifestProcessServicesClassName(PackageName, PipelineName);
@@ -246,7 +246,7 @@ namespace YooAsset.Editor
protected PopupField<Type> CreateManifestRestoreServicesField(VisualElement container) protected PopupField<Type> CreateManifestRestoreServicesField(VisualElement container)
{ {
// 资源清单加密服务类 // 资源清单加密服务类
var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestRestoreServices)); var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestDecryptor));
if (classTypes.Count > 0) if (classTypes.Count > 0)
{ {
var className = AssetBundleBuilderSetting.GetPackageManifestRestoreServicesClassName(PackageName, PipelineName); var className = AssetBundleBuilderSetting.GetPackageManifestRestoreServicesClassName(PackageName, PipelineName);

View File

@@ -121,9 +121,9 @@ namespace YooAsset.Editor
buildParameters.CompressOption = compressOption; buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache; buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB; buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance(); buildParameters.BundleEncryptor = CreateBundleEncryptorInstance();
buildParameters.ManifestProcessServices = CreateManifestProcessServicesInstance(); buildParameters.ManifestEncryptor = CreateManifestEncryptorInstance();
buildParameters.ManifestRestoreServices = CreateManifestRestoreServicesInstance(); buildParameters.ManifestDecryptor = CreateManifestDecryptorInstance();
BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline(); BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true); var buildResult = pipeline.Run(buildParameters, true);

View File

@@ -113,9 +113,9 @@ namespace YooAsset.Editor
buildParameters.BuildinFileCopyParams = buildinFileCopyParams; buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.ClearBuildCacheFiles = clearBuildCache; buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB; buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance(); buildParameters.BundleEncryptor = CreateBundleEncryptorInstance();
buildParameters.ManifestProcessServices = CreateManifestProcessServicesInstance(); buildParameters.ManifestEncryptor = CreateManifestEncryptorInstance();
buildParameters.ManifestRestoreServices = CreateManifestRestoreServicesInstance(); buildParameters.ManifestDecryptor = CreateManifestDecryptorInstance();
RawFileBuildPipeline pipeline = new RawFileBuildPipeline(); RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true); var buildResult = pipeline.Run(buildParameters, true);

View File

@@ -121,9 +121,9 @@ namespace YooAsset.Editor
buildParameters.CompressOption = compressOption; buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache; buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB; buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance(); buildParameters.BundleEncryptor = CreateBundleEncryptorInstance();
buildParameters.ManifestProcessServices = CreateManifestProcessServicesInstance(); buildParameters.ManifestEncryptor = CreateManifestEncryptorInstance();
buildParameters.ManifestRestoreServices = CreateManifestRestoreServicesInstance(); buildParameters.ManifestDecryptor = CreateManifestDecryptorInstance();
buildParameters.BuiltinShadersBundleName = GetBuiltinShaderBundleName(); buildParameters.BuiltinShadersBundleName = GetBuiltinShaderBundleName();
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline(); ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 1ca8ffceab2965e4c8892f62efa86e90 guid: c40f1ef3e0cc72f49903ce3b3a68d0cb
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@@ -0,0 +1,162 @@
using System.IO;
using UnityEngine;
namespace YooAsset
{
internal class LoadLocalAssetBundleOperation : FCLoadBundleOperation
{
private enum ESteps
{
None,
LoadBundle,
CheckResult,
Done,
}
private readonly PackageBundle _bundle;
private readonly LoadLocalAssetBundleOptions _options;
private AssetBundleCreateRequest _createRequest;
private AssetBundle _assetBundle;
private Stream _loadStream;
private ESteps _steps = ESteps.None;
public bool UnityEngineLoadFailed = false;
public LoadLocalAssetBundleOperation(LoadLocalAssetBundleOptions options)
{
_options = options;
}
internal override void InternalStart()
{
_steps = ESteps.LoadBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBundle)
{
if (_bundle.IsEncrypted == false)
{
LoadFromFile();
}
else
{
var decryptor = _options.Decryptor;
if (decryptor == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_options.CacheName} decryptor is null.";
return;
}
if (decryptor is IBundleOffsetDecryptor offsetDecryptor)
{
LoadFromFileWithOffset(offsetDecryptor);
}
else if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
{
LoadFromMemory(memoryDecryptor);
}
else if (decryptor is IBundleStreamDecryptor streamDecryptor)
{
LoadFromStream(streamDecryptor);
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
return;
}
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForCompletion)
{
// ǿ<>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<DFB3>ע<EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܺ<EFBFBD>ʱ<EFBFBD><CAB1>
YooLogger.Warning("Suspend the main thread to load unity bundle.");
_assetBundle = _createRequest.assetBundle;
}
else
{
if (_createRequest.isDone == false)
return;
_assetBundle = _createRequest.assetBundle;
}
}
if (_assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Unity engine load failed.";
UnityEngineLoadFailed = true;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(_options.FilePath, _options.Bundle, _assetBundle, _loadStream);
}
}
}
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
}
private void LoadFromFile()
{
if (IsWaitForCompletion)
_assetBundle = AssetBundle.LoadFromFile(_options.FilePath);
else
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath);
}
private void LoadFromFileWithOffset(IBundleOffsetDecryptor decryptor)
{
var args = new BundleDecryptArgs();
args.Bundle = _bundle;
args.FilePath = _options.FilePath;
uint offset = decryptor.GetFileOffset(args);
if (IsWaitForCompletion)
_assetBundle = AssetBundle.LoadFromFile(_options.FilePath, 0, offset);
else
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath, 0, offset);
}
private void LoadFromMemory(IBundleMemoryDecryptor decryptor)
{
var args = new BundleDecryptArgs();
args.Bundle = _bundle;
args.FilePath = _options.FilePath;
var binaryData = decryptor.GetDecryptData(args);
if (IsWaitForCompletion)
_assetBundle = AssetBundle.LoadFromMemory(binaryData);
else
_createRequest = AssetBundle.LoadFromMemoryAsync(binaryData);
}
private void LoadFromStream(IBundleStreamDecryptor decryptor)
{
var args = new BundleDecryptArgs();
args.Bundle = _bundle;
args.FilePath = _options.FilePath;
uint bufferSize = decryptor.GetReadBufferSize(args);
_loadStream = decryptor.GetDecryptStream(args);
if (IsWaitForCompletion)
_assetBundle = AssetBundle.LoadFromStream(_loadStream, 0, bufferSize);
else
_createRequest = AssetBundle.LoadFromStreamAsync(_loadStream, 0, bufferSize);
}
}
}

View File

@@ -0,0 +1,30 @@
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的上下文信息
/// </summary>
internal struct LoadLocalAssetBundleOptions
{
/// <summary>
/// 文件缓存名称
/// </summary>
public string CacheName { get; set; }
/// <summary>
/// 资源包信息
/// </summary>
public PackageBundle Bundle { get; set; }
/// <summary>
/// 文件加载路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 解密接口
/// </summary>
public IBundleDecryptor Decryptor { get; set; }
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.IO;
namespace YooAsset
{
internal class LoadLocalRawBundleOperation : FCLoadBundleOperation
{
private enum ESteps
{
None,
LoadBundle,
CheckResult,
Done,
}
protected readonly LoadLocalRawBundleOptions _options;
private RawBundle _rawBundle;
private ESteps _steps = ESteps.None;
public LoadLocalRawBundleOperation(LoadLocalRawBundleOptions options)
{
_options = options;
}
internal override void InternalStart()
{
_steps = ESteps.LoadBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBundle)
{
if (_options.Bundle.IsEncrypted == false)
{
if (IsSupportFileIO(_options.FilePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"FileIO not supported for builtin path : {_options.FilePath}";
return;
}
LoadFromFile();
}
else
{
var decryptor = _options.Decryptor;
if (decryptor == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_options.CacheName} decryptor is null.";
return;
}
if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
{
LoadFromMemory(memoryDecryptor);
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
return;
}
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_rawBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Loaded raw bundle is null.";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new RawBundleResult(_options.FilePath, _options.Bundle, _rawBundle);
}
}
}
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
}
private void LoadFromFile()
{
byte[] data = File.ReadAllBytes(_options.FilePath);
if (data != null)
_rawBundle = new RawBundle(data);
}
private void LoadFromMemory(IBundleMemoryDecryptor decryptor)
{
var args = new BundleDecryptArgs();
args.Bundle = _options.Bundle;
args.FilePath = _options.FilePath;
var binaryData = decryptor.GetDecryptData(args);
if (binaryData != null)
_rawBundle = new RawBundle(binaryData);
}
}
}

View File

@@ -0,0 +1,29 @@
namespace YooAsset
{
/// <summary>
/// 加载 RawBundle 的上下文信息
/// </summary>
internal struct LoadLocalRawBundleOptions
{
/// <summary>
/// 文件缓存名称
/// </summary>
public string CacheName { get; set; }
/// <summary>
/// 资源包信息
/// </summary>
public PackageBundle Bundle { get; set; }
/// <summary>
/// 文件加载路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 解密接口
/// </summary>
public IBundleDecryptor Decryptor { get; set; }
}
}

View File

@@ -0,0 +1,252 @@
using UnityEngine;
namespace YooAsset
{
internal abstract class LoadWebAssetBundleOperation : FCLoadBundleOperation
{
}
internal class LoadWebNormalAssetBundleOperation : LoadWebAssetBundleOperation
{
private enum ESteps
{
None,
DownloadBundle,
CheckResult,
TryAgain,
Done,
}
protected readonly LoadWebAssetBundleOptions _options;
private IDownloadAssetBundleRequest _downloadAssetBundleRequest;
private ESteps _steps = ESteps.None;
// ʧ<><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private int _requestCount = 0;
private float _tryAgainTimer = 0;
private int _failedTryAgain;
public LoadWebNormalAssetBundleOperation(LoadWebAssetBundleOptions options)
{
_options = options;
_failedTryAgain = int.MaxValue; //ע<><EFBFBD><E2A3BA><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>ʧ<EFBFBD>ܺ<EFBFBD><DCBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD><C2B3><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>ɹ<EFBFBD>
}
internal override void InternalStart()
{
_steps = ESteps.DownloadBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadBundle)
{
string url = GetRequestURL();
var args = new DownloadAssetBundleRequestArgs(url, 0, _options.WatchdogTimeout, _options.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCRC);
_downloadAssetBundleRequest = _options.DownloadBackend.CreateAssetBundleRequest(args);
_downloadAssetBundleRequest.SendRequest();
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
Progress = _downloadAssetBundleRequest.DownloadProgress;
if (_downloadAssetBundleRequest.IsDone == false)
return;
if (_downloadAssetBundleRequest.Status == EDownloadRequestStatus.Succeeded)
{
var assetBundle = _downloadAssetBundleRequest.Result;
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Fatal error: dwonload asset bundle is null.";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(_downloadAssetBundleRequest.Url, _options.Bundle, assetBundle, null);
}
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadAssetBundleRequest.Error;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
_downloadAssetBundleRequest.Dispose();
}
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
_steps = ESteps.DownloadBundle;
}
}
}
private string GetRequestURL()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
_requestCount++;
if (_requestCount % 2 == 0)
return _options.FallbackURL;
else
return _options.MainURL;
}
}
internal class LoadWebEncryptedAssetBundleOperation : LoadWebAssetBundleOperation
{
private enum ESteps
{
None,
DownloadData,
CheckResult,
TryAgain,
Done,
}
protected readonly LoadWebAssetBundleOptions _options;
private IDownloadBytesRequest _downloadBytesRequest;
private IBundleMemoryDecryptor _decryptor;
private ESteps _steps = ESteps.None;
// ʧ<><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private int _requestCount = 0;
private float _tryAgainTimer = 0;
private int _failedTryAgain;
public LoadWebEncryptedAssetBundleOperation(LoadWebAssetBundleOptions options)
{
_options = options;
_failedTryAgain = int.MaxValue; //ע<><EFBFBD><E2A3BA><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>ʧ<EFBFBD>ܺ<EFBFBD><DCBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD><C2B3><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>ɹ<EFBFBD>
}
internal override void InternalStart()
{
_steps = ESteps.DownloadData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadData)
{
var decryptor = _options.Decryptor;
if (decryptor == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_options.CacheName} decryptor is null.";
return;
}
if (decryptor is IBundleMemoryDecryptor)
{
string url = GetRequestURL();
_decryptor = decryptor as IBundleMemoryDecryptor;
var args = new DownloadDataRequestArgs(url, 0, _options.WatchdogTimeout);
_downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args);
_downloadBytesRequest.SendRequest();
_steps = ESteps.CheckResult;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
return;
}
}
if (_steps == ESteps.CheckResult)
{
Progress = _downloadBytesRequest.DownloadProgress;
if (_downloadBytesRequest.IsDone == false)
return;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
{
var assetBundle = LoadFromMemory(_decryptor, _downloadBytesRequest.Result);
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Unity engine load failed.";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(_downloadBytesRequest.Url, _options.Bundle, assetBundle, null);
}
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadBytesRequest.Error;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
_downloadBytesRequest.Dispose();
}
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
_steps = ESteps.DownloadData;
}
}
}
private AssetBundle LoadFromMemory(IBundleMemoryDecryptor decryptor, byte[] fileData)
{
var args = new BundleDecryptArgs();
args.Bundle = _options.Bundle;
args.FileData = fileData;
var binaryData = decryptor.GetDecryptData(args);
return AssetBundle.LoadFromMemory(binaryData);
}
private string GetRequestURL()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
_requestCount++;
if (_requestCount % 2 == 0)
return _options.FallbackURL;
else
return _options.MainURL;
}
}
}

View File

@@ -0,0 +1,49 @@
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的上下文信息
/// </summary>
internal struct LoadWebAssetBundleOptions
{
/// <summary>
/// 文件缓存名称
/// </summary>
public string CacheName { get; set; }
/// <summary>
/// 资源包信息
/// </summary>
public PackageBundle Bundle { get; set; }
/// <summary>
/// 请求地址
/// </summary>
public string MainURL { get; set; }
/// <summary>
/// 请求地址
/// </summary>
public string FallbackURL { get; set; }
/// <summary>
/// 解密接口
/// </summary>
public IBundleDecryptor Decryptor { get; set; }
/// <summary>
/// 下载后台接口
/// </summary>
public IDownloadBackend DownloadBackend { get; set; }
/// <summary>
/// 看门狗超时时间
/// </summary>
public int WatchdogTimeout { get; set; }
/// <summary>
/// 禁用Unity的网络缓存
/// </summary>
public bool DisableUnityWebCache { get; set; }
}
}

View File

@@ -7,6 +7,19 @@ namespace YooAsset
{ {
internal struct CacheConfig internal struct CacheConfig
{ {
/// <summary>
/// AssetBundle 解密器
/// </summary>
public IBundleDecryptor AssetBundleDecryptor { get; set; }
/// <summary>
/// RawBundle 解密器
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; set; }
/// <summary>
/// 下载后台接口
/// </summary>
public IDownloadBackend DownloadBackend { get; set; } public IDownloadBackend DownloadBackend { get; set; }
} }

View File

@@ -12,7 +12,7 @@ namespace YooAsset
/// 生成包裹的内置资源目录文件 /// 生成包裹的内置资源目录文件
/// 说明:根据指定目录下的文件生成清单文件。 /// 说明:根据指定目录下的文件生成清单文件。
/// </summary> /// </summary>
public static bool CreateFile(IManifestRestoreServices services, string packageName, string packageDirectory) public static bool CreateFile(IManifestDecryptor decryptor, string packageName, string packageDirectory)
{ {
// 获取资源清单版本 // 获取资源清单版本
string packageVersion; string packageVersion;
@@ -40,7 +40,7 @@ namespace YooAsset
} }
var binaryData = FileUtility.ReadAllBytes(manifestFilePath); var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
packageManifest = PackageManifestTools.DeserializeManifestFromBinary(binaryData, services); packageManifest = PackageManifestTools.DeserializeManifestFromBinary(binaryData, decryptor);
} }
// 获取文件名映射关系 // 获取文件名映射关系

View File

@@ -1,7 +1,4 @@
using System; 
using System.IO;
using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
internal class BFCLoadAssetBundleOperation : FCLoadBundleOperation internal class BFCLoadAssetBundleOperation : FCLoadBundleOperation
@@ -9,16 +6,15 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
LoadAssetBundle, GetEntry,
CheckResult, LoadBundle,
Done, Done,
} }
private readonly BuiltinFileCache _fileCache; private readonly BuiltinFileCache _fileCache;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private AssetBundleCreateRequest _createRequest; private LoadLocalAssetBundleOperation _loadLocalAssetBundleOp;
private AssetBundle _assetBundle; private BuiltinFileCacheEntry _cacheEntry;
private string _filePath;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
public BFCLoadAssetBundleOperation(BuiltinFileCache fileCache, PackageBundle bundle) public BFCLoadAssetBundleOperation(BuiltinFileCache fileCache, PackageBundle bundle)
@@ -28,62 +24,63 @@ namespace YooAsset
} }
internal override void InternalStart() internal override void InternalStart()
{ {
_steps = ESteps.LoadAssetBundle; _steps = ESteps.GetEntry;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadAssetBundle) if (_steps == ESteps.GetEntry)
{ {
var entry = _fileCache.GetEntry(_bundle.BundleGUID); _cacheEntry = _fileCache.GetEntry(_bundle.BundleGUID);
if (entry == null) if (_cacheEntry == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Not found file cache entry: {_bundle.BundleGUID}"; Error = $"Not found file cache entry: {_bundle.BundleGUID}";
return;
}
_filePath = entry.FilePath;
if (IsWaitForCompletion)
_assetBundle = AssetBundle.LoadFromFile(_filePath);
else
_createRequest = AssetBundle.LoadFromFileAsync(_filePath);
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForCompletion)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity bundle.");
_assetBundle = _createRequest.assetBundle;
} }
else else
{ {
if (_createRequest.isDone == false) _steps = ESteps.LoadBundle;
return;
_assetBundle = _createRequest.assetBundle;
} }
} }
if (_assetBundle == null) if (_steps == ESteps.LoadBundle)
{
if (_loadLocalAssetBundleOp == null)
{
var options = new LoadLocalAssetBundleOptions();
options.CacheName = _fileCache.GetType().Name;
options.Bundle = _bundle;
options.FilePath = _cacheEntry.FilePath;
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
_loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options);
_loadLocalAssetBundleOp.StartOperation();
AddChildOperation(_loadLocalAssetBundleOp);
}
if (IsWaitForCompletion)
_loadLocalAssetBundleOp.WaitForCompletion();
_loadLocalAssetBundleOp.UpdateOperation();
if (_loadLocalAssetBundleOp.IsDone == false)
return;
if (_loadLocalAssetBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadLocalAssetBundleOp.BundleResult == null)
throw new YooInternalException("Loaded asset bundle result is null.");
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = _loadLocalAssetBundleOp.BundleResult;
}
else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Failed to load asset bundle : {_bundle.BundleName}"; Error = _loadLocalAssetBundleOp.Error;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(_filePath, _bundle, _assetBundle, null);
} }
} }
} }
@@ -98,12 +95,15 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
LoadRawBundle, GetEntry,
LoadBundle,
Done, Done,
} }
private readonly BuiltinFileCache _fileCache; private readonly BuiltinFileCache _fileCache;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private LoadLocalRawBundleOperation _loadLocalRawBundleOp;
private BuiltinFileCacheEntry _cacheEntry;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
public BFCLoadRawBundleOperation(BuiltinFileCache fileCache, PackageBundle bundle) public BFCLoadRawBundleOperation(BuiltinFileCache fileCache, PackageBundle bundle)
@@ -113,48 +113,61 @@ namespace YooAsset
} }
internal override void InternalStart() internal override void InternalStart()
{ {
_steps = ESteps.LoadRawBundle; _steps = ESteps.GetEntry;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadRawBundle) if (_steps == ESteps.GetEntry)
{ {
var entry = _fileCache.GetEntry(_bundle.BundleGUID); _cacheEntry = _fileCache.GetEntry(_bundle.BundleGUID);
if (entry == null) if (_cacheEntry == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Not found file cache entry: {_bundle.BundleGUID}"; Error = $"Not found file cache entry: {_bundle.BundleGUID}";
}
else
{
_steps = ESteps.LoadBundle;
}
}
if (_steps == ESteps.LoadBundle)
{
if(_loadLocalRawBundleOp == null)
{
var options = new LoadLocalRawBundleOptions();
options.CacheName = _fileCache.GetType().Name;
options.Bundle = _bundle;
options.FilePath = _cacheEntry.FilePath;
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
_loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options);
_loadLocalRawBundleOp.StartOperation();
AddChildOperation(_loadLocalRawBundleOp);
}
if (IsWaitForCompletion)
_loadLocalRawBundleOp.WaitForCompletion();
_loadLocalRawBundleOp.UpdateOperation();
if (_loadLocalRawBundleOp.IsDone == false)
return; return;
}
string filePath = entry.FilePath; if(_loadLocalRawBundleOp.Status == EOperationStatus.Succeeded)
if (IsSupportFileIO(filePath) == false)
{ {
_steps = ESteps.Done; if (_loadLocalRawBundleOp.BundleResult == null)
Status = EOperationStatus.Failed; throw new YooInternalException("Loaded raw bundle result is null.");
Error = $"FileIO not supported for builtin path : {filePath}";
}
else
{
if (File.Exists(filePath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
byte[] data = File.ReadAllBytes(filePath); BundleResult = _loadLocalRawBundleOp.BundleResult;
var rawBundle = new RawBundle(data);
BundleResult = new RawBundleResult(filePath, _bundle, rawBundle);
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Can not found raw bundle file : {filePath}"; Error = _loadLocalRawBundleOp.Error;
}
} }
} }
} }
@@ -163,16 +176,4 @@ namespace YooAsset
ExecuteBatch(); ExecuteBatch();
} }
} }
internal abstract class BFCLoadAssetBundleFromOperation : FCLoadBundleOperation
{
internal abstract AssetBundle LoadFromOffset();
internal abstract AssetBundleCreateRequest LoadFromOffsetAsync();
internal abstract AssetBundle LoadFromMemory();
internal abstract AssetBundleCreateRequest LoadFromMemoryAsync();
internal abstract AssetBundle LoadFromStream();
internal abstract AssetBundleCreateRequest LoadFromStreamAsync();
}
} }

View File

@@ -83,10 +83,19 @@ namespace YooAsset
return operation; return operation;
} }
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options) public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
{
if (options.Bundle.BundleType == (int)EBundleType.VirtualBundle)
{ {
var operation = new EFCLoadVirtualBundleOperation(this, options.Bundle); var operation = new EFCLoadVirtualBundleOperation(this, options.Bundle);
return operation; return operation;
} }
else
{
string error = $"{nameof(EditorFileCache)} not support load bundle type : {options.Bundle.BundleType}";
var operation = new FCLoadBundleErrorOperation(error);
return operation;
}
}
public virtual bool IsCached(string bundleGUID) public virtual bool IsCached(string bundleGUID)
{ {
if (Config.VirtualDownloadMode) if (Config.VirtualDownloadMode)

View File

@@ -1,75 +0,0 @@
using System.IO;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的抽象基类
/// 用户可继承此类实现自定义加载逻辑(如加密解密)
/// </summary>
public abstract class LoadAssetBundleOperation : AsyncOperationBase
{
protected readonly LoadAssetBundleOptions _options;
/// <summary>
/// 加载结果AssetBundle 对象
/// </summary>
public AssetBundle Result { get; protected set; }
/// <summary>
/// 托管流对象(如果使用流加载)
/// 注意:流对象在资源包对象释放的时候会自动释放
/// </summary>
public Stream ManagedStream { get; protected set; }
public LoadAssetBundleOperation(LoadAssetBundleOptions options)
{
_options = options;
}
/// <summary>
/// 后备加载方法:从内存加载 AssetBundle
/// 当主加载方式失败时FileSystem 会调用此方法作为后备机制
/// </summary>
/// <returns>加载成功返回 AssetBundle 对象,失败返回 null</returns>
public abstract AssetBundle LoadFromMemory();
/// <summary>
/// 检查文件路径是否支持 FileIO 读取
/// </summary>
protected static bool IsSupportFileIO(string filePath)
{
if (string.IsNullOrEmpty(filePath))
return true;
if (filePath.StartsWith("jar:") || filePath.StartsWith("content:"))
return false;
return true;
}
}
/// <summary>
/// 立即完成(失败)的 AssetBundle 加载操作
/// 用途:当 Factory 判定某种场景不支持(例如默认实现不支持加密包)时,返回该 Operation
/// </summary>
public sealed class LoadAssetBundleCompleteOperation : LoadAssetBundleOperation
{
private readonly string _error;
public LoadAssetBundleCompleteOperation(string error, LoadAssetBundleOptions options) : base(options)
{
_error = error;
}
internal override void InternalStart()
{
Status = EOperationStatus.Failed;
Error = _error;
}
internal override void InternalUpdate()
{
}
public override AssetBundle LoadFromMemory()
{
return null;
}
}
}

View File

@@ -1,19 +0,0 @@
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的上下文信息
/// </summary>
public struct LoadAssetBundleOptions
{
/// <summary>
/// 文件加载路径
/// </summary>
internal string FileLoadPath { get; set; }
/// <summary>
/// 资源包信息
/// </summary>
internal PackageBundle Bundle { get; set; }
}
}

View File

@@ -1,57 +0,0 @@
using System.Text;
namespace YooAsset
{
/// <summary>
/// 加载 RawBundle 的抽象基类
/// 用户可继承此类实现自定义加载逻辑(如加密解密)
/// </summary>
public abstract class LoadRawBundleOperation : AsyncOperationBase
{
protected readonly LoadRawBundleOptions _options;
/// <summary>
/// 加载结果RawBundle 对象
/// </summary>
public RawBundle Result { get; protected set; }
public LoadRawBundleOperation(LoadRawBundleOptions options)
{
_options = options;
}
/// <summary>
/// 检查文件路径是否支持 FileIO 读取
/// </summary>
protected static bool IsSupportFileIO(string filePath)
{
if (string.IsNullOrEmpty(filePath))
return true;
if (filePath.StartsWith("jar:") || filePath.StartsWith("content:"))
return false;
return true;
}
}
/// <summary>
/// 立即完成(失败)的 RawBundle 加载操作
/// 用途:当 Factory 判定某种场景不支持(例如默认实现不支持加密包)时,返回该 Operation
/// </summary>
public sealed class LoadRawBundleCompleteOperation : LoadRawBundleOperation
{
private readonly string _error;
public LoadRawBundleCompleteOperation(string error, LoadRawBundleOptions options) : base(options)
{
_error = error;
}
internal override void InternalStart()
{
Status = EOperationStatus.Failed;
Error = _error;
}
internal override void InternalUpdate()
{
}
}
}

View File

@@ -1,19 +0,0 @@
namespace YooAsset
{
/// <summary>
/// 加载 RawBundle 的上下文信息
/// </summary>
public struct LoadRawBundleOptions
{
/// <summary>
/// 文件加载路径
/// </summary>
internal string FileLoadPath { get; set; }
/// <summary>
/// 资源包信息
/// </summary>
internal PackageBundle Bundle { get; set; }
}
}

View File

@@ -9,18 +9,18 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
LoadAssetBundle, GetEntry,
CheckResult, LoadBundle,
VerifyFile,
TryFallback, TryFallback,
Done, Done,
} }
private readonly SandboxFileCache _fileCache; private readonly SandboxFileCache _fileCache;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private LoadLocalAssetBundleOperation _loadLocalAssetBundleOp;
private FCVerifyCacheOperation _verifyCacheOp; private FCVerifyCacheOperation _verifyCacheOp;
private AssetBundleCreateRequest _createRequest; private SandboxFileCacheEntry _cacheEntry;
private AssetBundle _assetBundle;
private string _filePath;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
public SFCLoadAssetBundleOperation(SandboxFileCache fileCache, PackageBundle bundle) public SFCLoadAssetBundleOperation(SandboxFileCache fileCache, PackageBundle bundle)
@@ -30,64 +30,75 @@ namespace YooAsset
} }
internal override void InternalStart() internal override void InternalStart()
{ {
_steps = ESteps.LoadAssetBundle; _steps = ESteps.GetEntry;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadAssetBundle) if (_steps == ESteps.GetEntry)
{ {
var entry = _fileCache.GetEntry(_bundle.BundleGUID); _cacheEntry = _fileCache.GetEntry(_bundle.BundleGUID);
if (entry == null) if (_cacheEntry == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Not found file cache entry: {_bundle.BundleGUID}"; Error = $"Not found file cache entry: {_bundle.BundleGUID}";
return;
}
_filePath = entry.DataFilePath;
if (IsWaitForCompletion)
_assetBundle = AssetBundle.LoadFromFile(_filePath);
else
_createRequest = AssetBundle.LoadFromFileAsync(_filePath);
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForCompletion)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity bundle.");
_assetBundle = _createRequest.assetBundle;
} }
else else
{ {
if (_createRequest.isDone == false) _steps = ESteps.LoadBundle;
return;
_assetBundle = _createRequest.assetBundle;
} }
} }
if (_assetBundle == null) if (_steps == ESteps.LoadBundle)
{ {
_steps = ESteps.TryFallback; if (_loadLocalAssetBundleOp == null)
{
var options = new LoadLocalAssetBundleOptions();
options.CacheName = _fileCache.GetType().Name;
options.Bundle = _bundle;
options.FilePath = _cacheEntry.DataFilePath;
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
_loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options);
_loadLocalAssetBundleOp.StartOperation();
AddChildOperation(_loadLocalAssetBundleOp);
}
if (IsWaitForCompletion)
_loadLocalAssetBundleOp.WaitForCompletion();
_loadLocalAssetBundleOp.UpdateOperation();
if (_loadLocalAssetBundleOp.IsDone == false)
return;
if (_loadLocalAssetBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadLocalAssetBundleOp.BundleResult == null)
throw new YooInternalException("Loaded asset bundle result is null.");
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = _loadLocalAssetBundleOp.BundleResult;
}
else
{
// 注意:如果引擎加载失败,需要重新验证文件
if (_loadLocalAssetBundleOp.UnityEngineLoadFailed)
{
_steps = ESteps.VerifyFile;
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeeded; Status = EOperationStatus.Failed;
BundleResult = new AssetBundleResult(_filePath, _bundle, _assetBundle, null); Error = _loadLocalAssetBundleOp.Error;
}
} }
} }
if (_steps == ESteps.TryFallback) if (_steps == ESteps.VerifyFile)
{ {
// 注意当缓存文件的校验等级为Low的时候并不能保证缓存文件的完整性。 // 注意当缓存文件的校验等级为Low的时候并不能保证缓存文件的完整性。
// 说明在AssetBundle文件加载失败的情况下我们需要重新验证文件的完整性 // 说明在AssetBundle文件加载失败的情况下我们需要重新验证文件的完整性
@@ -110,22 +121,7 @@ namespace YooAsset
if (_verifyCacheOp.Status == EOperationStatus.Succeeded) if (_verifyCacheOp.Status == EOperationStatus.Succeeded)
{ {
// 调用后备加载方法 _steps = ESteps.TryFallback;
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
// 说明:大多数情况在首次安装下载资源到沙盒内,游戏过程中切换到后台再回到游戏内有很大概率触发!
AssetBundle assetBundle = LoadFromMemory();
if (assetBundle != null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(_filePath, _bundle, assetBundle, null);
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load asset bundle from memory : {_bundle.BundleName}";
}
} }
else else
{ {
@@ -134,19 +130,70 @@ namespace YooAsset
Error = _verifyCacheOp.Error; Error = _verifyCacheOp.Error;
} }
} }
if (_steps == ESteps.TryFallback)
{
// 调用后备加载方法
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
// 说明:大多数情况在首次安装下载资源到沙盒内,游戏过程中切换到后台再回到游戏内有很大概率触发!
AssetBundle assetBundle;
if (_bundle.IsEncrypted)
{
if (_fileCache.Config.AssetBundleFallbackDecryptor == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(SandboxFileCache)} fallback decryptor is null.";
return;
}
assetBundle = FallbackLoadDecryptAssetBundle(_fileCache.Config.AssetBundleFallbackDecryptor);
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed fallback load encrypted asset bundle: {_bundle.BundleName}";
}
}
else
{
assetBundle = FallbackLoadAssetBundle();
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed fallback load asset bundle: {_bundle.BundleName}";
}
}
if (assetBundle != null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(_cacheEntry.DataFilePath, _bundle, assetBundle, null);
}
}
} }
internal override void InternalWaitForCompletion() internal override void InternalWaitForCompletion()
{ {
ExecuteBatch(); ExecuteBatch();
} }
private AssetBundle LoadFromMemory() private AssetBundle FallbackLoadAssetBundle()
{ {
byte[] fileData = FileUtility.ReadAllBytes(_filePath); byte[] fileData = FileUtility.ReadAllBytes(_cacheEntry.DataFilePath);
if (fileData == null || fileData.Length == 0) if (fileData == null || fileData.Length == 0)
return null; return null;
return AssetBundle.LoadFromMemory(fileData); return AssetBundle.LoadFromMemory(fileData);
} }
private AssetBundle FallbackLoadDecryptAssetBundle(IBundleMemoryDecryptor decryptor)
{
var args = new BundleDecryptArgs();
args.Bundle = _bundle;
args.FilePath = _cacheEntry.DataFilePath;
var binaryData = decryptor.GetDecryptData(args);
return AssetBundle.LoadFromMemory(binaryData);
}
} }
internal class SFCLoadRawBundleOperation : FCLoadBundleOperation internal class SFCLoadRawBundleOperation : FCLoadBundleOperation
@@ -154,12 +201,16 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
LoadRawBundle, GetEntry,
LoadBundle,
Done, Done,
} }
private readonly SandboxFileCache _fileCache; private readonly SandboxFileCache _fileCache;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private LoadLocalRawBundleOperation _loadLocalRawBundleOp;
private SandboxFileCacheEntry _cacheEntry;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
public SFCLoadRawBundleOperation(SandboxFileCache fileCache, PackageBundle bundle) public SFCLoadRawBundleOperation(SandboxFileCache fileCache, PackageBundle bundle)
@@ -169,39 +220,61 @@ namespace YooAsset
} }
internal override void InternalStart() internal override void InternalStart()
{ {
_steps = ESteps.LoadRawBundle; _steps = ESteps.GetEntry;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadRawBundle) if (_steps == ESteps.GetEntry)
{ {
var entry = _fileCache.GetEntry(_bundle.BundleGUID); _cacheEntry = _fileCache.GetEntry(_bundle.BundleGUID);
if (entry == null) if (_cacheEntry == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Not found file cache entry: {_bundle.BundleGUID}"; Error = $"Not found file cache entry: {_bundle.BundleGUID}";
return; }
else
{
_steps = ESteps.LoadBundle;
}
} }
string filePath = entry.DataFilePath; if (_steps == ESteps.LoadBundle)
if (File.Exists(filePath))
{ {
_steps = ESteps.Done; if (_loadLocalRawBundleOp == null)
Status = EOperationStatus.Succeeded; {
var options = new LoadLocalRawBundleOptions();
options.CacheName = _fileCache.GetType().Name;
options.Bundle = _bundle;
options.FilePath = _cacheEntry.DataFilePath;
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
_loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options);
_loadLocalRawBundleOp.StartOperation();
AddChildOperation(_loadLocalRawBundleOp);
}
byte[] data = File.ReadAllBytes(filePath); if (IsWaitForCompletion)
var rawBundle = new RawBundle(data); _loadLocalRawBundleOp.WaitForCompletion();
BundleResult = new RawBundleResult(filePath, _bundle, rawBundle);
_loadLocalRawBundleOp.UpdateOperation();
if (_loadLocalRawBundleOp.IsDone == false)
return;
if (_loadLocalRawBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadLocalRawBundleOp.BundleResult == null)
throw new YooInternalException("Loaded raw bundle result is null.");
BundleResult = _loadLocalRawBundleOp.BundleResult;
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Can not found raw bundle file : {filePath}"; Error = _loadLocalRawBundleOp.Error;
} }
} }
} }
@@ -210,16 +283,4 @@ namespace YooAsset
ExecuteBatch(); ExecuteBatch();
} }
} }
internal abstract class SFCLoadAssetBundleFromOperation : FCLoadBundleOperation
{
internal abstract AssetBundle LoadFromOffset();
internal abstract AssetBundleCreateRequest LoadFromOffsetAsync();
internal abstract AssetBundle LoadFromMemory();
internal abstract AssetBundleCreateRequest LoadFromMemoryAsync();
internal abstract AssetBundle LoadFromStream();
internal abstract AssetBundleCreateRequest LoadFromStreamAsync();
}
} }

View File

@@ -16,6 +16,21 @@ namespace YooAsset
/// 文件校验级别 /// 文件校验级别
/// </summary> /// </summary>
public EFileVerifyLevel FileVerifyLevel { get; set; } public EFileVerifyLevel FileVerifyLevel { get; set; }
/// <summary>
/// AssetBundle 解密器
/// </summary>
public IBundleDecryptor AssetBundleDecryptor { get; set; }
/// <summary>
/// RawBundle 解密器
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; set; }
/// <summary>
/// AssetBundle 备用解密器
/// </summary>
public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; }
} }
private const int HashFolderLength = 2; private const int HashFolderLength = 2;

View File

@@ -6,121 +6,89 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
CreateRequest, GetEntry,
CheckRequest, LoadBundle,
TryAgain,
Done, Done,
} }
private readonly WebRemoteFileCache _fileCache; private readonly WebRemoteFileCache _fileCache;
private readonly LoadBundleOptions _options; private readonly LoadBundleOptions _options;
private IDownloadAssetBundleRequest _downloadAssetBundleRequest; private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
private WebRemoteFileCacheEntry _cacheEntry;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
// 失败重试
private int _requestCount = 0;
private float _tryAgainTimer = 0;
private int _failedTryAgain;
public WRFCLoadAssetBundleOperation(WebRemoteFileCache fileCache, LoadBundleOptions options) public WRFCLoadAssetBundleOperation(WebRemoteFileCache fileCache, LoadBundleOptions options)
{ {
_fileCache = fileCache; _fileCache = fileCache;
_options = options; _options = options;
_failedTryAgain = fileCache.Config.RetryCount;
} }
internal override void InternalStart() internal override void InternalStart()
{ {
_steps = ESteps.CreateRequest; _steps = ESteps.GetEntry;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.CreateRequest) if (_steps == ESteps.GetEntry)
{ {
var entry = _fileCache.GetEntry(_options.Bundle); _cacheEntry = _fileCache.GetEntry(_options.Bundle);
if(entry == null) if (_cacheEntry == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Not found file cache entry: {_options.Bundle.BundleGUID}"; Error = $"Not found file cache entry: {_options.Bundle.BundleGUID}";
return;
}
string url = GetRequestURL(entry);
var args = new DownloadAssetBundleRequestArgs(url, 0, _fileCache.Config.WatchdogTimeout, _fileCache.Config.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCRC);
_downloadAssetBundleRequest = _fileCache.Config.DownloadBackend.CreateAssetBundleRequest(args);
_downloadAssetBundleRequest.SendRequest();
_steps = ESteps.CheckRequest;
}
if (_steps == ESteps.CheckRequest)
{
Progress = _downloadAssetBundleRequest.DownloadProgress;
if (_downloadAssetBundleRequest.IsDone == false)
return;
if (_downloadAssetBundleRequest.Status == EDownloadRequestStatus.Succeeded)
{
var assetBundle = _downloadAssetBundleRequest.Result;
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load asset bundle : {_options.Bundle.BundleName}";
} }
else else
{ {
_steps = ESteps.LoadBundle;
}
}
if (_steps == ESteps.LoadBundle)
{
if (_loadWebAssetBundleOp == null)
{
var options = new LoadWebAssetBundleOptions();
options.CacheName = _fileCache.GetType().Name;
options.Bundle = _options.Bundle;
options.MainURL = _cacheEntry.MainURL;
options.FallbackURL = _cacheEntry.FallbackURL;
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
options.DownloadBackend = _fileCache.Config.DownloadBackend;
options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout;
options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache;
if (_options.Bundle.IsEncrypted)
_loadWebAssetBundleOp = new LoadWebEncryptedAssetBundleOperation(options);
else
_loadWebAssetBundleOp = new LoadWebNormalAssetBundleOperation(options);
_loadWebAssetBundleOp.StartOperation();
AddChildOperation(_loadWebAssetBundleOp);
}
_loadWebAssetBundleOp.UpdateOperation();
if (_loadWebAssetBundleOp.IsDone == false)
return;
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadWebAssetBundleOp.BundleResult == null)
throw new YooInternalException("Loaded asset bundle result is null.");
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeeded; Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(null, _options.Bundle, assetBundle, null); BundleResult = _loadWebAssetBundleOp.BundleResult;
}
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_downloadAssetBundleRequest.Url} Try again.");
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloadAssetBundleRequest.Error; Error = _loadWebAssetBundleOp.Error;
YooLogger.Error(Error);
} }
} }
// 最终释放请求器
_downloadAssetBundleRequest.Dispose();
}
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
_steps = ESteps.CreateRequest;
}
}
}
/// <summary>
/// 获取网络请求地址
/// </summary>
protected string GetRequestURL(WebRemoteFileCacheEntry entry)
{
// 轮流返回请求地址
_requestCount++;
if (_requestCount % 2 == 0)
return entry.FallbackURL;
else
return entry.MainURL;
} }
} }
} }

View File

@@ -7,27 +7,30 @@ namespace YooAsset
{ {
internal struct CacheConfig internal struct CacheConfig
{ {
/// <summary>
/// 看门狗超时时间
/// </summary>
public int WatchdogTimeout { get; set; }
/// <summary> /// <summary>
/// 禁用Unity的网络缓存 /// 禁用Unity的网络缓存
/// </summary> /// </summary>
public bool DisableUnityWebCache { get; set; } public bool DisableUnityWebCache { get; set; }
/// <summary>
/// AssetBundle 解密器
/// </summary>
public IBundleDecryptor AssetBundleDecryptor { get; set; }
/// <summary>
/// 远程服务接口
/// </summary>
public IRemoteServices RemoteServices { get; set; } public IRemoteServices RemoteServices { get; set; }
/// <summary> /// <summary>
/// 下载后台接口 /// 下载后台接口
/// </summary> /// </summary>
public IDownloadBackend DownloadBackend { get; set; } public IDownloadBackend DownloadBackend { get; set; }
/// <summary>
/// 看门狗超时时间
/// </summary>
public int WatchdogTimeout { get; set; }
/// <summary>
/// 失败后重试次数
/// </summary>
public int RetryCount { get; set; }
} }
private readonly Dictionary<string, WebRemoteFileCacheEntry> _caches = new Dictionary<string, WebRemoteFileCacheEntry>(10000); private readonly Dictionary<string, WebRemoteFileCacheEntry> _caches = new Dictionary<string, WebRemoteFileCacheEntry>(10000);
@@ -100,10 +103,19 @@ namespace YooAsset
return operation; return operation;
} }
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options) public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
{
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
{ {
var operation = new WRFCLoadAssetBundleOperation(this, options); var operation = new WRFCLoadAssetBundleOperation(this, options);
return operation; return operation;
} }
else
{
string error = $"{nameof(WebServerFileCache)} not support load bundle type : {options.Bundle.BundleType}";
var operation = new FCLoadBundleErrorOperation(error);
return operation;
}
}
public virtual bool IsCached(string bundleGUID) public virtual bool IsCached(string bundleGUID)
{ {
return true; return true;

View File

@@ -1,110 +1,93 @@
 
namespace YooAsset namespace YooAsset
{ {
internal class WFCLoadAssetBundleOperation : FCLoadBundleOperation internal class WSFCLoadAssetBundleOperation : FCLoadBundleOperation
{ {
private enum ESteps private enum ESteps
{ {
None, None,
CreateRequest, GetEntry,
CheckRequest, LoadBundle,
TryAgain,
Done, Done,
} }
private readonly WebServerFileCache _fileCache; private readonly WebServerFileCache _fileCache;
private readonly LoadBundleOptions _options; private readonly LoadBundleOptions _options;
private IDownloadAssetBundleRequest _downloadAssetBundleRequest; private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
private WebServerFileCacheEntry _cacheEntry;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
// 失败重试 public WSFCLoadAssetBundleOperation(WebServerFileCache fileCache, LoadBundleOptions options)
private float _tryAgainTimer = 0;
private int _failedTryAgain;
public WFCLoadAssetBundleOperation(WebServerFileCache fileCache, LoadBundleOptions options)
{ {
_fileCache = fileCache; _fileCache = fileCache;
_options = options; _options = options;
_failedTryAgain = fileCache.Config.RetryCount;
} }
internal override void InternalStart() internal override void InternalStart()
{ {
_steps = ESteps.CreateRequest; _steps = ESteps.GetEntry;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.CreateRequest) if (_steps == ESteps.GetEntry)
{ {
var entry = _fileCache.GetEntry(_options.Bundle.BundleGUID); _cacheEntry = _fileCache.GetEntry(_options.Bundle.BundleGUID);
if (entry == null) if (_cacheEntry == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Not found file cache entry: {_options.Bundle.BundleGUID}"; Error = $"Not found file cache entry: {_options.Bundle.BundleGUID}";
return;
}
string url = DownloadSystemTools.ToLocalUrl(entry.FilePath);
var args = new DownloadAssetBundleRequestArgs(url, 0, _fileCache.Config.WatchdogTimeout, _fileCache.Config.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCRC);
_downloadAssetBundleRequest = _fileCache.Config.DownloadBackend.CreateAssetBundleRequest(args);
_downloadAssetBundleRequest.SendRequest();
_steps = ESteps.CheckRequest;
}
if (_steps == ESteps.CheckRequest)
{
Progress = _downloadAssetBundleRequest.DownloadProgress;
if (_downloadAssetBundleRequest.IsDone == false)
return;
if (_downloadAssetBundleRequest.Status == EDownloadRequestStatus.Succeeded)
{
var assetBundle = _downloadAssetBundleRequest.Result;
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load asset bundle : {_options.Bundle.BundleName}";
} }
else else
{ {
_steps = ESteps.LoadBundle;
}
}
if (_steps == ESteps.LoadBundle)
{
if (_loadWebAssetBundleOp == null)
{
string url = DownloadSystemTools.ToLocalUrl(_cacheEntry.FilePath);
var options = new LoadWebAssetBundleOptions();
options.CacheName = _fileCache.GetType().Name;
options.Bundle = _options.Bundle;
options.MainURL = url;
options.FallbackURL = url;
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
options.DownloadBackend = _fileCache.Config.DownloadBackend;
options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout;
options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache;
if (_options.Bundle.IsEncrypted)
_loadWebAssetBundleOp = new LoadWebEncryptedAssetBundleOperation(options);
else
_loadWebAssetBundleOp = new LoadWebNormalAssetBundleOperation(options);
_loadWebAssetBundleOp.StartOperation();
AddChildOperation(_loadWebAssetBundleOp);
}
_loadWebAssetBundleOp.UpdateOperation();
if (_loadWebAssetBundleOp.IsDone == false)
return;
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadWebAssetBundleOp.BundleResult == null)
throw new YooInternalException("Loaded asset bundle result is null.");
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeeded; Status = EOperationStatus.Succeeded;
BundleResult = new AssetBundleResult(null, _options.Bundle, assetBundle, null); BundleResult = _loadWebAssetBundleOp.BundleResult;
}
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_downloadAssetBundleRequest.Url} Try again.");
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloadAssetBundleRequest.Error; Error = _loadWebAssetBundleOp.Error;
YooLogger.Error(Error);
}
}
// 最终释放请求器
_downloadAssetBundleRequest.Dispose();
}
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
_steps = ESteps.CreateRequest;
} }
} }
} }

View File

@@ -7,25 +7,25 @@ namespace YooAsset
{ {
internal struct CacheConfig internal struct CacheConfig
{ {
/// <summary>
/// 禁用Unity的网络缓存
/// </summary>
public bool DisableUnityWebCache { get; set; }
/// <summary>
/// 下载后台接口
/// </summary>
public IDownloadBackend DownloadBackend { get; set; }
/// <summary> /// <summary>
/// 看门狗超时时间 /// 看门狗超时时间
/// </summary> /// </summary>
public int WatchdogTimeout { get; set; } public int WatchdogTimeout { get; set; }
/// <summary> /// <summary>
/// 失败后重试次数 /// 禁用Unity的网络缓存
/// </summary> /// </summary>
public int RetryCount { get; set; } public bool DisableUnityWebCache { get; set; }
/// <summary>
/// AssetBundle 解密器
/// </summary>
public IBundleDecryptor AssetBundleDecryptor { get; set; }
/// <summary>
/// 下载后台接口
/// </summary>
public IDownloadBackend DownloadBackend { get; set; }
} }
private readonly Dictionary<string, WebServerFileCacheEntry> _caches = new Dictionary<string, WebServerFileCacheEntry>(10000); private readonly Dictionary<string, WebServerFileCacheEntry> _caches = new Dictionary<string, WebServerFileCacheEntry>(10000);
@@ -99,9 +99,18 @@ namespace YooAsset
} }
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options) public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
{ {
var operation = new WFCLoadAssetBundleOperation(this, options); if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
{
var operation = new WSFCLoadAssetBundleOperation(this, options);
return operation; return operation;
} }
else
{
string error = $"{nameof(WebServerFileCache)} not support load bundle type : {options.Bundle.BundleType}";
var operation = new FCLoadBundleErrorOperation(error);
return operation;
}
}
public virtual bool IsCached(string bundleGUID) public virtual bool IsCached(string bundleGUID)
{ {
return _caches.ContainsKey(bundleGUID); return _caches.ContainsKey(bundleGUID);

View File

@@ -2,6 +2,7 @@ using System;
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
/*
namespace YooAsset namespace YooAsset
{ {
/// <summary> /// <summary>
@@ -96,72 +97,8 @@ namespace YooAsset
/// </summary> /// </summary>
public abstract class DefaultLoadAssetBundleFromOffsetOperation : LoadAssetBundleOperation public abstract class DefaultLoadAssetBundleFromOffsetOperation : LoadAssetBundleOperation
{ {
private enum ESteps protected DefaultLoadAssetBundleFromOffsetOperation(LoadAssetBundleOptions options) : base(options)
{ {
None,
LoadAssetBundle,
CheckResult,
Done,
}
private AssetBundleCreateRequest _createRequest;
private ESteps _steps = ESteps.None;
public DefaultLoadAssetBundleFromOffsetOperation(LoadAssetBundleOptions options) : base(options) { }
internal override void InternalStart()
{
_steps = ESteps.LoadAssetBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadAssetBundle)
{
ulong offset = GetFileOffset();
if (IsWaitForCompletion)
Result = AssetBundle.LoadFromFile(_options.FileLoadPath, 0, offset);
else
_createRequest = AssetBundle.LoadFromFileAsync(_options.FileLoadPath, 0, offset);
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForCompletion)
{
// 强制挂起主线程(注意:该操作会很耗时)
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.Failed;
Error = $"Failed to load asset bundle file : {_options.Bundle.BundleName}";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
}
}
}
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
} }
/// <summary> /// <summary>
@@ -209,9 +146,6 @@ namespace YooAsset
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckFilePath) if (_steps == ESteps.CheckFilePath)
{ {
string filePath = _options.FileLoadPath; string filePath = _options.FileLoadPath;
@@ -246,41 +180,6 @@ namespace YooAsset
_steps = ESteps.CheckResult; _steps = ESteps.CheckResult;
} }
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForCompletion)
{
// 强制挂起主线程(注意:该操作会很耗时)
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.Failed;
Error = $"Failed to load asset bundle file : {_options.Bundle.BundleName}";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
}
}
}
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
} }
/// <summary> /// <summary>
@@ -313,20 +212,13 @@ namespace YooAsset
CheckResult, CheckResult,
Done, Done,
} }
private AssetBundleCreateRequest _createRequest;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
protected DefaultLoadAssetBundleFromStreamOperation(LoadAssetBundleOptions options) : base(options)
public DefaultLoadAssetBundleFromStreamOperation(LoadAssetBundleOptions options) : base(options) { }
internal override void InternalStart()
{ {
_steps = ESteps.CheckFilePath;
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckFilePath) if (_steps == ESteps.CheckFilePath)
{ {
string filePath = _options.FileLoadPath; string filePath = _options.FileLoadPath;
@@ -341,66 +233,8 @@ namespace YooAsset
_steps = ESteps.LoadAssetBundle; _steps = ESteps.LoadAssetBundle;
} }
} }
if (_steps == ESteps.LoadAssetBundle)
{
ManagedStream = CreateManagedFileStream();
uint bufferSize = GetManagedReadBufferSize();
if (IsWaitForCompletion)
Result = AssetBundle.LoadFromStream(ManagedStream, 0, bufferSize);
else
_createRequest = AssetBundle.LoadFromStreamAsync(ManagedStream, 0, bufferSize);
_steps = ESteps.CheckResult;
} }
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForCompletion)
{
// 强制挂起主线程(注意:该操作会很耗时)
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.Failed;
Error = $"Failed to load asset bundle file : {_options.Bundle.BundleName}";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeeded;
}
}
}
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
}
/// <summary>
/// 获取文件流
/// </summary>
protected abstract FileStream CreateManagedFileStream();
/// <summary>
/// 获取缓冲池大小
/// </summary>
protected abstract uint GetManagedReadBufferSize();
/// <summary> /// <summary>
/// 文件数据解密 /// 文件数据解密
/// </summary> /// </summary>
@@ -417,3 +251,4 @@ namespace YooAsset
} }
} }
} }
*/

View File

@@ -1,5 +1,6 @@
using System.IO; using System.IO;
/*
namespace YooAsset namespace YooAsset
{ {
/// <summary> /// <summary>
@@ -25,24 +26,6 @@ namespace YooAsset
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckFilePath)
{
string filePath = _options.FileLoadPath;
if (IsSupportFileIO(filePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"FileIO not supported for builtin path : {filePath}";
}
else
{
_steps = ESteps.LoadRawBundle;
}
}
if (_steps == ESteps.LoadRawBundle) if (_steps == ESteps.LoadRawBundle)
{ {
string filePath = _options.FileLoadPath; string filePath = _options.FileLoadPath;
@@ -61,10 +44,6 @@ namespace YooAsset
} }
} }
} }
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
}
} }
/// <summary> /// <summary>
@@ -90,24 +69,6 @@ namespace YooAsset
} }
internal override void InternalUpdate() internal override void InternalUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckFilePath)
{
string filePath = _options.FileLoadPath;
if (IsSupportFileIO(filePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"FileIO not supported for builtin path : {filePath}";
}
else
{
_steps = ESteps.LoadRawBundle;
}
}
if (_steps == ESteps.LoadRawBundle) if (_steps == ESteps.LoadRawBundle)
{ {
string filePath = _options.FileLoadPath; string filePath = _options.FileLoadPath;
@@ -136,10 +97,6 @@ namespace YooAsset
} }
} }
} }
internal override void InternalWaitForCompletion()
{
ExecuteBatch();
}
/// <summary> /// <summary>
/// 文件数据解密 /// 文件数据解密
@@ -147,3 +104,4 @@ namespace YooAsset
protected abstract byte[] DecryptData(byte[] data); protected abstract byte[] DecryptData(byte[] data);
} }
} }
*/

View File

@@ -1,5 +1,6 @@
using UnityEngine; using UnityEngine;
/*
namespace YooAsset namespace YooAsset
{ {
/// <summary> /// <summary>
@@ -247,3 +248,4 @@ namespace YooAsset
} }
} }
} }
*/

View File

@@ -96,7 +96,7 @@ namespace YooAsset
/// <param name="packageRoot">文件系统的根目录</param> /// <param name="packageRoot">文件系统的根目录</param>
public static FileSystemParameters CreateDefaultCacheFileSystemParameters(IRemoteServices remoteServices, string packageRoot = null) public static FileSystemParameters CreateDefaultCacheFileSystemParameters(IRemoteServices remoteServices, string packageRoot = null)
{ {
string fileSystemClass = typeof(CacheFileSystem).FullName; string fileSystemClass = typeof(SandboxFileSystem).FullName;
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot); var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices); fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
return fileSystemParams; return fileSystemParams;

View File

@@ -24,25 +24,25 @@ namespace YooAsset
public const string REMOTE_SERVICES = "REMOTE_SERVICES"; public const string REMOTE_SERVICES = "REMOTE_SERVICES";
/// <summary> /// <summary>
/// 资源清单服务类 <see cref=IManifestRestoreServices> /// AssetBundle 解密器 <see cref=IBundleDecryptor>
/// </summary> /// </summary>
public const string MANIFEST_RESTORE_SERVICES = "MANIFEST_RESTORE_SERVICES"; public const string ASSETBUNDLE_DECRYPTOR = "ASSETBUNDLE_DECRYPTOR";
/// <summary> /// <summary>
/// 禁用Unity的网络缓存 <see cref=bool> /// 禁用Unity的网络缓存 <see cref=bool>
/// </summary> /// </summary>
public const string DISABLE_UNITY_WEB_CACHE = "DISABLE_UNITY_WEB_CACHE"; public const string DISABLE_UNITY_WEB_CACHE = "DISABLE_UNITY_WEB_CACHE";
/// <summary>
/// 禁用边玩边下机制 <see cref=bool>
/// </summary>
public const string DISABLE_ONDEMAND_DOWNLOAD = "DISABLE_ONDEMAND_DOWNLOAD";
/// <summary> /// <summary>
/// UnityWebRequest 创建委托 <see cref=UnityWebRequestCreator> /// UnityWebRequest 创建委托 <see cref=UnityWebRequestCreator>
/// </summary> /// </summary>
public const string UNITY_WEB_REQUEST_CREATOR = "UNITY_WEB_REQUEST_CREATOR"; public const string UNITY_WEB_REQUEST_CREATOR = "UNITY_WEB_REQUEST_CREATOR";
/// <summary>
/// 禁用边玩边下机制 <see cref=bool>
/// </summary>
public const string DOWNLOAD_DISABLE_ONDEMAND = "DOWNLOAD_DISABLE_ONDEMAND";
/// <summary> /// <summary>
/// 下载后台接口 <see cref=IDownloadBackend> /// 下载后台接口 <see cref=IDownloadBackend>
/// </summary> /// </summary>
@@ -66,12 +66,12 @@ namespace YooAsset
/// <summary> /// <summary>
/// 启用断点续传的最小尺寸 <see cref=long> /// 启用断点续传的最小尺寸 <see cref=long>
/// </summary> /// </summary>
public const string RESUME_DOWNLOAD_MINMUM_SIZE = "RESUME_DOWNLOAD_MINMUM_SIZE"; public const string DOWNLOAD_RESUME_MINMUM_SIZE = "DOWNLOAD_RESUME_MINMUM_SIZE";
/// <summary> /// <summary>
/// 断点续传下载器关注的错误码 <see cref=List<long>> /// 断点续传下载器关注的错误码 <see cref=List<long>>
/// </summary> /// </summary>
public const string RESUME_DOWNLOAD_RESPONSE_CODES = "RESUME_DOWNLOAD_RESPONSE_CODES"; public const string DOWNLOAD_RESUME_RESPONSE_CODES = "DOWNLOAD_RESUME_RESPONSE_CODES";
/// <summary> /// <summary>
/// 模拟WebGL平台模式 <see cref=bool> /// 模拟WebGL平台模式 <see cref=bool>
@@ -112,5 +112,20 @@ namespace YooAsset
/// 解压文件系统的根目录 <see cref=string> /// 解压文件系统的根目录 <see cref=string>
/// </summary> /// </summary>
public const string UNPACK_FILE_SYSTEM_ROOT = "UNPACK_FILE_SYSTEM_ROOT"; public const string UNPACK_FILE_SYSTEM_ROOT = "UNPACK_FILE_SYSTEM_ROOT";
/// <summary>
/// RawBundle 解密器 <see cref=IBundleDecryptor>
/// </summary>
public const string RAWBUNDLE_DECRYPTOR = "RAWBUNDLE_DECRYPTOR";
/// <summary>
/// AssetBundle 备用解密器 <see cref=IBundleMemoryDecryptor>
/// </summary>
public const string ASSETBUNDLE_FALLBACK_DECRYPTOR = "ASSETBUNDLE_FALLBACK_DECRYPTOR";
/// <summary>
/// 资源清单解密器 <see cref=IManifestDecryptor>
/// </summary>
public const string MANIFEST_DECRYPTOR = "MANIFEST_DECRYPTOR";
} }
} }

View File

@@ -93,9 +93,24 @@ namespace YooAsset
public int UnpackMaxRequestPerFrame { private set; get; } public int UnpackMaxRequestPerFrame { private set; get; }
/// <summary> /// <summary>
/// 自定义参数:资源清单服务类 /// 自定义参数:AssetBundle 解密器
/// </summary> /// </summary>
public IManifestRestoreServices ManifestRestoreServices { private set; get; } public IBundleDecryptor AssetBundleDecryptor { get; set; }
/// <summary>
/// 自定义参数RawBundle 解密器
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; set; }
/// <summary>
/// 自定义参数AssetBundle 备用解密器
/// </summary>
public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; }
/// <summary>
/// 自定义参数:资源清单解密器
/// </summary>
public IManifestDecryptor ManifestDecryptor { private set; get; }
#endregion #endregion
@@ -190,9 +205,21 @@ namespace YooAsset
// 限制在合理范围内1-32 // 限制在合理范围内1-32
UnpackMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, 32); UnpackMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, 32);
} }
else if (name == FileSystemParametersDefine.MANIFEST_RESTORE_SERVICES) else if (name == FileSystemParametersDefine.ASSETBUNDLE_DECRYPTOR)
{ {
ManifestRestoreServices = (IManifestRestoreServices)value; AssetBundleDecryptor = (IBundleDecryptor)value;
}
else if (name == FileSystemParametersDefine.RAWBUNDLE_DECRYPTOR)
{
RawBundleDecryptor = (IBundleDecryptor)value;
}
else if (name == FileSystemParametersDefine.ASSETBUNDLE_FALLBACK_DECRYPTOR)
{
AssetBundleFallbackDecryptor = (IBundleMemoryDecryptor)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_DECRYPTOR)
{
ManifestDecryptor = (IManifestDecryptor)value;
} }
else else
{ {
@@ -218,13 +245,15 @@ namespace YooAsset
unpackRoot = GetDefaultUnpackCacheRoot(packageName); unpackRoot = GetDefaultUnpackCacheRoot(packageName);
else else
unpackRoot = UnpackFileSystemRoot; unpackRoot = UnpackFileSystemRoot;
_unpackManifestFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemConstants.UnpackManifestFilesFolderName); _unpackManifestFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackManifestFilesFolderName);
_unpackBundleFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemConstants.UnpackBundleFilesFolderName); _unpackBundleFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackBundleFilesFolderName);
_unpackTempFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemConstants.UnpackTempFilesFolderName); _unpackTempFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackTempFilesFolderName);
// 创建内置缓存对象 // 创建内置缓存对象
{ {
var cacheConfig = new BuiltinFileCache.CacheConfig(); var cacheConfig = new BuiltinFileCache.CacheConfig();
cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor;
cacheConfig.RawBundleDecryptor = RawBundleDecryptor;
cacheConfig.DownloadBackend = DownloadBackend; cacheConfig.DownloadBackend = DownloadBackend;
BuiltinFileCache = new BuiltinFileCache(packageName, _packageRoot, cacheConfig); BuiltinFileCache = new BuiltinFileCache(packageName, _packageRoot, cacheConfig);
} }
@@ -232,8 +261,11 @@ namespace YooAsset
// 创建沙盒缓存对象 // 创建沙盒缓存对象
{ {
var cacheConfig = new SandboxFileCache.CacheConfig(); var cacheConfig = new SandboxFileCache.CacheConfig();
cacheConfig.FileVerifyLevel = FileVerifyLevel;
cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency; cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency;
cacheConfig.FileVerifyLevel = FileVerifyLevel;
cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor;
cacheConfig.RawBundleDecryptor = RawBundleDecryptor;
cacheConfig.AssetBundleFallbackDecryptor = AssetBundleFallbackDecryptor;
UnpackFileCache = new SandboxFileCache(packageName, _unpackBundleFilesRoot, cacheConfig); UnpackFileCache = new SandboxFileCache(packageName, _unpackBundleFilesRoot, cacheConfig);
} }
} }
@@ -341,7 +373,7 @@ namespace YooAsset
} }
public string GetSandboxAppFootPrintFilePath() public string GetSandboxAppFootPrintFilePath()
{ {
return PathUtility.Combine(_unpackManifestFilesRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName); return PathUtility.Combine(_unpackManifestFilesRoot, SandboxFileSystemDefine.AppFootPrintFileName);
} }
/// <summary> /// <summary>

View File

@@ -1,7 +1,7 @@
namespace YooAsset namespace YooAsset
{ {
internal class BuiltinFileSystemConstants internal class BuiltinFileSystemDefine
{ {
/// <summary> /// <summary>
/// 解压清单文件的文件夹名称 /// 解压清单文件的文件夹名称

View File

@@ -1,4 +1,4 @@

namespace YooAsset namespace YooAsset
{ {
internal class BFSInitializeOperation : FSInitializeOperation internal class BFSInitializeOperation : FSInitializeOperation
@@ -45,7 +45,7 @@ namespace YooAsset
var appFootprint = new ApplicationFootprint(footprintFilePath); var appFootprint = new ApplicationFootprint(footprintFilePath);
appFootprint.Load(_fileSystem.PackageName); appFootprint.Load(_fileSystem.PackageName);
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˮӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>״δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ // 如果水印发生变化,则说明覆盖安装后首次打开游戏
if (appFootprint.IsDirty()) if (appFootprint.IsDirty())
{ {
if (_fileSystem.InstallClearMode == EInstallCleanupMode.None) if (_fileSystem.InstallClearMode == EInstallCleanupMode.None)
@@ -163,8 +163,8 @@ namespace YooAsset
if (_steps == ESteps.CreateScheduler) if (_steps == ESteps.CreateScheduler)
{ {
// ע<EFBFBD><EFBFBD>: <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9>ʼ<EFBFBD><CABC>ʧ<EFBFBD>ܺ<EFBFBD><DCBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // 注意: 下载调度中心在最后一步创建,防止初始化失败后残留任务。
// ע<EFBFBD><EFBFBD>: <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD> // 注意: 下载调度中心作为独立任务运行!
if (_fileSystem.UnpackScheduler == null) if (_fileSystem.UnpackScheduler == null)
{ {
var schedulerConfig = new DownloadSchedulerOperation.SchedulerConfig(); var schedulerConfig = new DownloadSchedulerOperation.SchedulerConfig();

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
namespace YooAsset namespace YooAsset
@@ -77,7 +77,7 @@ namespace YooAsset
{ {
if (_webFileRequestOp == null) if (_webFileRequestOp == null)
{ {
//TODO <EFBFBD>Ž<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ijЩ<EFBFBD><EFBFBD>׿<EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ף<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>UnityWebRequest<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> //TODO 团结引擎在某些安卓机型红米通过UnityWebRequest拷贝包内文件会小概率失败需要借助其它方式来拷贝包内文件。
string url = DownloadSystemTools.ToLocalUrl(_sourceFilePath); string url = DownloadSystemTools.ToLocalUrl(_sourceFilePath);
var args = new DownloadFileRequestArgs(url, _destFilePath, 60, 0); var args = new DownloadFileRequestArgs(url, _destFilePath, 60, 0);
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args); _webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
@@ -102,7 +102,7 @@ namespace YooAsset
} }
internal override void InternalWaitForCompletion() internal override void InternalWaitForCompletion()
{ {
//TODO <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD>ò<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<EFBFBD> //TODO 等待解压本地文件完毕,该操作会挂起主线程!
ExecuteUntilComplete(); ExecuteUntilComplete();
} }
} }

View File

@@ -120,7 +120,7 @@ namespace YooAsset
if (string.IsNullOrEmpty(destRoot)) if (string.IsNullOrEmpty(destRoot))
{ {
string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot(); string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot();
destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, DefaultCacheFileSystemDefine.ManifestFilesFolderName); destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, SandboxFileSystemDefine.ManifestFilesFolderName);
} }
return destRoot; return destRoot;
} }

View File

@@ -102,7 +102,7 @@ namespace YooAsset
{ {
if (_deserializer == null) if (_deserializer == null)
{ {
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestRestoreServices, _fileData); _deserializer = new DeserializeManifestOperation(_fileSystem.ManifestDecryptor, _fileData);
_deserializer.StartOperation(); _deserializer.StartOperation();
AddChildOperation(_deserializer); AddChildOperation(_deserializer);
} }

View File

@@ -13,7 +13,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _tempFilePath; private readonly string _tempFilePath;
private bool _enableResume = false; private bool _enableResume = false;
private long _fileOriginLength = 0; private long _fileOriginLength = 0;
@@ -21,7 +21,7 @@ namespace YooAsset
private FCWriteCacheOperation _writeCacheOp; private FCWriteCacheOperation _writeCacheOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal DownloadAndCacheFileOperation(CacheFileSystem fileSystem, PackageBundle bundle, string url) : base(bundle, url) internal DownloadAndCacheFileOperation(SandboxFileSystem fileSystem, PackageBundle bundle, string url) : base(bundle, url)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_tempFilePath = _fileSystem.GetTempFilePath(bundle); _tempFilePath = _fileSystem.GetTempFilePath(bundle);

View File

@@ -12,7 +12,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _packageVersion; private readonly string _packageVersion;
private readonly int _timeout; private readonly int _timeout;
private IDownloadFileRequest _webFileRequestOp; private IDownloadFileRequest _webFileRequestOp;
@@ -20,7 +20,7 @@ namespace YooAsset
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal DownloadPackageHashOperation(CacheFileSystem fileSystem, string packageVersion, int timeout) internal DownloadPackageHashOperation(SandboxFileSystem fileSystem, string packageVersion, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_packageVersion = packageVersion; _packageVersion = packageVersion;

View File

@@ -12,7 +12,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _packageVersion; private readonly string _packageVersion;
private readonly int _timeout; private readonly int _timeout;
private IDownloadFileRequest _webFileRequestOp; private IDownloadFileRequest _webFileRequestOp;
@@ -20,7 +20,7 @@ namespace YooAsset
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal DownloadPackageManifestOperation(CacheFileSystem fileSystem, string packageVersion, int timeout) internal DownloadPackageManifestOperation(SandboxFileSystem fileSystem, string packageVersion, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_packageVersion = packageVersion; _packageVersion = packageVersion;

View File

@@ -13,13 +13,13 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _sourceFilePath; private readonly string _sourceFilePath;
private readonly string _tempFilePath; private readonly string _tempFilePath;
private FCWriteCacheOperation _bundleCacheOp; private FCWriteCacheOperation _bundleCacheOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal ImportAndCacheFileOperation(CacheFileSystem fileSystem, PackageBundle bundle, string sourceFilePath) : base(bundle, sourceFilePath) internal ImportAndCacheFileOperation(SandboxFileSystem fileSystem, PackageBundle bundle, string sourceFilePath) : base(bundle, sourceFilePath)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_sourceFilePath = sourceFilePath; _sourceFilePath = sourceFilePath;

View File

@@ -11,7 +11,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _packageVersion; private readonly string _packageVersion;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
@@ -21,7 +21,7 @@ namespace YooAsset
public string PackageHash { private set; get; } public string PackageHash { private set; get; }
internal LoadCachePackageHashOperation(CacheFileSystem fileSystem, string packageVersion) internal LoadCachePackageHashOperation(SandboxFileSystem fileSystem, string packageVersion)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_packageVersion = packageVersion; _packageVersion = packageVersion;

View File

@@ -13,7 +13,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _packageVersion; private readonly string _packageVersion;
private readonly string _packageHash; private readonly string _packageHash;
private DeserializeManifestOperation _deserializer; private DeserializeManifestOperation _deserializer;
@@ -26,7 +26,7 @@ namespace YooAsset
public PackageManifest Manifest { private set; get; } public PackageManifest Manifest { private set; get; }
internal LoadCachePackageManifestOperation(CacheFileSystem fileSystem, string packageVersion, string packageHash) internal LoadCachePackageManifestOperation(SandboxFileSystem fileSystem, string packageVersion, string packageHash)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_packageVersion = packageVersion; _packageVersion = packageVersion;
@@ -75,7 +75,7 @@ namespace YooAsset
{ {
if (_deserializer == null) if (_deserializer == null)
{ {
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestRestoreServices, _fileData); _deserializer = new DeserializeManifestOperation(_fileSystem.ManifestDecryptor, _fileData);
_deserializer.StartOperation(); _deserializer.StartOperation();
AddChildOperation(_deserializer); AddChildOperation(_deserializer);
} }

View File

@@ -10,7 +10,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly bool _appendTimeTicks; private readonly bool _appendTimeTicks;
private readonly int _timeout; private readonly int _timeout;
private IDownloadTextRequest _webTextRequestOp; private IDownloadTextRequest _webTextRequestOp;
@@ -23,7 +23,7 @@ namespace YooAsset
internal string PackageVersion { set; get; } internal string PackageVersion { set; get; }
internal RequestRemotePackageVersionOperation(CacheFileSystem fileSystem, bool appendTimeTicks, int timeout) internal RequestRemotePackageVersionOperation(SandboxFileSystem fileSystem, bool appendTimeTicks, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks; _appendTimeTicks = appendTimeTicks;

View File

@@ -3,7 +3,7 @@ using System.IO;
namespace YooAsset namespace YooAsset
{ {
internal class CFSClearCacheOperation : FSClearCacheOperation internal class SFSClearCacheOperation : FSClearCacheOperation
{ {
private enum ESteps private enum ESteps
{ {
@@ -12,12 +12,12 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly ClearCacheOptions _options; private readonly ClearCacheOptions _options;
private FCClearCacheOperation _clearCacheOp; private FCClearCacheOperation _clearCacheOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSClearCacheOperation(CacheFileSystem fileSystem, ClearCacheOptions options) internal SFSClearCacheOperation(SandboxFileSystem fileSystem, ClearCacheOptions options)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_options = options; _options = options;
@@ -68,10 +68,10 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSClearAllCacheManifestOperation(CacheFileSystem fileSystem) internal CFSClearAllCacheManifestOperation(SandboxFileSystem fileSystem)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
@@ -96,7 +96,7 @@ namespace YooAsset
foreach (FileInfo fileInfo in directoryInfo.GetFiles()) foreach (FileInfo fileInfo in directoryInfo.GetFiles())
{ {
string fileName = fileInfo.Name; string fileName = fileInfo.Name;
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName) if (fileName == SandboxFileSystemDefine.AppFootPrintFileName)
continue; continue;
fileInfo.Delete(); fileInfo.Delete();
@@ -126,11 +126,11 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly PackageManifest _manifest; private readonly PackageManifest _manifest;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSClearUnusedCacheManifestOperation(CacheFileSystem fileSystem, PackageManifest manifest) internal CFSClearUnusedCacheManifestOperation(SandboxFileSystem fileSystem, PackageManifest manifest)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_manifest = manifest; _manifest = manifest;
@@ -173,7 +173,7 @@ namespace YooAsset
foreach (FileInfo fileInfo in directoryInfo.GetFiles()) foreach (FileInfo fileInfo in directoryInfo.GetFiles())
{ {
string fileName = fileInfo.Name; string fileName = fileInfo.Name;
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName) if (fileName == SandboxFileSystemDefine.AppFootPrintFileName)
continue; continue;
if (fileName == activeManifestFileName || fileName == activeHashFileName) if (fileName == activeManifestFileName || fileName == activeHashFileName)
continue; continue;

View File

@@ -2,7 +2,7 @@ using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
internal class CFSDownloadFileOperation : FSDownloadFileOperation internal class SFSDownloadFileOperation : FSDownloadFileOperation
{ {
protected enum ESteps protected enum ESteps
{ {
@@ -13,7 +13,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly DownloadFileOptions _options; private readonly DownloadFileOptions _options;
private DownloadFileBaseOperation _downloadFileOp; private DownloadFileBaseOperation _downloadFileOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
@@ -23,7 +23,7 @@ namespace YooAsset
private float _tryAgainTimer = 0; private float _tryAgainTimer = 0;
private int _failedTryAgain; private int _failedTryAgain;
internal CFSDownloadFileOperation(CacheFileSystem fileSystem, DownloadFileOptions options) : base(options.Bundle) internal SFSDownloadFileOperation(SandboxFileSystem fileSystem, DownloadFileOptions options) : base(options.Bundle)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_options = options; _options = options;

View File

@@ -1,7 +1,7 @@
namespace YooAsset namespace YooAsset
{ {
internal class CFSInitializeOperation : FSInitializeOperation internal class SFSInitializeOperation : FSInitializeOperation
{ {
private enum ESteps private enum ESteps
{ {
@@ -12,12 +12,12 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private FCInitializeOperation _initializeFileCacheOp; private FCInitializeOperation _initializeFileCacheOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSInitializeOperation(CacheFileSystem fileSystem) internal SFSInitializeOperation(SandboxFileSystem fileSystem)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
@@ -45,29 +45,29 @@ namespace YooAsset
// 如果水印发生变化,则说明覆盖安装后首次打开游戏 // 如果水印发生变化,则说明覆盖安装后首次打开游戏
if (appFootprint.IsDirty()) if (appFootprint.IsDirty())
{ {
if (_fileSystem.InstallClearMode == EInstallCleanupMode.None) if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.None)
{ {
YooLogger.Warning("Do nothing when overwrite install application."); YooLogger.Warning("Do nothing when overwrite install application.");
} }
else if (_fileSystem.InstallClearMode == EInstallCleanupMode.ClearAllCacheFiles) else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllCacheFiles)
{ {
_fileSystem.DeleteAllBundleFiles(); _fileSystem.DeleteAllBundleFiles();
_fileSystem.DeleteAllManifestFiles(); _fileSystem.DeleteAllManifestFiles();
YooLogger.Warning("Delete all cache files when overwrite install application."); YooLogger.Warning("Delete all cache files when overwrite install application.");
} }
else if (_fileSystem.InstallClearMode == EInstallCleanupMode.ClearAllBundleFiles) else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllBundleFiles)
{ {
_fileSystem.DeleteAllBundleFiles(); _fileSystem.DeleteAllBundleFiles();
YooLogger.Warning("Delete all bundle files when overwrite install application."); YooLogger.Warning("Delete all bundle files when overwrite install application.");
} }
else if (_fileSystem.InstallClearMode == EInstallCleanupMode.ClearAllManifestFiles) else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllManifestFiles)
{ {
_fileSystem.DeleteAllManifestFiles(); _fileSystem.DeleteAllManifestFiles();
YooLogger.Warning("Delete all manifest files when overwrite install application."); YooLogger.Warning("Delete all manifest files when overwrite install application.");
} }
else else
{ {
throw new System.NotImplementedException(_fileSystem.InstallClearMode.ToString()); throw new System.NotImplementedException(_fileSystem.InstallCleanupMode.ToString());
} }
appFootprint.Coverage(_fileSystem.PackageName); appFootprint.Coverage(_fileSystem.PackageName);

View File

@@ -1,7 +1,7 @@
namespace YooAsset namespace YooAsset
{ {
internal class CFSLoadBundleOperation : FSLoadBundleOperation internal class SFSLoadBundleOperation : FSLoadBundleOperation
{ {
private enum ESteps private enum ESteps
{ {
@@ -14,13 +14,13 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly LoadBundleOptions _options; private readonly LoadBundleOptions _options;
private FSDownloadFileOperation _downloadFileOp; private FSDownloadFileOperation _downloadFileOp;
private FCLoadBundleOperation _loadBundleOp; private FCLoadBundleOperation _loadBundleOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSLoadBundleOperation(CacheFileSystem fileSystem, LoadBundleOptions options) internal SFSLoadBundleOperation(SandboxFileSystem fileSystem, LoadBundleOptions options)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_options = options; _options = options;
@@ -139,7 +139,7 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = "Loaded bundle result is null."; Error = "Fatal error: loaded bundle result is null.";
YooLogger.Error(Error); YooLogger.Error(Error);
} }
else else

View File

@@ -2,7 +2,7 @@
namespace YooAsset namespace YooAsset
{ {
internal class CFSLoadPackageManifestOperation : FSLoadManifestOperation internal class SFSLoadPackageManifestOperation : FSLoadManifestOperation
{ {
private enum ESteps private enum ESteps
{ {
@@ -14,7 +14,7 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly string _packageVersion; private readonly string _packageVersion;
private readonly int _timeout; private readonly int _timeout;
private DownloadPackageHashOperation _downloadPackageHashOp; private DownloadPackageHashOperation _downloadPackageHashOp;
@@ -24,7 +24,7 @@ namespace YooAsset
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSLoadPackageManifestOperation(CacheFileSystem fileSystem, string packageVersion, int timeout) internal SFSLoadPackageManifestOperation(SandboxFileSystem fileSystem, string packageVersion, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_packageVersion = packageVersion; _packageVersion = packageVersion;

View File

@@ -1,7 +1,7 @@
 
namespace YooAsset namespace YooAsset
{ {
internal class CFSRequestPackageVersionOperation : FSRequestVersionOperation internal class SFSRequestPackageVersionOperation : FSRequestVersionOperation
{ {
private enum ESteps private enum ESteps
{ {
@@ -10,14 +10,14 @@ namespace YooAsset
Done, Done,
} }
private readonly CacheFileSystem _fileSystem; private readonly SandboxFileSystem _fileSystem;
private readonly bool _appendTimeTicks; private readonly bool _appendTimeTicks;
private readonly int _timeout; private readonly int _timeout;
private RequestRemotePackageVersionOperation _requestRemotePackageVersionOp; private RequestRemotePackageVersionOperation _requestRemotePackageVersionOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal CFSRequestPackageVersionOperation(CacheFileSystem fileSystem, bool appendTimeTicks, int timeout) internal SFSRequestPackageVersionOperation(SandboxFileSystem fileSystem, bool appendTimeTicks, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks; _appendTimeTicks = appendTimeTicks;

View File

@@ -7,10 +7,9 @@ using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
/// <summary> /// <summary>
/// 缓存文件系统 /// 沙盒文件系统
/// 说明正在进行的下载器会在ResourcePackage销毁的时候执行Abort操作
/// </summary> /// </summary>
internal class CacheFileSystem : IFileSystem internal class SandboxFileSystem : IFileSystem
{ {
protected readonly Dictionary<string, string> _tempFilePathMapping = new Dictionary<string, string>(10000); protected readonly Dictionary<string, string> _tempFilePathMapping = new Dictionary<string, string>(10000);
protected string _packageRoot; protected string _packageRoot;
@@ -52,12 +51,12 @@ namespace YooAsset
/// <summary> /// <summary>
/// 自定义参数:覆盖安装缓存清理模式 /// 自定义参数:覆盖安装缓存清理模式
/// </summary> /// </summary>
public EInstallCleanupMode InstallClearMode { private set; get; } = EInstallCleanupMode.ClearAllManifestFiles; public EInstallCleanupMode InstallCleanupMode { private set; get; } = EInstallCleanupMode.None;
/// <summary> /// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别 /// 自定义参数:初始化的时候缓存文件校验级别
/// </summary> /// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle; public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Low;
/// <summary> /// <summary>
/// 自定义参数:初始化的时候缓存文件校验最大并发数 /// 自定义参数:初始化的时候缓存文件校验最大并发数
@@ -101,27 +100,42 @@ namespace YooAsset
public List<long> ResumeDownloadResponseCodes { private set; get; } = null; public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
/// <summary> /// <summary>
/// 自定义参数:资源清单服务类 /// 自定义参数:AssetBundle 解密器
/// </summary> /// </summary>
public IManifestRestoreServices ManifestRestoreServices { private set; get; } public IBundleDecryptor AssetBundleDecryptor { get; set; }
/// <summary>
/// 自定义参数RawBundle 解密器
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; set; }
/// <summary>
/// 自定义参数AssetBundle 备用解密器
/// </summary>
public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; }
/// <summary>
/// 自定义参数:资源清单解密器
/// </summary>
public IManifestDecryptor ManifestDecryptor { private set; get; }
#endregion #endregion
public CacheFileSystem() public SandboxFileSystem()
{ {
} }
public virtual FSInitializeOperation InitializeAsync() public virtual FSInitializeOperation InitializeAsync()
{ {
var operation = new CFSInitializeOperation(this); var operation = new SFSInitializeOperation(this);
return operation; return operation;
} }
public virtual FSRequestVersionOperation RequestVersionAsync(RequestVersionOptions options) public virtual FSRequestVersionOperation RequestVersionAsync(RequestVersionOptions options)
{ {
var operation = new CFSRequestPackageVersionOperation(this, options.AppendTimeTicks, options.Timeout); var operation = new SFSRequestPackageVersionOperation(this, options.AppendTimeTicks, options.Timeout);
return operation; return operation;
} }
public virtual FSLoadManifestOperation LoadManifestAsync(LoadManifestOptions options) public virtual FSLoadManifestOperation LoadManifestAsync(LoadManifestOptions options)
{ {
var operation = new CFSLoadPackageManifestOperation(this, options.PackageVersion, options.Timeout); var operation = new SFSLoadPackageManifestOperation(this, options.PackageVersion, options.Timeout);
return operation; return operation;
} }
public virtual FSClearCacheOperation ClearCacheAsync(ClearCacheOptions options) public virtual FSClearCacheOperation ClearCacheAsync(ClearCacheOptions options)
@@ -138,18 +152,18 @@ namespace YooAsset
} }
else else
{ {
var operation = new CFSClearCacheOperation(this, options); var operation = new SFSClearCacheOperation(this, options);
return operation; return operation;
} }
} }
public virtual FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options) public virtual FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options)
{ {
var downloader = new CFSDownloadFileOperation(this, options); var downloader = new SFSDownloadFileOperation(this, options);
return downloader; return downloader;
} }
public virtual FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options) public virtual FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
{ {
var operation = new CFSLoadBundleOperation(this, options); var operation = new SFSLoadBundleOperation(this, options);
return operation; return operation;
} }
@@ -169,7 +183,7 @@ namespace YooAsset
} }
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE) else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
{ {
InstallClearMode = (EInstallCleanupMode)value; InstallCleanupMode = (EInstallCleanupMode)value;
} }
else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL) else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
{ {
@@ -186,7 +200,7 @@ namespace YooAsset
// 限制在合理范围内1-32 // 限制在合理范围内1-32
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, 32); FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, 32);
} }
else if (name == FileSystemParametersDefine.DISABLE_ONDEMAND_DOWNLOAD) else if (name == FileSystemParametersDefine.DOWNLOAD_DISABLE_ONDEMAND)
{ {
DisableOnDemandDownload = Convert.ToBoolean(value); DisableOnDemandDownload = Convert.ToBoolean(value);
} }
@@ -217,17 +231,29 @@ namespace YooAsset
int convertValue = Convert.ToInt32(value); int convertValue = Convert.ToInt32(value);
DownloadWatchDogTimeout = Mathf.Clamp(convertValue, 0, int.MaxValue); DownloadWatchDogTimeout = Mathf.Clamp(convertValue, 0, int.MaxValue);
} }
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE) else if (name == FileSystemParametersDefine.DOWNLOAD_RESUME_MINMUM_SIZE)
{ {
ResumeDownloadMinimumSize = Convert.ToInt64(value); ResumeDownloadMinimumSize = Convert.ToInt64(value);
} }
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_RESPONSE_CODES) else if (name == FileSystemParametersDefine.DOWNLOAD_RESUME_RESPONSE_CODES)
{ {
ResumeDownloadResponseCodes = (List<long>)value; ResumeDownloadResponseCodes = (List<long>)value;
} }
else if (name == FileSystemParametersDefine.MANIFEST_RESTORE_SERVICES) else if (name == FileSystemParametersDefine.ASSETBUNDLE_DECRYPTOR)
{ {
ManifestRestoreServices = (IManifestRestoreServices)value; AssetBundleDecryptor = (IBundleDecryptor)value;
}
else if (name == FileSystemParametersDefine.RAWBUNDLE_DECRYPTOR)
{
RawBundleDecryptor = (IBundleDecryptor)value;
}
else if (name == FileSystemParametersDefine.ASSETBUNDLE_FALLBACK_DECRYPTOR)
{
AssetBundleFallbackDecryptor = (IBundleMemoryDecryptor)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_DECRYPTOR)
{
ManifestDecryptor = (IManifestDecryptor)value;
} }
else else
{ {
@@ -243,15 +269,18 @@ namespace YooAsset
else else
_packageRoot = packageRoot; _packageRoot = packageRoot;
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName); _cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, SandboxFileSystemDefine.BundleFilesFolderName);
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName); _cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, SandboxFileSystemDefine.ManifestFilesFolderName);
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName); _tempFilesRoot = PathUtility.Combine(_packageRoot, SandboxFileSystemDefine.TempFilesFolderName);
// 创建文件缓存系统 // 创建文件缓存系统
{ {
var cacheConfig = new SandboxFileCache.CacheConfig(); var cacheConfig = new SandboxFileCache.CacheConfig();
cacheConfig.FileVerifyLevel = FileVerifyLevel;
cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency; cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency;
cacheConfig.FileVerifyLevel = FileVerifyLevel;
cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor;
cacheConfig.RawBundleDecryptor = RawBundleDecryptor;
cacheConfig.AssetBundleFallbackDecryptor = AssetBundleFallbackDecryptor;
FileCache = new SandboxFileCache(PackageName, _cacheBundleFilesRoot, cacheConfig); FileCache = new SandboxFileCache(PackageName, _cacheBundleFilesRoot, cacheConfig);
} }
@@ -326,7 +355,7 @@ namespace YooAsset
} }
public string GetSandboxAppFootPrintFilePath() public string GetSandboxAppFootPrintFilePath()
{ {
return PathUtility.Combine(_cacheManifestFilesRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName); return PathUtility.Combine(_cacheManifestFilesRoot, SandboxFileSystemDefine.AppFootPrintFileName);
} }
public string GetTempFilePath(PackageBundle bundle) public string GetTempFilePath(PackageBundle bundle)
{ {

View File

@@ -1,7 +1,7 @@
 
namespace YooAsset namespace YooAsset
{ {
internal class DefaultCacheFileSystemDefine internal class SandboxFileSystemDefine
{ {
/// <summary> /// <summary>
/// 记录应用程序版本的文件名称 /// 记录应用程序版本的文件名称

View File

@@ -1,55 +0,0 @@
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的抽象基类
/// 用户可继承此类实现自定义加载逻辑(如加密解密)
/// </summary>
public abstract class LoadWebAssetBundleOperation : AsyncOperationBase
{
protected readonly LoadWebAssetBundleOptions _options;
/// <summary>
/// 加载结果AssetBundle 对象
/// </summary>
public AssetBundle Result { get; protected set; }
/// <summary>
/// 下载进度
/// </summary>
public float DownloadProgress { protected set; get; }
/// <summary>
/// 下载大小
/// </summary>
public long DownloadedBytes { protected set; get; }
public LoadWebAssetBundleOperation(LoadWebAssetBundleOptions options)
{
_options = options;
}
}
/// <summary>
/// 立即完成(失败)的 AssetBundle 加载操作
/// 用途:当 Factory 判定某种场景不支持(例如默认实现不支持加密包)时,返回该 Operation
/// </summary>
public sealed class LoadWebAssetBundleCompleteOperation : LoadWebAssetBundleOperation
{
private readonly string _error;
public LoadWebAssetBundleCompleteOperation(string error, LoadWebAssetBundleOptions options) : base(options)
{
_error = error;
}
internal override void InternalStart()
{
Status = EOperationStatus.Failed;
Error = _error;
}
internal override void InternalUpdate()
{
}
}
}

View File

@@ -1,44 +0,0 @@
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的上下文信息
/// </summary>
public struct LoadWebAssetBundleOptions
{
/// <summary>
/// 资源包信息
/// </summary>
internal PackageBundle Bundle { get; set; }
/// <summary>
/// 失败后重试次数
/// </summary>
internal int RetryCount { get; set; }
/// <summary>
/// 看门狗超时时间
/// </summary>
internal int WatchdogTimeout { get; set; }
/// <summary>
/// 下载后台接口
/// </summary>
internal IDownloadBackend DownloadBackend { get; set; }
/// <summary>
/// 禁用Unity的网络缓存
/// </summary>
internal bool DisableUnityWebCache { get; set; }
/// <summary>
/// 主资源地址
/// </summary>
internal string MainURL { get; set; }
/// <summary>
/// 备用资源地址
/// </summary>
internal string FallbackURL { get; set; }
}
}

View File

@@ -11,7 +11,7 @@ internal class LoadWebPackageManifestOperation : AsyncOperationBase
Done, Done,
} }
private readonly IManifestRestoreServices _manifestServices; private readonly IManifestDecryptor _manifestDecryptor;
private readonly IRemoteServices _remoteServices; private readonly IRemoteServices _remoteServices;
private readonly IDownloadBackend _downloadBackend; private readonly IDownloadBackend _downloadBackend;
private readonly string _packageName; private readonly string _packageName;
@@ -29,10 +29,10 @@ internal class LoadWebPackageManifestOperation : AsyncOperationBase
public PackageManifest Manifest { private set; get; } public PackageManifest Manifest { private set; get; }
internal LoadWebPackageManifestOperation(IManifestRestoreServices manifestServices, IRemoteServices remoteServices, IDownloadBackend downloadBackend, internal LoadWebPackageManifestOperation(IManifestDecryptor manifestDecryptor, IRemoteServices remoteServices, IDownloadBackend downloadBackend,
string packageName, string packageVersion, string packageHash, int timeout) string packageName, string packageVersion, string packageHash, int timeout)
{ {
_manifestServices = manifestServices; _manifestDecryptor = manifestDecryptor;
_remoteServices = remoteServices; _remoteServices = remoteServices;
_downloadBackend = downloadBackend; _downloadBackend = downloadBackend;
_packageName = packageName; _packageName = packageName;
@@ -96,7 +96,7 @@ internal class LoadWebPackageManifestOperation : AsyncOperationBase
{ {
if (_deserializer == null) if (_deserializer == null)
{ {
_deserializer = new DeserializeManifestOperation(_manifestServices, _webDataRequestOp.Result); _deserializer = new DeserializeManifestOperation(_manifestDecryptor, _webDataRequestOp.Result);
_deserializer.StartOperation(); _deserializer.StartOperation();
AddChildOperation(_deserializer); AddChildOperation(_deserializer);
} }

Some files were not shown because too many files have changed in this diff Show More