Update YooAsset 2.3.8 -> 2.3.12

This commit is contained in:
Alex-Rachel
2025-07-08 23:02:24 +08:00
parent 71eb698038
commit 86b1ff5d7b
172 changed files with 2124 additions and 724 deletions

View File

@@ -5,6 +5,7 @@
[assembly: InternalsVisibleTo("YooAsset.Test.Editor")]
// 外部友元
[assembly: InternalsVisibleTo("YooAsset.MiniGame")]
[assembly: InternalsVisibleTo("YooAsset.RuntimeExtension")]
[assembly: InternalsVisibleTo("YooAsset.EditorExtension")]
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]

View File

@@ -69,6 +69,8 @@ namespace YooAsset
url = new System.Uri(path).ToString();
#elif UNITY_STANDALONE || UNITY_WSA
url = StringUtility.Format("file:///{0}", path);
#elif UNITY_TVOS
url = StringUtility.Format("file:///{0}", path);
#else
throw new System.NotImplementedException();
#endif

View File

@@ -106,7 +106,7 @@ namespace YooAsset
}
internal override void InternalWaitForAsyncComplete()
{
//TODO 场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
//注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
InternalUpdate();
}
public override void UnSuspendLoad()

View File

@@ -112,7 +112,7 @@ namespace YooAsset
}
internal override void InternalWaitForAsyncComplete()
{
//TODO 场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
//注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
InternalUpdate();
}
public override void UnSuspendLoad()

View File

@@ -88,6 +88,16 @@ namespace YooAsset
/// 自定义参数:解密方法类
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
/// <summary>
/// 自定义参数:拷贝内置文件服务类
/// </summary>
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
#endregion
@@ -174,6 +184,14 @@ namespace YooAsset
{
DecryptionServices = (IDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else if (name == FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES)
{
CopyLocalFileServices = (ICopyLocalFileServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
@@ -196,6 +214,7 @@ namespace YooAsset
_unpackFileSystem.SetParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, InstallClearMode);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES, CopyLocalFileServices);
_unpackFileSystem.OnCreate(packageName, null);
}
public virtual void OnDestroy()

View File

@@ -11,7 +11,7 @@ namespace YooAsset
/// <summary>
/// 在构建应用程序前自动生成内置资源目录文件。
/// 原理搜索StreamingAssets目录下的所有资源文件然后将这些文件信息写入文件,并存储在Resources目录下
/// 原理搜索StreamingAssets目录下的所有资源文件将这些文件信息写入文件然后在运行时做查询用途
/// </summary>
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
@@ -21,7 +21,7 @@ namespace YooAsset
DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);
if (rootDirectory.Exists == false)
{
UnityEngine.Debug.LogWarning($"Can not found StreamingAssets root directory : {rootPath}");
Debug.LogWarning($"Can not found StreamingAssets root directory : {rootPath}");
return;
}
@@ -31,10 +31,17 @@ namespace YooAsset
{
string packageName = subDirectory.Name;
string pacakgeDirectory = subDirectory.FullName;
bool result = CreateBuildinCatalogFile(packageName, pacakgeDirectory);
if (result == false)
try
{
throw new System.Exception($"Create package {packageName} catalog file failed ! See the detail error in console !");
bool result = CreateBuildinCatalogFile(null, packageName, pacakgeDirectory);
if (result == false)
{
Debug.LogError($"Create package {packageName} catalog file failed ! See the detail error in console !");
}
}
catch (System.Exception ex)
{
Debug.LogError($"Create package {packageName} catalog file failed ! {ex.Message}");
}
}
}
@@ -42,7 +49,7 @@ namespace YooAsset
/// <summary>
/// 生成包裹的内置资源目录文件
/// </summary>
public static bool CreateBuildinCatalogFile(string packageName, string pacakgeDirectory)
public static bool CreateBuildinCatalogFile(IManifestServices services, string packageName, string pacakgeDirectory)
{
// 获取资源清单版本
string packageVersion;
@@ -70,7 +77,7 @@ namespace YooAsset
}
var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
packageManifest = ManifestTools.DeserializeFromBinary(binaryData);
packageManifest = ManifestTools.DeserializeFromBinary(binaryData, services);
}
// 获取文件名映射关系

View File

@@ -106,10 +106,11 @@ namespace YooAsset
if (_loadCatalogFileOp == null)
{
#if UNITY_EDITOR
/*
// 兼容性初始化
// 说明:内置文件系统在编辑器下运行时需要动态生成
string packageRoot = _fileSystem.FileRoot;
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.PackageName, packageRoot);
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.ManifestServices, _fileSystem.PackageName, packageRoot);
if (result == false)
{
_steps = ESteps.Done;
@@ -117,6 +118,7 @@ namespace YooAsset
Error = $"Create package catalog file failed ! See the detail error in console !";
return;
}
*/
#endif
_loadCatalogFileOp = new LoadBuildinCatalogFileOperation(_fileSystem);

View File

@@ -85,7 +85,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -58,7 +58,7 @@ namespace YooAsset
/// <summary>
/// 自定义参数:远程服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
public IRemoteServices RemoteServices { private set; get; }
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别
@@ -99,6 +99,16 @@ namespace YooAsset
/// 自定义参数:解密方法类
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
/// <summary>
/// 自定义参数:拷贝内置文件服务类
/// </summary>
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
#endregion
@@ -221,6 +231,14 @@ namespace YooAsset
{
DecryptionServices = (IDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else if (name == FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES)
{
CopyLocalFileServices = (ICopyLocalFileServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
@@ -559,6 +577,21 @@ namespace YooAsset
};
return DecryptionServices.LoadAssetBundleAsync(fileInfo);
}
/// <summary>
/// 加载加密资源文件
/// </summary>
public DecryptResult LoadEncryptedAssetBundleFallback(PackageBundle bundle)
{
string filePath = GetCacheBundleFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.LoadAssetBundleFallback(fileInfo);
}
#endregion
}
}

View File

@@ -164,11 +164,23 @@ namespace YooAsset
{
if (_bundle.Encrypted)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load encrypted asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
return;
var decryptResult = _fileSystem.LoadEncryptedAssetBundleFallback(_bundle);
_assetBundle = decryptResult.Result;
if (_assetBundle != null)
{
_steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, _managedStream);
Status = EOperationStatus.Succeed;
return;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load encrypted asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
return;
}
}
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
@@ -216,9 +228,6 @@ namespace YooAsset
{
if (ExecuteWhileDone())
{
if (_downloadFileOp != null && _downloadFileOp.Status == EOperationStatus.Failed)
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote !");
_steps = ESteps.Done;
break;
}
@@ -348,10 +357,6 @@ namespace YooAsset
{
if (ExecuteWhileDone())
{
//TODO 拷贝本地文件失败也会触发该错误!
if (_downloadFileOp != null && _downloadFileOp.Status == EOperationStatus.Failed)
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote !");
_steps = ESteps.Done;
break;
}

View File

@@ -82,32 +82,43 @@ namespace YooAsset
return oldDownloader;
}
// 设置请求URL
// 获取下载地址
if (string.IsNullOrEmpty(options.ImportFilePath))
{
// 注意:如果是解压文件系统类,这里会返回本地内置文件的下载路径
options.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(bundle.FileName);
options.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(bundle.FileName);
}
else
{
// 注意:把本地文件路径指定为远端下载地址
// 注意:把本地导入文件路径转换为下载器请求地址
options.MainURL = DownloadSystemHelper.ConvertToWWWPath(options.ImportFilePath);
options.FallbackURL = options.MainURL;
}
// 创建新的下载器
DefaultDownloadFileOperation newDownloader;
if (bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize)
bool isRequestLocalFile = DownloadSystemHelper.IsRequestLocalFile(options.MainURL);
if (isRequestLocalFile)
{
newDownloader = new DownloadResumeFileOperation(_fileSystem, bundle, options);
newDownloader = new DownloadLocalFileOperation(_fileSystem, bundle, options);
AddChildOperation(newDownloader);
_downloaders.Add(bundle.BundleGUID, newDownloader);
}
else
{
newDownloader = new DownloadNormalFileOperation(_fileSystem, bundle, options);
AddChildOperation(newDownloader);
_downloaders.Add(bundle.BundleGUID, newDownloader);
if (bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize)
{
newDownloader = new DownloadResumeFileOperation(_fileSystem, bundle, options);
AddChildOperation(newDownloader);
_downloaders.Add(bundle.BundleGUID, newDownloader);
}
else
{
newDownloader = new DownloadNormalFileOperation(_fileSystem, bundle, options);
AddChildOperation(newDownloader);
_downloaders.Add(bundle.BundleGUID, newDownloader);
}
}
return newDownloader;
}

View File

@@ -0,0 +1,221 @@
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
internal class DownloadLocalFileOperation : DefaultDownloadFileOperation
{
private readonly DefaultCacheFileSystem _fileSystem;
private VerifyTempFileOperation _verifyOperation;
private string _tempFilePath;
private ESteps _steps = ESteps.None;
internal DownloadLocalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
_tempFilePath = _fileSystem.GetTempFilePath(Bundle);
_steps = ESteps.CheckExists;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 检测文件是否存在
if (_steps == ESteps.CheckExists)
{
if (_fileSystem.Exists(Bundle))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
if (_fileSystem.CopyLocalFileServices != null)
_steps = ESteps.CopyBuildinBundle;
else
_steps = ESteps.CreateRequest;
}
}
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
FileUtility.CreateFileDirectory(_tempFilePath);
// 删除临时文件
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
// 获取请求地址
_requestURL = GetRequestURL();
// 重置请求
ResetRequestFiled();
// 创建下载器
CreateWebRequest();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
{
CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
_steps = ESteps.VerifyTempFile;
else
_steps = ESteps.TryAgain;
// 注意:最终释放请求器
DisposeWebRequest();
}
// 拷贝内置文件
if (_steps == ESteps.CopyBuildinBundle)
{
FileUtility.CreateFileDirectory(_tempFilePath);
// 删除临时文件
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
// 获取请求地址
_requestURL = GetRequestURL();
try
{
//TODO 团结引擎,在某些机型(红米),拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。
var localFileInfo = new LocalFileInfo();
localFileInfo.PackageName = _fileSystem.PackageName;
localFileInfo.BundleName = Bundle.BundleName;
localFileInfo.SourceFileURL = _requestURL;
_fileSystem.CopyLocalFileServices.CopyFile(localFileInfo, _tempFilePath);
if (File.Exists(_tempFilePath))
{
DownloadProgress = 1f;
DownloadedBytes = Bundle.FileSize;
Progress = DownloadProgress;
_steps = ESteps.VerifyTempFile;
}
else
{
Error = $"Failed copy local file : {_requestURL}";
_steps = ESteps.TryAgain;
}
}
catch (System.Exception ex)
{
Error = $"Failed copy local file : {ex.Message}";
_steps = ESteps.TryAgain;
}
}
// 验证下载文件
if (_steps == ESteps.VerifyTempFile)
{
var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize);
_verifyOperation = new VerifyTempFileOperation(element);
_verifyOperation.StartOperation();
AddChildOperation(_verifyOperation);
_steps = ESteps.CheckVerifyTempFile;
}
// 等待验证完成
if (_steps == ESteps.CheckVerifyTempFile)
{
if (IsWaitForAsyncComplete)
_verifyOperation.WaitForAsyncComplete();
_verifyOperation.UpdateOperation();
if (_verifyOperation.IsDone == false)
return;
if (_verifyOperation.Status == EOperationStatus.Succeed)
{
if (_fileSystem.WriteCacheBundleFile(Bundle, _tempFilePath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{_fileSystem.GetType().FullName} failed to write file !";
YooLogger.Error(Error);
}
}
else
{
_steps = ESteps.TryAgain;
Error = _verifyOperation.Error;
}
// 注意:验证完成后直接删除文件
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
//TODO 拷贝本地文件失败后不再尝试!
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
}
}
internal override void InternalAbort()
{
_steps = ESteps.Done;
DisposeWebRequest();
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
//TODO 等待导入或解压本地文件完毕,该操作会挂起主线程!
InternalUpdate();
if (IsDone)
break;
// 短暂休眠避免完全卡死
System.Threading.Thread.Sleep(1);
}
}
private void CreateWebRequest()
{
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
//注意引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
}
}

View File

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

View File

@@ -8,7 +8,6 @@ namespace YooAsset
{
private readonly DefaultCacheFileSystem _fileSystem;
private VerifyTempFileOperation _verifyOperation;
private bool _isReuqestLocalFile;
private string _tempFilePath;
private ESteps _steps = ESteps.None;
@@ -18,7 +17,6 @@ namespace YooAsset
}
internal override void InternalStart()
{
_isReuqestLocalFile = DownloadSystemHelper.IsRequestLocalFile(Options.MainURL);
_tempFilePath = _fileSystem.GetTempFilePath(Bundle);
_steps = ESteps.CheckExists;
}
@@ -133,15 +131,6 @@ namespace YooAsset
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
//TODO 拷贝本地文件失败后不再尝试!
if (_isReuqestLocalFile)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
@@ -168,20 +157,17 @@ namespace YooAsset
{
while (true)
{
//TODO 如果是导入或解压本地文件,执行等待完毕
if (_isReuqestLocalFile)
if (ExecuteWhileDone())
{
InternalUpdate();
if (IsDone)
break;
}
else
{
if (ExecuteWhileDone())
//TODO 尝试同步加载远端的资源文件失败
if (Status == EOperationStatus.Failed)
{
_steps = ESteps.Done;
break;
YooLogger.Error($"Try load bundle {Bundle.BundleName} from remote !");
YooLogger.Error($"The load remote bundle url : {_requestURL}");
}
_steps = ESteps.Done;
break;
}
}
}

View File

@@ -9,19 +9,16 @@ namespace YooAsset
private readonly DefaultCacheFileSystem _fileSystem;
private DownloadHandlerFileRange _downloadHandle;
private VerifyTempFileOperation _verifyOperation;
private bool _isReuqestLocalFile;
private long _fileOriginLength = 0;
private string _tempFilePath;
private ESteps _steps = ESteps.None;
internal DownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle, options)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
_isReuqestLocalFile = DownloadSystemHelper.IsRequestLocalFile(Options.MainURL);
_tempFilePath = _fileSystem.GetTempFilePath(Bundle);
_steps = ESteps.CheckExists;
}
@@ -152,15 +149,6 @@ namespace YooAsset
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
//TODO 拷贝本地文件失败后不再尝试!
if (_isReuqestLocalFile)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
@@ -187,20 +175,17 @@ namespace YooAsset
{
while (true)
{
//TODO 如果是导入或解压本地文件,执行等待完毕
if (_isReuqestLocalFile)
if (ExecuteWhileDone())
{
InternalUpdate();
if (IsDone)
break;
}
else
{
if (ExecuteWhileDone())
//TODO 尝试同步加载远端的资源文件失败
if (Status == EOperationStatus.Failed)
{
_steps = ESteps.Done;
break;
YooLogger.Error($"Try load bundle {Bundle.BundleName} from remote !");
YooLogger.Error($"The load remote bundle url : {_requestURL}");
}
_steps = ESteps.Done;
break;
}
}
}

View File

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

View File

@@ -71,10 +71,13 @@ namespace YooAsset
{
while (true)
{
//TODO 等待子线程验证文件完毕,该操作会挂起主线程
//TODO 等待子线程验证文件完毕,该操作会挂起主线程
InternalUpdate();
if (IsDone)
break;
// 短暂休眠避免完全卡死
System.Threading.Thread.Sleep(1);
}
}

View File

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

View File

@@ -3,11 +3,6 @@ namespace YooAsset
{
internal class DefaultUnpackFileSystemDefine
{
/// <summary>
/// 文件系统的优先级
/// </summary>
public const int DefaultPriority = 11;
/// <summary>
/// 保存的资源文件的文件夹名称
/// </summary>

View File

@@ -46,12 +46,17 @@ namespace YooAsset
/// <summary>
/// 自定义参数:跨域下载服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
public IRemoteServices RemoteServices { private set; get; }
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
#endregion
@@ -111,6 +116,10 @@ namespace YooAsset
{
DecryptionServices = (IWebDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");

View File

@@ -88,7 +88,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -61,6 +61,11 @@ namespace YooAsset
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
#endregion
@@ -116,6 +121,10 @@ namespace YooAsset
{
DecryptionServices = (IWebDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");

View File

@@ -33,10 +33,11 @@ namespace YooAsset
if (_loadCatalogFileOp == null)
{
#if UNITY_EDITOR
/*
// 兼容性初始化
// 说明:内置文件系统在编辑器下运行时需要动态生成
string packageRoot = _fileSystem.FileRoot;
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.PackageName, packageRoot);
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.ManifestServices, _fileSystem.PackageName, packageRoot);
if (result == false)
{
_steps = ESteps.Done;
@@ -44,6 +45,7 @@ namespace YooAsset
Error = $"Create package catalog file failed ! See the detail error in console !";
return;
}
*/
#endif
_loadCatalogFileOp = new LoadWebServerCatalogFileOperation(_fileSystem);

View File

@@ -85,7 +85,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -7,6 +7,7 @@ namespace YooAsset
public const string INSTALL_CLEAR_MODE = "INSTALL_CLEAR_MODE";
public const string REMOTE_SERVICES = "REMOTE_SERVICES";
public const string DECRYPTION_SERVICES = "DECRYPTION_SERVICES";
public const string MANIFEST_SERVICES = "MANIFEST_SERVICES";
public const string APPEND_FILE_EXTENSION = "APPEND_FILE_EXTENSION";
public const string DISABLE_CATALOG_FILE = "DISABLE_CATALOG_FILE";
public const string DISABLE_UNITY_WEB_CACHE = "DISABLE_UNITY_WEB_CACHE";
@@ -18,5 +19,6 @@ namespace YooAsset
public const string ASYNC_SIMULATE_MAX_FRAME = "ASYNC_SIMULATE_MAX_FRAME";
public const string COPY_BUILDIN_PACKAGE_MANIFEST = "COPY_BUILDIN_PACKAGE_MANIFEST";
public const string COPY_BUILDIN_PACKAGE_MANIFEST_DEST_ROOT = "COPY_BUILDIN_PACKAGE_MANIFEST_DEST_ROOT";
public const string COPY_LOCAL_FILE_SERVICES = "COPY_LOCAL_FILE_SERVICES";
}
}

View File

@@ -24,7 +24,7 @@ namespace YooAsset
public string FallbackURL { set; get; }
/// <summary>
/// 导入的本地文件路径
/// 拷贝的本地文件路径
/// </summary>
public string ImportFilePath { set; get; }

View File

@@ -11,6 +11,7 @@ namespace YooAsset
CheckExists,
CreateRequest,
CheckRequest,
CopyBuildinBundle,
VerifyTempFile,
CheckVerifyTempFile,
TryAgain,

View File

@@ -42,6 +42,11 @@ namespace YooAsset
/// 同时加载Bundle文件的最大并发数
/// </summary>
public int BundleLoadingMaxConcurrency = int.MaxValue;
/// <summary>
/// WebGL平台强制同步加载资源对象
/// </summary>
public bool WebGLForceSyncLoadAsset = false;
}
/// <summary>

View File

@@ -260,8 +260,11 @@ namespace YooAsset
StartOperation();
}
IsWaitForAsyncComplete = true;
InternalWaitForAsyncComplete();
if (IsWaitForAsyncComplete == false)
{
IsWaitForAsyncComplete = true;
InternalWaitForAsyncComplete();
}
}
#region

View File

@@ -14,7 +14,7 @@ namespace YooAsset
Done,
}
private readonly ResourceManager _resourceManager;
private readonly ResourceManager _resManager;
private readonly List<ProviderOperation> _providers = new List<ProviderOperation>(100);
private readonly List<ProviderOperation> _removeList = new List<ProviderOperation>(100);
private FSLoadBundleOperation _loadBundleOp;
@@ -53,7 +53,7 @@ namespace YooAsset
internal LoadBundleFileOperation(ResourceManager resourceManager, BundleInfo bundleInfo)
{
_resourceManager = resourceManager;
_resManager = resourceManager;
LoadBundleInfo = bundleInfo;
}
internal override void InternalStart()
@@ -73,7 +73,7 @@ namespace YooAsset
}
else
{
if (_resourceManager.BundleLoadingIsBusy())
if (_resManager.BundleLoadingIsBusy())
return;
_steps = ESteps.LoadBundleFile;
}
@@ -83,7 +83,7 @@ namespace YooAsset
{
if (_loadBundleOp == null)
{
_resourceManager.BundleLoadingCounter++;
_resManager.BundleLoadingCounter++;
_loadBundleOp = LoadBundleInfo.LoadBundleFile();
_loadBundleOp.StartOperation();
AddChildOperation(_loadBundleOp);
@@ -121,7 +121,7 @@ namespace YooAsset
}
// 统计计数减少
_resourceManager.BundleLoadingCounter--;
_resManager.BundleLoadingCounter--;
}
}
internal override void InternalWaitForAsyncComplete()
@@ -191,7 +191,7 @@ namespace YooAsset
{
foreach (var bundleID in LoadBundleInfo.Bundle.ReferenceBundleIDs)
{
if (_resourceManager.CheckBundleDestroyed(bundleID) == false)
if (_resManager.CheckBundleDestroyed(bundleID) == false)
return false;
}
}
@@ -233,7 +233,7 @@ namespace YooAsset
// 移除资源提供者
if (_removeList.Count > 0)
{
_resourceManager.RemoveBundleProviders(_removeList);
_resManager.RemoveBundleProviders(_removeList);
_removeList.Clear();
}
}

View File

@@ -15,6 +15,11 @@ namespace YooAsset
_loadAllAssetsOp = BundleResultObject.LoadAllAssetsAsync(MainAssetInfo);
_loadAllAssetsOp.StartOperation();
AddChildOperation(_loadAllAssetsOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
_loadAllAssetsOp.WaitForAsyncComplete();
#endif
}
if (IsWaitForAsyncComplete)

View File

@@ -15,6 +15,11 @@ namespace YooAsset
_loadAssetOp = BundleResultObject.LoadAssetAsync(MainAssetInfo);
_loadAssetOp.StartOperation();
AddChildOperation(_loadAssetOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
_loadAssetOp.WaitForAsyncComplete();
#endif
}
if (IsWaitForAsyncComplete)

View File

@@ -68,13 +68,14 @@ namespace YooAsset
private ESteps _steps = ESteps.None;
protected readonly ResourceManager _resManager;
private readonly LoadBundleFileOperation _mainBundleLoader;
private readonly List<LoadBundleFileOperation> _bundleLoaders = new List<LoadBundleFileOperation>(10);
private readonly HashSet<HandleBase> _handles = new HashSet<HandleBase>();
public ProviderOperation(ResourceManager manager, string providerGUID, AssetInfo assetInfo)
{
_resManager = manager;
ProviderGUID = providerGUID;
MainAssetInfo = assetInfo;

View File

@@ -15,6 +15,11 @@ namespace YooAsset
_loadSubAssetsOp = BundleResultObject.LoadSubAssetsAsync(MainAssetInfo);
_loadSubAssetsOp.StartOperation();
AddChildOperation(_loadSubAssetsOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
_loadSubAssetsOp.WaitForAsyncComplete();
#endif
}
if (IsWaitForAsyncComplete)

View File

@@ -15,6 +15,7 @@ namespace YooAsset
private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery;
private int _bundleLoadingMaxConcurrency;
private bool _webGLForceSyncLoadAsset;
/// <summary>
/// 所属包裹
@@ -43,6 +44,7 @@ namespace YooAsset
public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices)
{
_bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency;
_webGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset;
_bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
@@ -58,7 +60,7 @@ namespace YooAsset
/// <summary>
/// 尝试卸载指定资源的资源包(包括依赖资源)
/// </summary>
public void TryUnloadUnusedAsset(AssetInfo assetInfo)
public void TryUnloadUnusedAsset(AssetInfo assetInfo, int loopCount)
{
if (assetInfo.IsInvalid)
{
@@ -66,34 +68,39 @@ namespace YooAsset
return;
}
// 卸载主资源包加载器
string mainBundleName = _bundleQuery.GetMainBundleName(assetInfo);
var mainLoader = TryGetBundleFileLoader(mainBundleName);
if (mainLoader != null)
while (loopCount > 0)
{
mainLoader.TryDestroyProviders();
if (mainLoader.CanDestroyLoader())
{
string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName;
mainLoader.DestroyLoader();
LoaderDic.Remove(bundleName);
}
}
loopCount--;
// 卸载依赖资源包加载器
string[] dependBundleNames = _bundleQuery.GetDependBundleNames(assetInfo);
foreach (var dependBundleName in dependBundleNames)
{
var dependLoader = TryGetBundleFileLoader(dependBundleName);
if (dependLoader != null)
// 卸载资源包加载器
string mainBundleName = _bundleQuery.GetMainBundleName(assetInfo);
var mainLoader = TryGetBundleFileLoader(mainBundleName);
if (mainLoader != null)
{
if (dependLoader.CanDestroyLoader())
mainLoader.TryDestroyProviders();
if (mainLoader.CanDestroyLoader())
{
string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName;
dependLoader.DestroyLoader();
string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName;
mainLoader.DestroyLoader();
LoaderDic.Remove(bundleName);
}
}
// 卸载依赖资源包加载器
string[] dependBundleNames = _bundleQuery.GetDependBundleNames(assetInfo);
foreach (var dependBundleName in dependBundleNames)
{
var dependLoader = TryGetBundleFileLoader(dependBundleName);
if (dependLoader != null)
{
if (dependLoader.CanDestroyLoader())
{
string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName;
dependLoader.DestroyLoader();
LoaderDic.Remove(bundleName);
}
}
}
}
}
@@ -321,6 +328,10 @@ namespace YooAsset
{
return BundleLoadingCounter >= _bundleLoadingMaxConcurrency;
}
internal bool WebGLForceSyncLoadAsset()
{
return _webGLForceSyncLoadAsset;
}
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
{

View File

@@ -44,7 +44,7 @@ namespace YooAsset
/// <summary>
/// 序列化(二进制文件)
/// </summary>
public static void SerializeToBinary(string savePath, PackageManifest manifest)
public static void SerializeToBinary(string savePath, PackageManifest manifest, IManifestServices services)
{
using (FileStream fs = new FileStream(savePath, FileMode.Create))
{
@@ -96,9 +96,20 @@ namespace YooAsset
buffer.WriteInt32Array(packageBundle.DependBundleIDs);
}
// 写入文件流
buffer.WriteToStream(fs);
fs.Flush();
// 清单处理操作
if (services != null)
{
var tempBytes = buffer.GetBytes();
var resultBytes = services.ProcessManifest(tempBytes);
fs.Write(resultBytes, 0, resultBytes.Length);
fs.Flush();
}
else
{
// 写入文件流
buffer.WriteToStream(fs);
fs.Flush();
}
}
}
@@ -113,10 +124,19 @@ namespace YooAsset
/// <summary>
/// 反序列化(二进制文件)
/// </summary>
public static PackageManifest DeserializeFromBinary(byte[] binaryData)
public static PackageManifest DeserializeFromBinary(byte[] binaryData, IManifestServices services)
{
// 创建缓存器
BufferReader buffer = new BufferReader(binaryData);
BufferReader buffer;
if (services != null)
{
var resultBytes = services.RestoreManifest(binaryData);
buffer = new BufferReader(resultBytes);
}
else
{
buffer = new BufferReader(binaryData);
}
// 读取文件标记
uint fileSign = buffer.ReadUInt32();

View File

@@ -10,6 +10,7 @@ namespace YooAsset
private enum ESteps
{
None,
RestoreFileData,
DeserializeFileHeader,
PrepareAssetList,
DeserializeAssetList,
@@ -19,7 +20,9 @@ namespace YooAsset
Done,
}
private readonly BufferReader _buffer;
private readonly IManifestServices _services;
private byte[] _sourceData;
private BufferReader _buffer;
private int _packageAssetCount;
private int _packageBundleCount;
private int _progressTotalValue;
@@ -30,13 +33,14 @@ namespace YooAsset
/// </summary>
public PackageManifest Manifest { private set; get; }
public DeserializeManifestOperation(byte[] binaryData)
public DeserializeManifestOperation(IManifestServices services, byte[] binaryData)
{
_buffer = new BufferReader(binaryData);
_services = services;
_sourceData = binaryData;
}
internal override void InternalStart()
{
_steps = ESteps.DeserializeFileHeader;
_steps = ESteps.RestoreFileData;
}
internal override void InternalUpdate()
{
@@ -45,6 +49,19 @@ namespace YooAsset
try
{
if (_steps == ESteps.RestoreFileData)
{
if (_services != null)
{
var resultData = _services.RestoreManifest(_sourceData);
if (resultData != null)
_sourceData = resultData;
}
_buffer = new BufferReader(_sourceData);
_steps = ESteps.DeserializeFileHeader;
}
if (_steps == ESteps.DeserializeFileHeader)
{
if (_buffer.IsValid == false)

View File

@@ -361,21 +361,21 @@ namespace YooAsset
/// 资源回收
/// 说明:尝试卸载指定的资源
/// </summary>
public void TryUnloadUnusedAsset(string location)
public void TryUnloadUnusedAsset(string location, int loopCount = 10)
{
DebugCheckInitialize();
AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null);
_resourceManager.TryUnloadUnusedAsset(assetInfo);
_resourceManager.TryUnloadUnusedAsset(assetInfo, loopCount);
}
/// <summary>
/// 资源回收
/// 说明:尝试卸载指定的资源
/// </summary>
public void TryUnloadUnusedAsset(AssetInfo assetInfo)
public void TryUnloadUnusedAsset(AssetInfo assetInfo, int loopCount = 10)
{
DebugCheckInitialize();
_resourceManager.TryUnloadUnusedAsset(assetInfo);
_resourceManager.TryUnloadUnusedAsset(assetInfo, loopCount);
}
#endregion

View File

@@ -0,0 +1,30 @@

namespace YooAsset
{
public struct LocalFileInfo
{
/// <summary>
/// 包裹名称
/// </summary>
public string PackageName;
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
/// <summary>
/// 源文件请求地址
/// </summary>
public string SourceFileURL;
}
/// <summary>
/// 本地文件拷贝服务类
/// 备注:包体内文件拷贝,沙盒内文件导入都会触发该服务!
/// </summary>
public interface ICopyLocalFileServices
{
void CopyFile(LocalFileInfo sourceFileInfo, string destFilePath);
}
}

View File

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

View File

@@ -42,15 +42,23 @@ namespace YooAsset
public interface IDecryptionServices
{
/// <summary>
/// 同步方式获取解密的资源包对象
/// 同步方式获取解密的资源包
/// </summary>
DecryptResult LoadAssetBundle(DecryptFileInfo fileInfo);
/// <summary>
/// 异步方式获取解密的资源包对象
/// 异步方式获取解密的资源包
/// </summary>
DecryptResult LoadAssetBundleAsync(DecryptFileInfo fileInfo);
/// <summary>
/// 后备方式获取解密的资源包
/// 注意:当正常解密方法失败后,会触发后备加载!
/// 说明建议通过LoadFromMemory()方法加载资源包作为保底机制。
/// issues : https://github.com/tuyoogame/YooAsset/issues/562
/// </summary>
DecryptResult LoadAssetBundleFallback(DecryptFileInfo fileInfo);
/// <summary>
/// 获取解密的字节数据
/// </summary>

View File

@@ -1,6 +1,18 @@

namespace YooAsset
{
public struct EncryptFileInfo
{
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
/// <summary>
/// 文件路径
/// </summary>
public string FileLoadPath;
}
public struct EncryptResult
{
/// <summary>
@@ -14,19 +26,6 @@ namespace YooAsset
public byte[] EncryptedData;
}
public struct EncryptFileInfo
{
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
/// <summary>
/// 文件路径
/// </summary>
public string FileLoadPath;
}
public interface IEncryptionServices
{
EncryptResult Encrypt(EncryptFileInfo fileInfo);

View File

@@ -0,0 +1,19 @@

namespace YooAsset
{
/// <summary>
/// 资源清单文件处理服务接口
/// </summary>
public interface IManifestServices
{
/// <summary>
/// 处理资源清单(压缩和加密)
/// </summary>
byte[] ProcessManifest(byte[] fileData);
/// <summary>
/// 还原资源清单(解压和解密)
/// </summary>
byte[] RestoreManifest(byte[] fileData);
}
}

View File

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

View File

@@ -36,6 +36,16 @@ namespace YooAsset
_index = 0;
}
/// <summary>
/// 获取有效数据
/// </summary>
public byte[] GetBytes()
{
byte[] newArray = new byte[_index];
Buffer.BlockCopy(_buffer, 0, newArray, 0, _index);
return newArray;
}
/// <summary>
/// 将有效数据写入文件流
/// </summary>

View File

@@ -34,6 +34,20 @@ namespace YooAsset
return str.Remove(index); //"assets/config/test.unity3d" --> "assets/config/test"
}
/// <summary>
/// URL地址是否包含双斜杠
/// 注意:只检查协议之后的部分
/// </summary>
public static bool HasDoubleSlashes(string url)
{
if (url == null)
throw new ArgumentNullException();
int protocolIndex = url.IndexOf("://");
string partToCheck = protocolIndex == -1 ? url : url.Substring(protocolIndex + 3);
return partToCheck.Contains("//") || partToCheck.Contains(@"\\");
}
/// <summary>
/// 合并路径
/// </summary>

View File

@@ -63,6 +63,29 @@ namespace YooAsset
}
}
/// <summary>
/// 销毁资源系统
/// </summary>
public static void Destroy()
{
if (_isInitialize)
{
_isInitialize = false;
if (_driver != null)
GameObject.Destroy(_driver);
// 终止并清空所有包裹的异步操作
ClearAllPackageOperation();
// 卸载所有AssetBundle
AssetBundle.UnloadAllAssetBundles(true);
// 清空资源包裹列表
_packages.Clear();
}
}
/// <summary>
/// 更新资源系统
/// </summary>
@@ -75,11 +98,10 @@ namespace YooAsset
}
/// <summary>
/// 应用程序退出处理
/// 终止并清空所有包裹的异步操作
/// </summary>
internal static void OnApplicationQuit()
internal static void ClearAllPackageOperation()
{
// 说明在编辑器下确保播放被停止时IO类操作被终止。
foreach (var package in _packages)
{
OperationSystem.ClearPackageOperation(package.PackageName);

View File

@@ -24,7 +24,8 @@ namespace YooAsset
#if UNITY_EDITOR
void OnApplicationQuit()
{
YooAssets.OnApplicationQuit();
// 说明在编辑器下确保播放被停止时IO类操作被终止。
YooAssets.ClearAllPackageOperation();
}
#endif