feat: support ArchiveBundle loading in Web file systems

This commit is contained in:
何冠峰
2026-05-28 21:07:40 +08:00
parent 289dee326b
commit 513c1d0b18
18 changed files with 586 additions and 23 deletions

View File

@@ -2,7 +2,7 @@
namespace YooAsset
{
/// <summary>
/// 加载 ArchiveBundle 的操作选项
/// 本地加载 ArchiveBundle 的操作选项
/// </summary>
internal readonly struct LoadLocalArchiveBundleOptions
{

View File

@@ -2,7 +2,7 @@
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的操作选项
/// 本地加载 AssetBundle 的操作选项
/// </summary>
internal readonly struct LoadLocalAssetBundleOptions
{

View File

@@ -2,7 +2,7 @@
namespace YooAsset
{
/// <summary>
/// 加载 RawBundle 的操作选项
/// 本地加载 RawBundle 的操作选项
/// </summary>
internal readonly struct LoadLocalRawBundleOptions
{

View File

@@ -0,0 +1,216 @@
using System;
namespace YooAsset
{
/// <summary>
/// WebGL 平台加载 ArchiveBundle 操作
/// </summary>
internal sealed class LoadWebArchiveBundleOperation : BCLoadBundleOperation
{
private enum ESteps
{
None,
Prepare,
DataRequest,
CheckRequest,
VerifyData,
LoadBundle,
TryAgain,
Done,
}
private readonly LoadWebArchiveBundleOptions _options;
private readonly DownloadRetryController _downloadRetryController;
private IDownloadBytesRequest _downloadBytesRequest;
private IBundleMemoryDecryptor _decryptor;
private ArchiveBundle _archiveBundle;
private ESteps _steps = ESteps.None;
internal LoadWebArchiveBundleOperation(LoadWebArchiveBundleOptions options)
{
_options = options;
// 注意:网络原因失败后,重新尝试直到成功
_downloadRetryController = new DownloadRetryController(int.MaxValue, options.DownloadRetryPolicy);
}
protected override void InternalStart()
{
_steps = ESteps.Prepare;
}
protected override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Prepare)
{
if (_options.Bundle.IsEncrypted == false)
{
_steps = ESteps.DataRequest;
}
else
{
var decryptor = _options.ArchiveBundleDecryptor;
if (decryptor == null)
{
_steps = ESteps.Done;
SetError($"{_options.CacheName} archive bundle decryptor is null.");
return;
}
if (decryptor is IBundleMemoryDecryptor)
{
_decryptor = decryptor as IBundleMemoryDecryptor;
_steps = ESteps.DataRequest;
}
else
{
_steps = ESteps.Done;
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}' for ArchiveBundle.");
return;
}
}
}
if (_steps == ESteps.DataRequest)
{
string url = _options.DownloadUrlPolicy.SelectUrl(_options.CandidateUrls);
var args = new DownloadDataRequestArgs(
url: url,
timeout: 0,
watchdogTimeout: _options.WatchdogTimeout);
_downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args);
_downloadBytesRequest.SendRequest();
_steps = ESteps.CheckRequest;
}
if (_steps == ESteps.CheckRequest)
{
Progress = _downloadBytesRequest.DownloadProgress;
if (_downloadBytesRequest.IsDone == false)
return;
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
{
_options.DownloadUrlPolicy.OnRequestSucceeded(_downloadBytesRequest.Url);
_steps = ESteps.VerifyData;
}
else
{
string url = _downloadBytesRequest.Url;
long httpCode = _downloadBytesRequest.HttpCode;
string httpError = _downloadBytesRequest.HttpError;
_options.DownloadUrlPolicy.OnRequestFailed(url, httpCode, httpError);
if (IsWaitForCompletion == false && _downloadRetryController.CanRetryRequest(url, httpCode, httpError))
{
_downloadRetryController.StartRetryDelay();
_steps = ESteps.TryAgain;
}
else
{
_steps = ESteps.Done;
SetError(_downloadBytesRequest.Error);
YooLogger.LogError(Error);
}
}
}
if (_steps == ESteps.VerifyData)
{
// 注意:网络/代理/服务器异常导致内容不完整但请求仍成功
EFileVerifyResult verifyResult;
if (_options.DownloadVerifyLevel == EFileVerifyLevel.Low || _options.DownloadVerifyLevel == EFileVerifyLevel.Middle)
verifyResult = FileVerifyHelper.VerifyFile(_downloadBytesRequest.Result, _options.Bundle.FileSize, 0);
else if (_options.DownloadVerifyLevel == EFileVerifyLevel.High)
verifyResult = FileVerifyHelper.VerifyFile(_downloadBytesRequest.Result, _options.Bundle.FileSize, _options.Bundle.FileCrc);
else
throw new YooInternalException($"Unexpected verify level: {_options.DownloadVerifyLevel}.");
if (verifyResult == EFileVerifyResult.Succeed)
{
_steps = ESteps.LoadBundle;
}
else
{
string error = $"Verify failed. Url: '{_downloadBytesRequest.Url}' Level: {_options.DownloadVerifyLevel} Result: {verifyResult}.";
YooLogger.LogWarning(error);
if (IsWaitForCompletion == false && _downloadRetryController.HasRetriesRemaining())
{
_downloadRetryController.StartRetryDelay();
_steps = ESteps.TryAgain;
}
else
{
_steps = ESteps.Done;
SetError(error);
}
}
}
if (_steps == ESteps.LoadBundle)
{
LoadResult result = LoadFromMemory(_decryptor, _downloadBytesRequest.Result);
if (result.Succeeded == false)
{
_steps = ESteps.Done;
SetError(result.Error);
return;
}
_steps = ESteps.Done;
SetResult();
BundleHandle = new ArchiveBundleHandle(_options.Bundle, _archiveBundle);
}
if (_steps == ESteps.TryAgain)
{
// 注意:失败后释放网络请求
if (_downloadBytesRequest != null)
{
_downloadBytesRequest.Dispose();
_downloadBytesRequest = null;
}
if (_downloadRetryController.TickRetryDelay())
{
Progress = 0f;
_steps = ESteps.DataRequest;
}
}
}
protected override void InternalDispose()
{
if (_downloadBytesRequest != null)
{
_downloadBytesRequest.Dispose();
_downloadBytesRequest = null;
}
}
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor, byte[] fileData)
{
try
{
if (decryptor != null)
{
var args = new BundleDecryptArgs(_options.Bundle, fileData, null);
var binaryData = decryptor.GetDecryptedData(args);
if (binaryData == null)
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
_archiveBundle = ArchiveBundleHelper.LoadFromMemory(binaryData);
}
else
{
_archiveBundle = ArchiveBundleHelper.LoadFromMemory(fileData);
}
return LoadResult.Default();
}
catch (Exception ex)
{
return LoadResult.Failure($"Failed to load archive bundle from memory: {ex.Message}.");
}
}
}
}

View File

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

View File

@@ -0,0 +1,70 @@
using System.Collections.Generic;
namespace YooAsset
{
/// <summary>
/// WebGL 平台加载 ArchiveBundle 的操作选项
/// </summary>
internal readonly struct LoadWebArchiveBundleOptions
{
/// <summary>
/// 文件缓存名称
/// </summary>
public string CacheName { get; }
/// <summary>
/// 资源包描述
/// </summary>
public PackageBundle Bundle { get; }
/// <summary>
/// 候选下载地址列表
/// </summary>
public IReadOnlyList<string> CandidateUrls { get; }
/// <summary>
/// ArchiveBundle 解密器
/// </summary>
public IBundleDecryptor ArchiveBundleDecryptor { get; }
/// <summary>
/// 下载后台接口
/// </summary>
public IDownloadBackend DownloadBackend { get; }
/// <summary>
/// 下载数据校验级别
/// </summary>
public EFileVerifyLevel DownloadVerifyLevel { get; }
/// <summary>
/// 看门狗超时时间
/// </summary>
public int WatchdogTimeout { get; }
/// <summary>
/// 下载重试判定策略
/// </summary>
public IDownloadRetryPolicy DownloadRetryPolicy { get; }
/// <summary>
/// URL 选择策略
/// </summary>
public IDownloadUrlPolicy DownloadUrlPolicy { get; }
public LoadWebArchiveBundleOptions(string cacheName, PackageBundle bundle, IReadOnlyList<string> candidateUrls,
IBundleDecryptor archiveBundleDecryptor, IDownloadBackend downloadBackend, EFileVerifyLevel downloadVerifyLevel,
int watchdogTimeout, IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy)
{
CacheName = cacheName;
Bundle = bundle;
CandidateUrls = candidateUrls;
ArchiveBundleDecryptor = archiveBundleDecryptor;
DownloadBackend = downloadBackend;
DownloadVerifyLevel = downloadVerifyLevel;
WatchdogTimeout = watchdogTimeout;
DownloadRetryPolicy = downloadRetryPolicy;
DownloadUrlPolicy = downloadUrlPolicy;
}
}
}

View File

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

View File

@@ -61,7 +61,7 @@ namespace YooAsset
else
{
_steps = ESteps.Done;
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}'.");
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}' for ArchiveBundle.");
return;
}
}

View File

@@ -1,7 +1,9 @@
using System;
namespace YooAsset
{
/// <summary>
/// 从网络加载 RawBundle 操作
/// WebGL 平台加载 RawBundle 操作
/// </summary>
internal sealed class LoadWebRawBundleOperation : BCLoadBundleOperation
{
@@ -24,10 +26,6 @@ namespace YooAsset
private RawBundle _rawBundle;
private ESteps _steps = ESteps.None;
/// <summary>
/// 创建网络 RawBundle 加载操作实例
/// </summary>
/// <param name="options">从网络加载 RawBundle 的操作选项</param>
internal LoadWebRawBundleOperation(LoadWebRawBundleOptions options)
{
_options = options;
@@ -68,7 +66,7 @@ namespace YooAsset
else
{
_steps = ESteps.Done;
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}'.");
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}' for RawBundle.");
return;
}
}
@@ -191,6 +189,8 @@ namespace YooAsset
}
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor, byte[] fileData)
{
try
{
if (decryptor != null)
{
@@ -200,13 +200,17 @@ namespace YooAsset
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
_rawBundle = RawBundleHelper.LoadFromMemory(binaryData);
return LoadResult.Default();
}
else
{
_rawBundle = RawBundleHelper.LoadFromMemory(fileData);
}
return LoadResult.Default();
}
catch (Exception ex)
{
return LoadResult.Failure($"Failed to load archive bundle from memory: {ex.Message}.");
}
}
}
}

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace YooAsset
{
/// <summary>
/// 加载 RawBundle 的操作选项
/// WebGL 平台加载 RawBundle 的操作选项
/// </summary>
internal readonly struct LoadWebRawBundleOptions
{

View File

@@ -0,0 +1,86 @@
namespace YooAsset
{
/// <summary>
/// WebGL 平台网络缓存加载 ArchiveBundle 操作
/// </summary>
internal sealed class WNBCLoadArchiveBundleOperation : BCLoadBundleOperation
{
private enum ESteps
{
None,
LoadBundle,
Done,
}
private readonly WebNetworkBundleCache _fileCache;
private readonly BCLoadBundleOptions _options;
private BCLoadBundleOperation _loadBundleOp;
private ESteps _steps = ESteps.None;
internal WNBCLoadArchiveBundleOperation(WebNetworkBundleCache fileCache, BCLoadBundleOptions options)
{
_fileCache = fileCache;
_options = options;
}
protected override void InternalStart()
{
_steps = ESteps.LoadBundle;
}
protected override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBundle)
{
if (_loadBundleOp == null)
{
var urls = _fileCache.Config.RemoteService.GetRemoteUrls(_options.Bundle.GetFileName());
var options = new LoadWebArchiveBundleOptions(
cacheName: _fileCache.GetType().Name,
bundle: _options.Bundle,
candidateUrls: urls,
archiveBundleDecryptor: _fileCache.Config.ArchiveBundleDecryptor,
downloadBackend: _fileCache.Config.DownloadBackend,
downloadVerifyLevel: _fileCache.Config.DownloadVerifyLevel,
watchdogTimeout: 0,
downloadRetryPolicy: _fileCache.Config.DownloadRetryPolicy,
downloadUrlPolicy: _fileCache.Config.DownloadUrlPolicy);
_loadBundleOp = new LoadWebArchiveBundleOperation(options);
_loadBundleOp.StartOperation();
AddChildOperation(_loadBundleOp);
}
_loadBundleOp.UpdateOperation();
Progress = _loadBundleOp.Progress;
if (_loadBundleOp.IsDone == false)
return;
if (_loadBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadBundleOp.BundleHandle == null)
throw new YooInternalException("Loaded bundle handle is null.");
_steps = ESteps.Done;
SetResult();
BundleHandle = _loadBundleOp.BundleHandle;
}
else
{
_steps = ESteps.Done;
SetError(_loadBundleOp.Error);
}
}
}
protected override void InternalWaitForCompletion()
{
if (_steps != ESteps.Done)
{
_steps = ESteps.Done;
SetError("WebGL platform does not support synchronous loading.");
YooLogger.LogError(Error);
}
}
}
}

View File

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

View File

@@ -27,6 +27,11 @@ namespace YooAsset
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; }
/// <summary>
/// ArchiveBundle 解密器
/// </summary>
public IBundleDecryptor ArchiveBundleDecryptor { get; }
/// <summary>
/// 平台策略接口
/// </summary>
@@ -54,13 +59,14 @@ namespace YooAsset
public Configuration(bool disableUnityWebCache,
EFileVerifyLevel downloadVerifyLevel, IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor,
IWebPlatformStrategy platformStrategy, IRemoteService remoteService, IDownloadBackend downloadBackend,
IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy)
IBundleDecryptor archiveBundleDecryptor, IWebPlatformStrategy platformStrategy, IRemoteService remoteService,
IDownloadBackend downloadBackend, IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy)
{
DisableUnityWebCache = disableUnityWebCache;
DownloadVerifyLevel = downloadVerifyLevel;
AssetBundleDecryptor = assetBundleDecryptor;
RawBundleDecryptor = rawBundleDecryptor;
ArchiveBundleDecryptor = archiveBundleDecryptor;
PlatformStrategy = platformStrategy;
RemoteService = remoteService;
DownloadBackend = downloadBackend;
@@ -139,6 +145,11 @@ namespace YooAsset
var operation = new WNBCLoadRawBundleOperation(this, options);
return operation;
}
else if (options.Bundle.GetBundleType() == (int)EBundleType.ArchiveBundle)
{
var operation = new WNBCLoadArchiveBundleOperation(this, options);
return operation;
}
else
{
string error = $"{nameof(WebNetworkBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}.";

View File

@@ -0,0 +1,101 @@
namespace YooAsset
{
/// <summary>
/// Web服务器文件缓存加载 ArchiveBundle 操作
/// </summary>
internal sealed class WSBCLoadArchiveBundleOperation : BCLoadBundleOperation
{
private enum ESteps
{
None,
GetEntry,
LoadBundle,
Done,
}
private readonly WebServerBundleCache _fileCache;
private readonly BCLoadBundleOptions _options;
private BCLoadBundleOperation _loadBundleOp;
private WebServerBundleCacheEntry _cacheEntry;
private ESteps _steps = ESteps.None;
public WSBCLoadArchiveBundleOperation(WebServerBundleCache fileCache, BCLoadBundleOptions options)
{
_fileCache = fileCache;
_options = options;
}
protected override void InternalStart()
{
_steps = ESteps.GetEntry;
}
protected override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.GetEntry)
{
_cacheEntry = _fileCache.GetEntry(_options.Bundle.BundleGuid);
if (_cacheEntry == null)
{
_steps = ESteps.Done;
SetError($"File cache entry not found: '{_options.Bundle.BundleGuid}'.");
}
else
{
_steps = ESteps.LoadBundle;
}
}
if (_steps == ESteps.LoadBundle)
{
if (_loadBundleOp == null)
{
string url = DownloadUrlHelper.ToLocalFileUrl(_cacheEntry.FilePath);
var options = new LoadWebArchiveBundleOptions(
cacheName: _fileCache.GetType().Name,
bundle: _options.Bundle,
candidateUrls: new[] { url },
archiveBundleDecryptor: _fileCache.Config.ArchiveBundleDecryptor,
downloadBackend: _fileCache.Config.DownloadBackend,
downloadVerifyLevel: _fileCache.Config.DownloadVerifyLevel,
watchdogTimeout: _fileCache.Config.WatchdogTimeout,
downloadRetryPolicy: _fileCache.Config.DownloadRetryPolicy,
downloadUrlPolicy: _fileCache.Config.DownloadUrlPolicy);
_loadBundleOp = new LoadWebArchiveBundleOperation(options);
_loadBundleOp.StartOperation();
AddChildOperation(_loadBundleOp);
}
_loadBundleOp.UpdateOperation();
Progress = _loadBundleOp.Progress;
if (_loadBundleOp.IsDone == false)
return;
if (_loadBundleOp.Status == EOperationStatus.Succeeded)
{
if (_loadBundleOp.BundleHandle == null)
throw new YooInternalException("Loaded bundle handle is null.");
_steps = ESteps.Done;
SetResult();
BundleHandle = _loadBundleOp.BundleHandle;
}
else
{
_steps = ESteps.Done;
SetError(_loadBundleOp.Error);
}
}
}
protected override void InternalWaitForCompletion()
{
if (_steps != ESteps.Done)
{
_steps = ESteps.Done;
SetError("WebGL platform does not support synchronous loading.");
YooLogger.LogError(Error);
}
}
}
}

View File

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

View File

@@ -35,6 +35,11 @@ namespace YooAsset
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; }
/// <summary>
/// ArchiveBundle 解密器
/// </summary>
public IBundleDecryptor ArchiveBundleDecryptor { get; }
/// <summary>
/// Web 平台策略
/// </summary>
@@ -57,7 +62,7 @@ namespace YooAsset
public Configuration(int watchdogTimeout, bool disableUnityWebCache,
EFileVerifyLevel downloadVerifyLevel, IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor,
IWebPlatformStrategy platformStrategy, IDownloadBackend downloadBackend,
IBundleDecryptor archiveBundleDecryptor, IWebPlatformStrategy platformStrategy, IDownloadBackend downloadBackend,
IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy)
{
WatchdogTimeout = watchdogTimeout;
@@ -65,6 +70,7 @@ namespace YooAsset
DownloadVerifyLevel = downloadVerifyLevel;
AssetBundleDecryptor = assetBundleDecryptor;
RawBundleDecryptor = rawBundleDecryptor;
ArchiveBundleDecryptor = archiveBundleDecryptor;
PlatformStrategy = platformStrategy;
DownloadBackend = downloadBackend;
DownloadRetryPolicy = downloadRetryPolicy;
@@ -157,6 +163,11 @@ namespace YooAsset
var operation = new WSBCLoadRawBundleOperation(this, options);
return operation;
}
else if (options.Bundle.GetBundleType() == (int)EBundleType.ArchiveBundle)
{
var operation = new WSBCLoadArchiveBundleOperation(this, options);
return operation;
}
else
{
string error = $"{nameof(WebServerBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}.";

View File

@@ -57,6 +57,11 @@ namespace YooAsset
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; private set; }
/// <summary>
/// 自定义参数ArchiveBundle 解密器
/// </summary>
public IBundleDecryptor ArchiveBundleDecryptor { get; private set; }
/// <summary>
/// 自定义参数:资源清单解密器
/// </summary>
@@ -156,6 +161,10 @@ namespace YooAsset
{
RawBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
}
else if (paramName == nameof(EFileSystemParameter.ArchiveBundleDecryptor))
{
ArchiveBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
}
else if (paramName == nameof(EFileSystemParameter.ManifestDecryptor))
{
ManifestDecryptor = FileSystemHelper.CastParameter<IManifestDecryptor>(paramName, value);
@@ -204,6 +213,7 @@ namespace YooAsset
downloadVerifyLevel: DownloadVerifyLevel,
assetBundleDecryptor: AssetBundleDecryptor,
rawBundleDecryptor: RawBundleDecryptor,
archiveBundleDecryptor: ArchiveBundleDecryptor,
platformStrategy: PlatformStrategy,
remoteService: RemoteService,
downloadBackend: DownloadBackend,

View File

@@ -69,6 +69,11 @@ namespace YooAsset
/// </summary>
public IBundleDecryptor RawBundleDecryptor { get; private set; }
/// <summary>
/// 自定义参数ArchiveBundle 解密器
/// </summary>
public IBundleDecryptor ArchiveBundleDecryptor { get; private set; }
/// <summary>
/// 自定义参数:资源清单解密器
/// </summary>
@@ -166,6 +171,10 @@ namespace YooAsset
{
RawBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
}
else if (paramName == nameof(EFileSystemParameter.ArchiveBundleDecryptor))
{
ArchiveBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
}
else if (paramName == nameof(EFileSystemParameter.ManifestDecryptor))
{
ManifestDecryptor = FileSystemHelper.CastParameter<IManifestDecryptor>(paramName, value);
@@ -220,6 +229,7 @@ namespace YooAsset
downloadVerifyLevel: DownloadVerifyLevel,
assetBundleDecryptor: AssetBundleDecryptor,
rawBundleDecryptor: RawBundleDecryptor,
archiveBundleDecryptor: ArchiveBundleDecryptor,
platformStrategy: PlatformStrategy,
downloadBackend: DownloadBackend,
downloadRetryPolicy: DownloadRetryPolicy,