mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-17 05:10:12 +00:00
refactor : 重构代码
This commit is contained in:
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.cs text eol=lf
|
||||
BIN
Assets/YooAsset.zip
Normal file
BIN
Assets/YooAsset.zip
Normal file
Binary file not shown.
@@ -204,7 +204,7 @@ namespace YooAsset.Editor
|
||||
packageBundle.FileHash = PackageFileHash;
|
||||
packageBundle.FileCRC = PackageFileCRC;
|
||||
packageBundle.FileSize = PackageFileSize;
|
||||
packageBundle.Encrypted = Encrypted;
|
||||
packageBundle.IsEncrypted = Encrypted;
|
||||
return packageBundle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace YooAsset.Editor
|
||||
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
|
||||
string buildPackageName = buildParametersContext.Parameters.PackageName;
|
||||
var manifestServices = buildParametersContext.Parameters.ManifestRestoreServices;
|
||||
CatalogFileTools.CreateFile(manifestServices, buildPackageName, buildinRootDirectory);
|
||||
BuiltinFileCatalogTools.CreateFile(manifestServices, buildPackageName, buildinRootDirectory);
|
||||
|
||||
// 刷新目录
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace YooAsset.Editor
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
PackageManifestTools.SerializeToJson(filePath, manifest);
|
||||
PackageManifestTools.SerializeManifestToJson(filePath, manifest);
|
||||
BuildLogger.Log($"Create package manifest file: {filePath}");
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ namespace YooAsset.Editor
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
packagePath = $"{packageOutputDirectory}/{fileName}";
|
||||
PackageManifestTools.SerializeToBinary(packagePath, manifest, buildParameters.ManifestProcessServices);
|
||||
packageHash = HashUtility.FileCRC32(packagePath);
|
||||
PackageManifestTools.SerializeManifestToBinary(packagePath, manifest, buildParameters.ManifestProcessServices);
|
||||
packageHash = HashUtility.ComputeFileCRC32(packagePath);
|
||||
BuildLogger.Log($"Create package manifest file: {packagePath}");
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace YooAsset.Editor
|
||||
{
|
||||
ManifestContext manifestContext = new ManifestContext();
|
||||
byte[] bytesData = FileUtility.ReadAllBytes(packagePath);
|
||||
manifestContext.Manifest = PackageManifestTools.DeserializeFromBinary(bytesData, buildParameters.ManifestRestoreServices);
|
||||
manifestContext.Manifest = PackageManifestTools.DeserializeManifestFromBinary(bytesData, buildParameters.ManifestRestoreServices);
|
||||
context.SetContextObject(manifestContext);
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ namespace YooAsset.Editor
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
var mainAssetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
|
||||
packageAsset.DependBundleIDs = GetAssetDependBundleIDs(mainAssetInfo);
|
||||
packageAsset.DependentBundleIDs = GetAssetDependBundleIDs(mainAssetInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace YooAsset.Editor
|
||||
|
||||
// 排序并填充数据
|
||||
dependIDs.Sort();
|
||||
packageBundle.DependBundleIDs = dependIDs.ToArray();
|
||||
packageBundle.DependentBundleIDs = dependIDs.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,9 +249,9 @@ namespace YooAsset.Editor
|
||||
var assetTags = packageAsset.AssetTags;
|
||||
int bundleID = packageAsset.BundleID;
|
||||
CacheBundleTags(bundleID, assetTags);
|
||||
if (packageAsset.DependBundleIDs != null)
|
||||
if (packageAsset.DependentBundleIDs != null)
|
||||
{
|
||||
foreach (var dependBundleID in packageAsset.DependBundleIDs)
|
||||
foreach (var dependBundleID in packageAsset.DependentBundleIDs)
|
||||
{
|
||||
CacheBundleTags(dependBundleID, assetTags);
|
||||
}
|
||||
@@ -359,11 +359,11 @@ namespace YooAsset.Editor
|
||||
{
|
||||
if (cacheBundleIDs.Contains(packageAsset.BundleID))
|
||||
{
|
||||
if (packageAsset.DependBundleIDs.Contains(builtinBundleID) == false)
|
||||
if (packageAsset.DependentBundleIDs.Contains(builtinBundleID) == false)
|
||||
{
|
||||
var tempBundleIDs = new List<int>(packageAsset.DependBundleIDs);
|
||||
var tempBundleIDs = new List<int>(packageAsset.DependentBundleIDs);
|
||||
tempBundleIDs.Add(builtinBundleID);
|
||||
packageAsset.DependBundleIDs = tempBundleIDs.ToArray();
|
||||
packageAsset.DependentBundleIDs = tempBundleIDs.ToArray();
|
||||
}
|
||||
|
||||
foreach (var tag in packageAsset.AssetTags)
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace YooAsset.Editor
|
||||
reportBundleInfo.FileHash = packageBundle.FileHash;
|
||||
reportBundleInfo.FileCRC = packageBundle.FileCRC;
|
||||
reportBundleInfo.FileSize = packageBundle.FileSize;
|
||||
reportBundleInfo.Encrypted = packageBundle.Encrypted;
|
||||
reportBundleInfo.Encrypted = packageBundle.IsEncrypted;
|
||||
reportBundleInfo.Tags = packageBundle.Tags;
|
||||
reportBundleInfo.DependBundles = GetBundleDependBundles(manifest, packageBundle);
|
||||
reportBundleInfo.ReferenceBundles = GetBundleReferenceBundles(manifest, packageBundle);
|
||||
@@ -145,8 +145,8 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
private List<string> GetAssetDependBundles(PackageManifest manifest, PackageAsset packageAsset)
|
||||
{
|
||||
List<string> dependBundles = new List<string>(packageAsset.DependBundleIDs.Length);
|
||||
foreach (int index in packageAsset.DependBundleIDs)
|
||||
List<string> dependBundles = new List<string>(packageAsset.DependentBundleIDs.Length);
|
||||
foreach (int index in packageAsset.DependentBundleIDs)
|
||||
{
|
||||
string dependBundleName = manifest.BundleList[index].BundleName;
|
||||
dependBundles.Add(dependBundleName);
|
||||
@@ -160,8 +160,8 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
private List<string> GetBundleDependBundles(PackageManifest manifest, PackageBundle packageBundle)
|
||||
{
|
||||
List<string> dependBundles = new List<string>(packageBundle.DependBundleIDs.Length);
|
||||
foreach (int index in packageBundle.DependBundleIDs)
|
||||
List<string> dependBundles = new List<string>(packageBundle.DependentBundleIDs.Length);
|
||||
foreach (int index in packageBundle.DependentBundleIDs)
|
||||
{
|
||||
string dependBundleName = manifest.BundleList[index].BundleName;
|
||||
dependBundles.Add(dependBundleName);
|
||||
@@ -218,7 +218,7 @@ namespace YooAsset.Editor
|
||||
int fileCount = 0;
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
if (packageBundle.Encrypted)
|
||||
if (packageBundle.IsEncrypted)
|
||||
fileCount++;
|
||||
}
|
||||
return fileCount;
|
||||
@@ -228,7 +228,7 @@ namespace YooAsset.Editor
|
||||
long fileBytes = 0;
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
if (packageBundle.Encrypted)
|
||||
if (packageBundle.IsEncrypted)
|
||||
fileBytes += packageBundle.FileSize;
|
||||
}
|
||||
return fileBytes;
|
||||
|
||||
@@ -43,12 +43,12 @@ namespace YooAsset.Editor
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
return HashUtility.ComputeFileMD5(filePath);
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileCRC32Value(filePath);
|
||||
return HashUtility.ComputeFileCRC32AsUInt(filePath);
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace YooAsset.Editor
|
||||
private string GetFilePathTempHash(string filePath)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(filePath);
|
||||
return HashUtility.BytesMD5(bytes);
|
||||
return HashUtility.ComputeBytesMD5(bytes);
|
||||
|
||||
// 注意:在文件路径的哈希值冲突的情况下,可以使用下面的方法
|
||||
//return $"{HashUtility.BytesMD5(bytes)}-{Guid.NewGuid():N}";
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace YooAsset.Editor
|
||||
else
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
return HashUtility.ComputeFileMD5(filePath);
|
||||
}
|
||||
}
|
||||
protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
@@ -44,13 +44,13 @@ namespace YooAsset.Editor
|
||||
else
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
return HashUtility.ComputeFileMD5(filePath);
|
||||
}
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileCRC32Value(filePath);
|
||||
return HashUtility.ComputeFileCRC32AsUInt(filePath);
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
@@ -60,10 +60,10 @@ namespace YooAsset.Editor
|
||||
|
||||
private string GetFileMD5IncludePath(string filePath)
|
||||
{
|
||||
string pathHash = HashUtility.StringMD5(filePath.ToLowerInvariant());
|
||||
string contentHash = HashUtility.FileMD5(filePath);
|
||||
string pathHash = HashUtility.ComputeMD5(filePath.ToLowerInvariant());
|
||||
string contentHash = HashUtility.ComputeFileMD5(filePath);
|
||||
string combined = pathHash + contentHash;
|
||||
return HashUtility.StringMD5(combined);
|
||||
return HashUtility.ComputeMD5(combined);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,12 +43,12 @@ namespace YooAsset.Editor
|
||||
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
return HashUtility.ComputeFileMD5(filePath);
|
||||
}
|
||||
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileCRC32Value(filePath);
|
||||
return HashUtility.ComputeFileCRC32AsUInt(filePath);
|
||||
}
|
||||
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace YooAsset.Editor
|
||||
if (File.Exists(_logFilePath))
|
||||
File.Delete(_logFilePath);
|
||||
|
||||
FileUtility.CreateFileDirectory(_logFilePath);
|
||||
FileUtility.EnsureFileDirectory(_logFilePath);
|
||||
File.WriteAllText(_logFilePath, _logBuilder.ToString(), Encoding.UTF8);
|
||||
_logBuilder.Clear();
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace YooAsset.Editor
|
||||
EditorConnection.instance.UnregisterConnection(OnHandleConnectionEvent);
|
||||
EditorConnection.instance.UnregisterDisconnection(OnHandleDisconnectionEvent);
|
||||
EditorConnection.instance.Unregister(DiagnosticSystemDefine.PlayerToEditorMessageId, OnHandlePlayerMessage);
|
||||
MockEditorConnection.Instance.Unregister(DiagnosticSystemDefine.PlayerToEditorMessageId);
|
||||
MockEditorConnection.Instance.Unregister(DiagnosticSystemDefine.PlayerToEditorMessageId, OnHandlePlayerMessage);
|
||||
_playerSessions.Clear();
|
||||
}
|
||||
public void Update()
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace YooAsset
|
||||
public float Progress { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务逻辑是否完成(Status为Succeed、Failed或Aborted)
|
||||
/// 任务逻辑是否完成(Status为Succeeded、Failed或Aborted)
|
||||
/// </summary>
|
||||
public bool IsDone
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace YooAsset
|
||||
{
|
||||
try
|
||||
{
|
||||
//注意:任务已完成,立即调用回调
|
||||
// 注意:任务已完成,立即调用回调
|
||||
value.Invoke(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -162,7 +162,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
internal virtual void InternalWaitForCompletion()
|
||||
{
|
||||
throw new YooInternalException($"InternalWaitForCompletion not implemented : {this.GetType().Name}");
|
||||
throw new YooInternalException($"InternalWaitForCompletion() is not implemented: {this.GetType().Name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -183,17 +183,17 @@ namespace YooAsset
|
||||
|
||||
#if UNITY_EDITOR || DEBUG
|
||||
if (child == null)
|
||||
throw new YooInternalException("The child node is null.");
|
||||
throw new YooInternalException("Child operation is null.");
|
||||
|
||||
if (ReferenceEquals(child, this))
|
||||
throw new YooInternalException("The child node cannot be itself.");
|
||||
throw new YooInternalException("Cannot add operation as its own child.");
|
||||
|
||||
if (_children.Contains(child))
|
||||
throw new YooInternalException($"The child node {child.GetType().Name} already exists.");
|
||||
throw new YooInternalException($"Child operation {child.GetType().Name} already exists.");
|
||||
|
||||
// 禁止形成环依赖
|
||||
if (WouldCreateCycle(child))
|
||||
throw new YooInternalException($"AddChildOperation would create a cycle : {this.GetType().Name} -> {child.GetType().Name}");
|
||||
throw new YooInternalException($"Adding {child.GetType().Name} would create a circular dependency with {this.GetType().Name}.");
|
||||
#endif
|
||||
|
||||
_children.Add(child);
|
||||
@@ -209,10 +209,10 @@ namespace YooAsset
|
||||
|
||||
#if UNITY_EDITOR || DEBUG
|
||||
if (child == null)
|
||||
throw new YooInternalException("The child node is null.");
|
||||
throw new YooInternalException("Child operation is null.");
|
||||
|
||||
if (_children.Contains(child) == false)
|
||||
throw new YooInternalException($"The child node {child.GetType().Name} not exists.");
|
||||
throw new YooInternalException($"Child operation {child.GetType().Name} does not exist.");
|
||||
#endif
|
||||
|
||||
_children.Remove(child);
|
||||
@@ -247,7 +247,7 @@ namespace YooAsset
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = ex.ToString();
|
||||
YooLogger.Error($"Exception in {this.GetType().Name}.InternalStart : {ex}");
|
||||
YooLogger.Error($"Exception in {this.GetType().Name}.InternalStart: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,7 +273,7 @@ namespace YooAsset
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = ex.ToString();
|
||||
YooLogger.Error($"Exception in {this.GetType().Name}.InternalUpdate : {ex}");
|
||||
YooLogger.Error($"Exception in {this.GetType().Name}.InternalUpdate: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,11 +300,11 @@ namespace YooAsset
|
||||
{
|
||||
InternalAbort();
|
||||
Status = EOperationStatus.Aborted;
|
||||
Error = "user abort";
|
||||
Error = "Aborted by user";
|
||||
YooLogger.Warning($"Async operation {this.GetType().Name} has been aborted.");
|
||||
}
|
||||
|
||||
//注意:强制收尾,确保Task能完成
|
||||
// 注意:强制收尾,确保Task能完成
|
||||
FinishOperation();
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ namespace YooAsset
|
||||
if (IsDone)
|
||||
break;
|
||||
|
||||
// 注意: 短暂休眠避免完全占用CPU资源
|
||||
// 注意:短暂休眠避免完全占用CPU资源
|
||||
System.Threading.Thread.Sleep(sleepMS);
|
||||
}
|
||||
}
|
||||
@@ -407,7 +407,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public void WaitForCompletion()
|
||||
{
|
||||
//注意:防止异步操作被挂起陷入无限死循环!
|
||||
// 注意:防止异步操作被挂起陷入无限死循环
|
||||
if (Status == EOperationStatus.None)
|
||||
{
|
||||
StartOperation();
|
||||
@@ -423,11 +423,11 @@ namespace YooAsset
|
||||
if (IsDone == false)
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Operation {this.GetType().Name} failed to wait for async complete.";
|
||||
Error = $"Operation {this.GetType().Name} failed to wait for completion.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
|
||||
//注意:强制收尾,确保Task能完成
|
||||
// 注意:强制收尾,确保Task能完成
|
||||
FinishOperation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace YooAsset
|
||||
if (_maxTimeSlice == long.MaxValue)
|
||||
return false;
|
||||
|
||||
// 注意 : 单次调用开销约1微秒
|
||||
// 注意:单次调用开销约1微秒
|
||||
return _stopwatch.ElapsedMilliseconds - _frameStartTime >= _maxTimeSlice;
|
||||
}
|
||||
}
|
||||
@@ -265,7 +265,7 @@ namespace YooAsset
|
||||
throw new YooInternalException("Package name is null or empty.");
|
||||
|
||||
if (_isInitialized == false)
|
||||
throw new YooInternalException($"{nameof(AsyncOperationSystem)} not initialized.");
|
||||
throw new YooInternalException($"{nameof(AsyncOperationSystem)} is not initialized.");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace YooAsset
|
||||
private void OnDisable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
MockPlayerConnection.Instance.Unregister(DiagnosticSystemDefine.EditorToPlayerMessageId);
|
||||
MockPlayerConnection.Instance.Unregister(DiagnosticSystemDefine.EditorToPlayerMessageId, HandleEditorMessage);
|
||||
#else
|
||||
PlayerConnection.instance.Unregister(DiagnosticSystemDefine.EditorToPlayerMessageId, HandleEditorMessage);
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace YooAsset
|
||||
|
||||
/// <summary>
|
||||
/// 子任务列表
|
||||
/// TODO : Serialization depth limit 10 exceeded
|
||||
/// TODO:序列化深度限制为10层
|
||||
/// </summary>
|
||||
public List<DiagnosticOperationInfo> Children;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
@@ -63,7 +63,8 @@ namespace YooAsset
|
||||
/// 注销消息处理回调
|
||||
/// </summary>
|
||||
/// <param name="messageID">消息标识符</param>
|
||||
public void Unregister(Guid messageID)
|
||||
/// <param name="callback">要注销的回调函数</param>
|
||||
public void Unregister(Guid messageID, UnityAction<MessageEventArgs> callback)
|
||||
{
|
||||
if (_messageHandlers.ContainsKey(messageID))
|
||||
_messageHandlers.Remove(messageID);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
@@ -63,7 +63,8 @@ namespace YooAsset
|
||||
/// 注销消息处理回调
|
||||
/// </summary>
|
||||
/// <param name="messageID">消息标识符</param>
|
||||
public void Unregister(Guid messageID)
|
||||
/// <param name="callback">要注销的回调函数</param>
|
||||
public void Unregister(Guid messageID, UnityAction<MessageEventArgs> callback)
|
||||
{
|
||||
if (_messageHandlers.ContainsKey(messageID))
|
||||
_messageHandlers.Remove(messageID);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
public readonly string Url;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒)
|
||||
@@ -91,7 +91,7 @@ namespace YooAsset
|
||||
bool removeFileOnAbort = true,
|
||||
long resumeOffset = 0)
|
||||
{
|
||||
URL = url;
|
||||
Url = url;
|
||||
SavePath = savePath;
|
||||
Timeout = timeout;
|
||||
WatchdogTimeout = watchdogTimeout;
|
||||
@@ -104,6 +104,8 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 添加请求头数据
|
||||
/// </summary>
|
||||
/// <param name="name">请求头名称(如 "Authorization"、"User-Agent")</param>
|
||||
/// <param name="value">请求头值</param>
|
||||
public void AddRequestHeader(string name, string value)
|
||||
{
|
||||
if (Headers == null)
|
||||
@@ -124,7 +126,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
public readonly string Url;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒)
|
||||
@@ -164,7 +166,7 @@ namespace YooAsset
|
||||
/// <param name="watchdogTimeout">看门狗超时时间(秒),0 表示禁用</param>
|
||||
public DownloadDataRequestArgs(string url, int timeout, int watchdogTimeout)
|
||||
{
|
||||
URL = url;
|
||||
Url = url;
|
||||
Timeout = timeout;
|
||||
WatchdogTimeout = watchdogTimeout;
|
||||
Headers = null;
|
||||
@@ -173,6 +175,8 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 添加请求头数据
|
||||
/// </summary>
|
||||
/// <param name="name">请求头名称(如 "Authorization"、"User-Agent")</param>
|
||||
/// <param name="value">请求头值</param>
|
||||
public void AddRequestHeader(string name, string value)
|
||||
{
|
||||
if (Headers == null)
|
||||
@@ -193,7 +197,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
public readonly string Url;
|
||||
|
||||
/// <summary>
|
||||
/// 响应的超时时间(单位:秒)
|
||||
@@ -232,7 +236,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// Unity CRC 校验值
|
||||
/// </summary>
|
||||
public readonly uint UnityCRC;
|
||||
public readonly uint UnityCrc;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义请求头(可选)
|
||||
@@ -260,18 +264,20 @@ namespace YooAsset
|
||||
string fileHash = null,
|
||||
uint unityCrc = 0)
|
||||
{
|
||||
URL = url;
|
||||
Url = url;
|
||||
Timeout = timeout;
|
||||
WatchdogTimeout = watchdogTimeout;
|
||||
DisableUnityWebCache = disableUnityWebCache;
|
||||
FileHash = fileHash;
|
||||
UnityCRC = unityCrc;
|
||||
UnityCrc = unityCrc;
|
||||
Headers = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加请求头数据
|
||||
/// </summary>
|
||||
/// <param name="name">请求头名称(如 "Authorization"、"User-Agent")</param>
|
||||
/// <param name="value">请求头值</param>
|
||||
public void AddRequestHeader(string name, string value)
|
||||
{
|
||||
if (Headers == null)
|
||||
@@ -286,12 +292,12 @@ namespace YooAsset
|
||||
/// <remarks>
|
||||
/// 用于编辑器模式下模拟下载进度,不进行实际网络请求。
|
||||
/// </remarks>
|
||||
internal struct DownloadSimulateRequestArgs
|
||||
internal struct SimulateDownloadRequestArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址(仅用于标识)
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
public readonly string Url;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟的文件大小(字节)
|
||||
@@ -312,9 +318,9 @@ namespace YooAsset
|
||||
/// <param name="url">请求地址(仅用于标识)</param>
|
||||
/// <param name="fileSize">模拟的文件大小(字节)</param>
|
||||
/// <param name="downloadSpeed">模拟的下载速度(字节/秒),默认 1MB/s</param>
|
||||
public DownloadSimulateRequestArgs(string url, long fileSize, long downloadSpeed = 1024 * 1024)
|
||||
public SimulateDownloadRequestArgs(string url, long fileSize, long downloadSpeed = 1024 * 1024)
|
||||
{
|
||||
URL = url;
|
||||
Url = url;
|
||||
FileSize = fileSize;
|
||||
DownloadSpeed = downloadSpeed > 0 ? downloadSpeed : 1024 * 1024;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
/// <param name="path">本地文件路径</param>
|
||||
/// <returns>可用于 UnityWebRequest 的文件协议 URL</returns>
|
||||
public static string ToLocalURL(string path)
|
||||
public static string ToLocalUrl(string path)
|
||||
{
|
||||
string url;
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace YooAsset
|
||||
// 说明:iPhone和iPod对应的是iOS系统。
|
||||
// 说明:iPad对应的是iPadOS系统。
|
||||
// 说明:AppleTV对应的是tvOS系统。
|
||||
// TODO 安卓平台未考虑外部存储器
|
||||
// TODO Linux平台确认路径正确
|
||||
#if UNITY_EDITOR_OSX
|
||||
url = StringUtility.Format("file://{0}", path);
|
||||
#elif UNITY_EDITOR_WIN
|
||||
@@ -75,7 +77,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
/// <param name="url">要判断的 URL</param>
|
||||
/// <returns>如果是本地文件 URL 返回 true,否则返回 false</returns>
|
||||
public static bool IsLocalFileURL(string url)
|
||||
public static bool IsLocalFileUrl(string url)
|
||||
{
|
||||
//TODO UNITY_STANDALONE_OSX平台目前无法确定
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 已成功
|
||||
/// </summary>
|
||||
Succeed,
|
||||
Succeeded,
|
||||
|
||||
/// <summary>
|
||||
/// 已失败
|
||||
|
||||
@@ -73,6 +73,6 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
/// <param name="args">模拟下载参数</param>
|
||||
/// <returns>模拟下载请求实例</returns>
|
||||
IDownloadFileRequest CreateSimulateRequest(DownloadSimulateRequestArgs args);
|
||||
IDownloadFileRequest CreateSimulateRequest(SimulateDownloadRequestArgs args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,22 +5,16 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 可轮询的下载请求接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 上层通常在每帧检查 IsDone 属性,完成后读取结果并调用 Dispose() 释放资源。
|
||||
/// </remarks>
|
||||
internal interface IDownloadRequest : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
string URL { get; }
|
||||
string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否完成(成功/失败/中止)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 注意:访问此属性时会自动调用 PollingRequest() 进行轮询。
|
||||
/// </remarks>
|
||||
bool IsDone { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -65,11 +59,6 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
void SendRequest();
|
||||
|
||||
/// <summary>
|
||||
/// 轮询请求
|
||||
/// </summary>
|
||||
void PollingRequest();
|
||||
|
||||
/// <summary>
|
||||
/// 中止请求
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf9991076b60f0f459846f54b0ca6698
|
||||
guid: cc2d6a25257866e459a31ad41ea97d58
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class DownloadAndCacheFileOperation : AsyncOperationBase
|
||||
internal abstract class DownloadFileBaseOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 引用计数
|
||||
/// 资源包对象
|
||||
/// </summary>
|
||||
public int RefCount { private set; get; }
|
||||
public readonly PackageBundle Bundle;
|
||||
|
||||
/// <summary>
|
||||
/// 下载地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
public readonly string Url;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度
|
||||
@@ -23,9 +23,15 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public long DownloadedBytes { get; protected set; }
|
||||
|
||||
public DownloadAndCacheFileOperation(string url)
|
||||
/// <summary>
|
||||
/// 引用计数
|
||||
/// </summary>
|
||||
public int RefCount { private set; get; }
|
||||
|
||||
public DownloadFileBaseOperation(PackageBundle bundle, string url)
|
||||
{
|
||||
URL = url;
|
||||
Bundle = bundle;
|
||||
Url = url;
|
||||
}
|
||||
internal override string InternalGetDescription()
|
||||
{
|
||||
@@ -11,9 +11,17 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal class DownloadSchedulerOperation : AsyncOperationBase, IDisposable
|
||||
{
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly Dictionary<string, DownloadAndCacheFileOperation> _downloaders = new Dictionary<string, DownloadAndCacheFileOperation>(1000);
|
||||
public struct SchedulerConfig
|
||||
{
|
||||
public string SchedulerName { get; set; }
|
||||
public IDownloadBackend DownloadBackend { get; set; }
|
||||
public int MaxConcurrency { get; set; }
|
||||
public int MaxRequestPerFrame { get; set; }
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, DownloadFileBaseOperation> _downloaders = new Dictionary<string, DownloadFileBaseOperation>(1000);
|
||||
private readonly List<string> _removeList = new List<string>(1000);
|
||||
private readonly SchedulerConfig _config;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已暂停
|
||||
@@ -36,13 +44,12 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构造下载中心
|
||||
/// </summary>
|
||||
public DownloadSchedulerOperation(CacheFileSystem fileSystem)
|
||||
public DownloadSchedulerOperation(SchedulerConfig config)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_config = config;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -50,7 +57,7 @@ namespace YooAsset
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
// 驱动下载后台
|
||||
_fileSystem.DownloadBackend.Update();
|
||||
_config.DownloadBackend.Update();
|
||||
|
||||
// 获取可移除的下载器集合
|
||||
_removeList.Clear();
|
||||
@@ -91,8 +98,8 @@ namespace YooAsset
|
||||
ActiveDownloadCount = GetProcessingOperationCount();
|
||||
if (ActiveDownloadCount != _downloaders.Count)
|
||||
{
|
||||
int maxConcurrency = _fileSystem.DownloadMaxConcurrency;
|
||||
int maxRequestPerFrame = _fileSystem.DownloadMaxRequestPerFrame;
|
||||
int maxConcurrency = _config.MaxConcurrency;
|
||||
int maxRequestPerFrame = _config.MaxRequestPerFrame;
|
||||
if (ActiveDownloadCount < maxConcurrency)
|
||||
{
|
||||
int startCount = maxConcurrency - ActiveDownloadCount;
|
||||
@@ -115,7 +122,7 @@ namespace YooAsset
|
||||
}
|
||||
internal override string InternalGetDescription()
|
||||
{
|
||||
return $"{_fileSystem.GetType().FullName}";
|
||||
return _config.SchedulerName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -132,36 +139,30 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建下载任务
|
||||
/// 尝试获取已经存在的下载器
|
||||
/// </summary>
|
||||
/// <param name="bundle">资源包信息</param>
|
||||
/// <param name="url">下载地址</param>
|
||||
/// <returns>下载操作</returns>
|
||||
public DownloadAndCacheFileOperation DownloadAndCacheFileAsync(PackageBundle bundle, string url)
|
||||
public DownloadFileBaseOperation TryGetDownloadFile(PackageBundle bundle)
|
||||
{
|
||||
// 查询旧的下载器
|
||||
if (_downloaders.TryGetValue(bundle.BundleGUID, out var oldDownloader))
|
||||
{
|
||||
oldDownloader.Reference();
|
||||
return oldDownloader;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 创建新的下载器
|
||||
DownloadAndCacheFileOperation newDownloader;
|
||||
bool isRequestLocalFile = DownloadSystemTools.IsLocalFileURL(url);
|
||||
if (isRequestLocalFile)
|
||||
{
|
||||
newDownloader = new DownloadAndCacheLocalFileOperation(_fileSystem, bundle, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDownloader = new DownloadAndCacheRemoteFileOperation(_fileSystem, bundle, url);
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加新的下载器到调度中心
|
||||
/// </summary>
|
||||
public void AddDownloadFile(DownloadFileBaseOperation downloadFileOp)
|
||||
{
|
||||
string bundleGUID = downloadFileOp.Bundle.BundleGUID;
|
||||
if (_downloaders.ContainsKey(bundleGUID))
|
||||
throw new YooInternalException();
|
||||
|
||||
AddChildOperation(newDownloader);
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
newDownloader.Reference();
|
||||
return newDownloader;
|
||||
AddChildOperation(downloadFileOp);
|
||||
_downloaders.Add(bundleGUID, downloadFileOp);
|
||||
downloadFileOp.Reference();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -12,6 +12,9 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestBackend : IDownloadBackend
|
||||
{
|
||||
/// <summary>
|
||||
/// 自定义 UnityWebRequest 创建器(可为 null)
|
||||
/// </summary>
|
||||
private readonly UnityWebRequestCreator _webRequestCreator;
|
||||
|
||||
/// <summary>
|
||||
@@ -102,9 +105,9 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 创建模拟下载请求
|
||||
/// </summary>
|
||||
public IDownloadFileRequest CreateSimulateRequest(DownloadSimulateRequestArgs args)
|
||||
public IDownloadFileRequest CreateSimulateRequest(SimulateDownloadRequestArgs args)
|
||||
{
|
||||
return new SimulateRequestFile(args);
|
||||
return new SimulatedFileRequest(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,17 @@ namespace YooAsset
|
||||
/// 用于编辑器模式下模拟下载进度,不进行实际网络请求。
|
||||
/// 根据配置的下载速度模拟进度变化。
|
||||
/// </remarks>
|
||||
internal sealed class SimulateRequestFile : IDownloadFileRequest
|
||||
internal sealed class SimulatedFileRequest : IDownloadFileRequest
|
||||
{
|
||||
private readonly DownloadSimulateRequestArgs _args;
|
||||
private double _lastTickTime;
|
||||
/// <summary>
|
||||
/// 模拟下载参数
|
||||
/// </summary>
|
||||
private readonly SimulateDownloadRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
/// 最近一次更新的时间戳(用于计算时间增量)
|
||||
/// </summary>
|
||||
private double _lastestUpdateTime;
|
||||
|
||||
/// <summary>
|
||||
/// 文件保存路径(模拟下载不需要)
|
||||
@@ -26,7 +33,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public string URL { get; }
|
||||
public string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否完成
|
||||
@@ -35,8 +42,8 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
PollingRequest();
|
||||
return Status == EDownloadRequestStatus.Succeed
|
||||
PollRequest();
|
||||
return Status == EDownloadRequestStatus.Succeeded
|
||||
|| Status == EDownloadRequestStatus.Failed
|
||||
|| Status == EDownloadRequestStatus.Aborted;
|
||||
}
|
||||
@@ -72,10 +79,10 @@ namespace YooAsset
|
||||
/// 构造模拟下载器
|
||||
/// </summary>
|
||||
/// <param name="args">模拟下载参数</param>
|
||||
public SimulateRequestFile(DownloadSimulateRequestArgs args)
|
||||
public SimulatedFileRequest(SimulateDownloadRequestArgs args)
|
||||
{
|
||||
_args = args;
|
||||
URL = args.URL;
|
||||
Url = args.Url;
|
||||
Status = EDownloadRequestStatus.None;
|
||||
}
|
||||
|
||||
@@ -87,36 +94,7 @@ namespace YooAsset
|
||||
if (Status == EDownloadRequestStatus.None)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Running;
|
||||
_lastTickTime = TimeUtility.RealtimeSinceStartup;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询请求
|
||||
/// </summary>
|
||||
public void PollingRequest()
|
||||
{
|
||||
if (Status != EDownloadRequestStatus.Running)
|
||||
return;
|
||||
|
||||
double currentTime = TimeUtility.RealtimeSinceStartup;
|
||||
double deltaTime = currentTime - _lastTickTime;
|
||||
_lastTickTime = currentTime;
|
||||
|
||||
// 计算本帧下载的字节数
|
||||
long downloadBytes = (long)(_args.DownloadSpeed * deltaTime);
|
||||
DownloadedBytes += downloadBytes;
|
||||
|
||||
if (_args.FileSize > 0)
|
||||
DownloadProgress = (float)DownloadedBytes / _args.FileSize;
|
||||
|
||||
// 检查是否完成
|
||||
if (DownloadedBytes >= _args.FileSize)
|
||||
{
|
||||
HttpCode = 200;
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _args.FileSize;
|
||||
Status = EDownloadRequestStatus.Succeed;
|
||||
_lastestUpdateTime = TimeUtility.RealtimeSinceStartup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,5 +115,34 @@ namespace YooAsset
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新网络请求
|
||||
/// </summary>
|
||||
private void PollRequest()
|
||||
{
|
||||
if (Status != EDownloadRequestStatus.Running)
|
||||
return;
|
||||
|
||||
double currentTime = TimeUtility.RealtimeSinceStartup;
|
||||
double deltaTime = currentTime - _lastestUpdateTime;
|
||||
_lastestUpdateTime = currentTime;
|
||||
|
||||
// 计算本帧下载的字节数
|
||||
long downloadBytes = (long)(_args.DownloadSpeed * deltaTime);
|
||||
DownloadedBytes += downloadBytes;
|
||||
|
||||
if (_args.FileSize > 0)
|
||||
DownloadProgress = (float)DownloadedBytes / _args.FileSize;
|
||||
|
||||
// 检查是否完成
|
||||
if (DownloadedBytes >= _args.FileSize)
|
||||
{
|
||||
HttpCode = 200;
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _args.FileSize;
|
||||
Status = EDownloadRequestStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,14 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestAssetBundle : UnityWebRequestBase, IDownloadAssetBundleRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// AssetBundle 下载参数
|
||||
/// </summary>
|
||||
private readonly DownloadAssetBundleRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 下载处理器
|
||||
/// </summary>
|
||||
private DownloadHandlerAssetBundle _downloadHandler;
|
||||
|
||||
/// <summary>
|
||||
@@ -27,7 +34,7 @@ namespace YooAsset
|
||||
/// <param name="args">AssetBundle 下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestAssetBundle(DownloadAssetBundleRequestArgs args, UnityWebRequestCreator webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
: base(args.Url, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
@@ -38,7 +45,7 @@ namespace YooAsset
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
_downloadHandler = CreateAssetBundleDownloadHandler();
|
||||
_webRequest = CreateGetRequest(URL);
|
||||
_webRequest = CreateGetWebRequest(Url);
|
||||
_webRequest.downloadHandler = _downloadHandler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
ConfigureRequest(_args.Timeout, _args.WatchdogTimeout, _args.Headers);
|
||||
@@ -47,13 +54,13 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
protected override void OnRequestSucceeded()
|
||||
{
|
||||
AssetBundle assetBundle = _downloadHandler.assetBundle;
|
||||
if (assetBundle == null)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] URL: {URL} - AssetBundle object is null";
|
||||
Error = $"[{GetType().Name}] Failed to load AssetBundle. URL: {Url}, Error: AssetBundle object is null";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -64,6 +71,10 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 创建 AssetBundle 下载处理器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 根据 DisableUnityWebCache 配置决定是否使用 Unity 内置缓存。
|
||||
/// 启用缓存时需要提供有效的 FileHash。
|
||||
/// </remarks>
|
||||
private DownloadHandlerAssetBundle CreateAssetBundleDownloadHandler()
|
||||
{
|
||||
DownloadHandlerAssetBundle handler;
|
||||
@@ -71,17 +82,17 @@ namespace YooAsset
|
||||
if (_args.DisableUnityWebCache)
|
||||
{
|
||||
// 禁用 Unity 缓存
|
||||
handler = new DownloadHandlerAssetBundle(URL, _args.UnityCRC);
|
||||
handler = new DownloadHandlerAssetBundle(Url, _args.UnityCrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(_args.FileHash))
|
||||
throw new YooInternalException("File hash is null or empty.");
|
||||
throw new YooInternalException("FileHash is required when Unity web cache is enabled (DisableUnityWebCache = false).");
|
||||
|
||||
// 使用 Unity 缓存
|
||||
// 说明:The file hash defining the version of the asset bundle.
|
||||
Hash128 fileHash = Hash128.Parse(_args.FileHash);
|
||||
handler = new DownloadHandlerAssetBundle(URL, fileHash, _args.UnityCRC);
|
||||
handler = new DownloadHandlerAssetBundle(Url, fileHash, _args.UnityCrc);
|
||||
}
|
||||
|
||||
return handler;
|
||||
|
||||
@@ -13,33 +13,54 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal abstract class UnityWebRequestBase : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 自定义 UnityWebRequest 创建器
|
||||
/// </summary>
|
||||
private readonly UnityWebRequestCreator _webRequestCreator;
|
||||
|
||||
/// <summary>
|
||||
/// UnityWebRequest 实例
|
||||
/// </summary>
|
||||
protected UnityWebRequest _webRequest;
|
||||
|
||||
// 看门狗相关
|
||||
/// <summary>
|
||||
/// 看门狗超时时间(秒)
|
||||
/// </summary>
|
||||
private int _watchdogTimeout = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已被看门狗中止
|
||||
/// </summary>
|
||||
private bool _watchdogAborted = false;
|
||||
private long _lastDownloadBytes = -1;
|
||||
private double _lastDataReceivedTime;
|
||||
|
||||
/// <summary>
|
||||
/// 最近一次记录的下载字节数
|
||||
/// </summary>
|
||||
private long _lastestDownloadBytes = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 最近一次接收数据的时间
|
||||
/// </summary>
|
||||
private double _lastestDataReceivedTime;
|
||||
|
||||
#region 接口实现
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public string URL { get; }
|
||||
public string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否完成
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 每次调用都会主动轮询请求 PollingRequest
|
||||
/// 每次访问此属性都会自动调用内部方法 UpdateRequest() 进行状态更新。
|
||||
/// </remarks>
|
||||
public bool IsDone
|
||||
{
|
||||
get
|
||||
{
|
||||
PollingRequest();
|
||||
return Status == EDownloadRequestStatus.Succeed
|
||||
PollRequest();
|
||||
return Status == EDownloadRequestStatus.Succeeded
|
||||
|| Status == EDownloadRequestStatus.Failed
|
||||
|| Status == EDownloadRequestStatus.Aborted;
|
||||
}
|
||||
@@ -78,7 +99,7 @@ namespace YooAsset
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
protected UnityWebRequestBase(string url, UnityWebRequestCreator webRequestCreator)
|
||||
{
|
||||
URL = url;
|
||||
Url = url;
|
||||
_webRequestCreator = webRequestCreator;
|
||||
Status = EDownloadRequestStatus.None;
|
||||
}
|
||||
@@ -86,6 +107,10 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 发起请求
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅在 Status 为 None 时生效,重复调用无效。
|
||||
/// 调用后 Status 变为 Running。
|
||||
/// </remarks>
|
||||
public void SendRequest()
|
||||
{
|
||||
if (Status == EDownloadRequestStatus.None)
|
||||
@@ -99,7 +124,7 @@ namespace YooAsset
|
||||
if (_webRequest == null)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] Created web request is null.";
|
||||
Error = $"[{GetType().Name}] CreateWebRequest() returned null";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -114,47 +139,13 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询请求
|
||||
/// </summary>
|
||||
public void PollingRequest()
|
||||
{
|
||||
if (Status != EDownloadRequestStatus.Running)
|
||||
return;
|
||||
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
|
||||
TickWatchdog();
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
HttpCode = _webRequest.responseCode;
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
bool isSuccess = _webRequest.result == UnityWebRequest.Result.Success;
|
||||
#else
|
||||
bool isSuccess = !_webRequest.isNetworkError && !_webRequest.isHttpError;
|
||||
#endif
|
||||
|
||||
if (isSuccess)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Succeed;
|
||||
OnRequestSucceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] URL: {URL} - Error: {_webRequest.error}";
|
||||
OnRequestFailed();
|
||||
}
|
||||
|
||||
// 完成后释放
|
||||
CleanupWebRequest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中止请求
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 可在任意状态调用,仅当 Status 为 None 或 Running 时生效。
|
||||
/// 调用后 Status 变为 Aborted。
|
||||
/// </remarks>
|
||||
public void AbortRequest()
|
||||
{
|
||||
if (Status == EDownloadRequestStatus.None || Status == EDownloadRequestStatus.Running)
|
||||
@@ -182,7 +173,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求成功时的回调(子类可重写)
|
||||
/// </summary>
|
||||
protected virtual void OnRequestSucceed()
|
||||
protected virtual void OnRequestSucceeded()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -199,7 +190,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
/// <param name="requestUrl">请求地址</param>
|
||||
/// <returns>UnityWebRequest 实例</returns>
|
||||
protected UnityWebRequest CreateGetRequest(string requestUrl)
|
||||
protected UnityWebRequest CreateGetWebRequest(string requestUrl)
|
||||
{
|
||||
if (_webRequestCreator != null)
|
||||
return _webRequestCreator.Invoke(requestUrl, UnityWebRequest.kHttpVerbGET);
|
||||
@@ -212,7 +203,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
/// <param name="requestUrl">请求地址</param>
|
||||
/// <returns>UnityWebRequest 实例</returns>
|
||||
protected UnityWebRequest CreateHeadRequest(string requestUrl)
|
||||
protected UnityWebRequest CreateHeadWebRequest(string requestUrl)
|
||||
{
|
||||
if (_webRequestCreator != null)
|
||||
return _webRequestCreator.Invoke(requestUrl, UnityWebRequest.kHttpVerbHEAD);
|
||||
@@ -223,10 +214,13 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 配置通用请求参数
|
||||
/// </summary>
|
||||
/// <param name="timeout">响应超时时间(秒),0 表示不应用超时</param>
|
||||
/// <param name="watchdogTimeout">看门狗超时时间(秒),0 表示禁用</param>
|
||||
/// <param name="headers">自定义请求头(可选)</param>
|
||||
protected void ConfigureRequest(int timeout, int watchdogTimeout, Dictionary<string, string> headers)
|
||||
{
|
||||
if (_webRequest == null)
|
||||
throw new YooInternalException("Web request is null.");
|
||||
throw new YooInternalException("Cannot configure request: UnityWebRequest object is null. Ensure CreateWebRequest() is called first.");
|
||||
|
||||
// 设置看门狗超时时间
|
||||
_watchdogTimeout = watchdogTimeout;
|
||||
@@ -246,9 +240,47 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测看门狗
|
||||
/// 更新网络请求
|
||||
/// </summary>
|
||||
private void TickWatchdog()
|
||||
private void PollRequest()
|
||||
{
|
||||
if (Status != EDownloadRequestStatus.Running)
|
||||
return;
|
||||
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
|
||||
UpdateWatchdog();
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
HttpCode = _webRequest.responseCode;
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
bool isSuccess = _webRequest.result == UnityWebRequest.Result.Success;
|
||||
#else
|
||||
bool isSuccess = !_webRequest.isNetworkError && !_webRequest.isHttpError;
|
||||
#endif
|
||||
|
||||
if (isSuccess)
|
||||
{
|
||||
Status = EDownloadRequestStatus.Succeeded;
|
||||
OnRequestSucceeded();
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EDownloadRequestStatus.Failed;
|
||||
Error = $"[{GetType().Name}] Request failed. URL: {Url}, Error: {_webRequest.error}";
|
||||
OnRequestFailed();
|
||||
}
|
||||
|
||||
// 完成后释放
|
||||
CleanupWebRequest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新看门狗机制
|
||||
/// </summary>
|
||||
private void UpdateWatchdog()
|
||||
{
|
||||
if (_watchdogTimeout == 0)
|
||||
return;
|
||||
@@ -256,14 +288,14 @@ namespace YooAsset
|
||||
return;
|
||||
|
||||
double realtimeSinceStartup = TimeUtility.RealtimeSinceStartup;
|
||||
if (DownloadedBytes != _lastDownloadBytes)
|
||||
if (DownloadedBytes != _lastestDownloadBytes)
|
||||
{
|
||||
_lastDownloadBytes = DownloadedBytes;
|
||||
_lastDataReceivedTime = realtimeSinceStartup;
|
||||
_lastestDownloadBytes = DownloadedBytes;
|
||||
_lastestDataReceivedTime = realtimeSinceStartup;
|
||||
}
|
||||
else
|
||||
{
|
||||
double deltaTime = realtimeSinceStartup - _lastDataReceivedTime;
|
||||
double deltaTime = realtimeSinceStartup - _lastestDataReceivedTime;
|
||||
if (deltaTime > _watchdogTimeout)
|
||||
{
|
||||
_watchdogAborted = true;
|
||||
|
||||
@@ -11,6 +11,9 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestBytes : UnityWebRequestBase, IDownloadBytesRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据下载参数
|
||||
/// </summary>
|
||||
private readonly DownloadDataRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
@@ -24,7 +27,7 @@ namespace YooAsset
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestBytes(DownloadDataRequestArgs args, UnityWebRequestCreator webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
: base(args.Url, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
@@ -35,7 +38,7 @@ namespace YooAsset
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
var handler = new DownloadHandlerBuffer();
|
||||
_webRequest = CreateGetRequest(URL);
|
||||
_webRequest = CreateGetWebRequest(Url);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
ConfigureRequest(_args.Timeout, _args.WatchdogTimeout, _args.Headers);
|
||||
@@ -44,7 +47,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
protected override void OnRequestSucceeded()
|
||||
{
|
||||
Result = _webRequest.downloadHandler.data;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestFile : UnityWebRequestBase, IDownloadFileRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件下载参数
|
||||
/// </summary>
|
||||
private readonly DownloadFileRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
@@ -27,7 +30,7 @@ namespace YooAsset
|
||||
/// <param name="args">文件下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestFile(DownloadFileRequestArgs args, UnityWebRequestCreator webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
: base(args.Url, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
@@ -40,7 +43,7 @@ namespace YooAsset
|
||||
var handler = new DownloadHandlerFile(_args.SavePath, _args.AppendToFile);
|
||||
handler.removeFileOnAbort = _args.RemoveFileOnAbort;
|
||||
|
||||
_webRequest = CreateGetRequest(URL);
|
||||
_webRequest = CreateGetWebRequest(Url);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
|
||||
|
||||
@@ -13,8 +13,17 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestHead : UnityWebRequestBase, IDownloadHeadRequest
|
||||
{
|
||||
// 注意:缓存响应头(因为 WebRequest 释放后无法获取)
|
||||
/// <summary>
|
||||
/// 缓存的响应头(请求完成后从 WebRequest 复制)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// WebRequest 释放后无法获取响应头,因此需要提前缓存。
|
||||
/// </remarks>
|
||||
private Dictionary<string, string> _cachedResponseHeaders;
|
||||
|
||||
/// <summary>
|
||||
/// 数据下载参数
|
||||
/// </summary>
|
||||
private readonly DownloadDataRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
@@ -70,7 +79,7 @@ namespace YooAsset
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestHead(DownloadDataRequestArgs args, UnityWebRequestCreator webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
: base(args.Url, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
@@ -98,7 +107,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
_webRequest = CreateHeadRequest(URL);
|
||||
_webRequest = CreateHeadWebRequest(Url);
|
||||
_webRequest.downloadHandler = null; // HEAD 请求不需要 DownloadHandler
|
||||
ConfigureRequest(_args.Timeout, _args.WatchdogTimeout, _args.Headers);
|
||||
}
|
||||
@@ -106,7 +115,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
protected override void OnRequestSucceeded()
|
||||
{
|
||||
var headers = _webRequest.GetResponseHeaders();
|
||||
if (headers != null)
|
||||
|
||||
@@ -11,6 +11,9 @@ namespace YooAsset
|
||||
/// </remarks>
|
||||
internal sealed class UnityWebRequestText : UnityWebRequestBase, IDownloadTextRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据下载参数
|
||||
/// </summary>
|
||||
private readonly DownloadDataRequestArgs _args;
|
||||
|
||||
/// <summary>
|
||||
@@ -24,7 +27,7 @@ namespace YooAsset
|
||||
/// <param name="args">数据下载参数</param>
|
||||
/// <param name="webRequestCreator">UnityWebRequest 创建器(可选)</param>
|
||||
public UnityWebRequestText(DownloadDataRequestArgs args, UnityWebRequestCreator webRequestCreator)
|
||||
: base(args.URL, webRequestCreator)
|
||||
: base(args.Url, webRequestCreator)
|
||||
{
|
||||
_args = args;
|
||||
}
|
||||
@@ -35,7 +38,7 @@ namespace YooAsset
|
||||
protected override void CreateWebRequest()
|
||||
{
|
||||
var handler = new DownloadHandlerBuffer();
|
||||
_webRequest = CreateGetRequest(URL);
|
||||
_webRequest = CreateGetWebRequest(Url);
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
ConfigureRequest(_args.Timeout, _args.WatchdogTimeout, _args.Headers);
|
||||
@@ -44,7 +47,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 请求成功时的回调
|
||||
/// </summary>
|
||||
protected override void OnRequestSucceed()
|
||||
protected override void OnRequestSucceeded()
|
||||
{
|
||||
Result = _webRequest.downloadHandler.text;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
@@ -5,10 +6,8 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 文件缓存系统接口
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntry">缓存记录类型</typeparam>
|
||||
internal interface IFileCache<TEntry> where TEntry : ICacheEntry
|
||||
internal interface IFileCache : IDisposable
|
||||
{
|
||||
#region 状态属性
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
@@ -24,44 +23,45 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
bool IsReadOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存文件数量
|
||||
/// </summary>
|
||||
int FileCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 已占用空间(字节)
|
||||
/// </summary>
|
||||
long SpaceOccupied { get; }
|
||||
#endregion
|
||||
|
||||
#region 异步操作
|
||||
/// <summary>
|
||||
/// 初始化缓存
|
||||
/// </summary>
|
||||
FCInitializeOperation InitializeAsync(FCInitializeOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 存储缓存文件
|
||||
/// 初始化文件缓存系统
|
||||
/// </summary>
|
||||
FCStoreCacheOperation StoreCacheAsync(FCStoreCacheOptions options);
|
||||
FCInitializeOperation InitializeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 写入缓存文件
|
||||
/// </summary>
|
||||
FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 清理缓存文件
|
||||
/// </summary>
|
||||
FCClearCacheOperation ClearCacheAsync(FCClearCacheOptions options);
|
||||
#endregion
|
||||
FCClearCacheOperation ClearCacheAsync(ClearCacheOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 验证缓存文件
|
||||
/// </summary>
|
||||
FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 加载资源包
|
||||
/// </summary>
|
||||
FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options);
|
||||
|
||||
#region 查询方法
|
||||
/// <summary>
|
||||
/// 是否已缓存指定 Bundle
|
||||
/// </summary>
|
||||
bool IsCached(string bundleGUID);
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存记录
|
||||
/// </summary>
|
||||
TEntry GetEntry(string bundleGUID);
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有的缓存记录
|
||||
/// </summary>
|
||||
IReadOnlyCollection<TEntry> GetAllEntries();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class FCClearCacheOperation : AsyncOperationBase
|
||||
internal abstract class FCClearCacheOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
}
|
||||
|
||||
internal class FCClearCacheCompleteOperation : FCClearCacheOperation
|
||||
{
|
||||
private readonly string _error;
|
||||
|
||||
public FCClearCacheCompleteOperation()
|
||||
{
|
||||
None,
|
||||
CheckOptions,
|
||||
ClearCache,
|
||||
Done,
|
||||
_error = null;
|
||||
}
|
||||
|
||||
private BundleCache _cache;
|
||||
private FCClearCacheOptions _options;
|
||||
private int _clearFileTotalCount;
|
||||
private List<string> _bundleGUIDs;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public FCClearCacheOperation(BundleCache cache, FCClearCacheOptions options)
|
||||
public FCClearCacheCompleteOperation(string error)
|
||||
{
|
||||
_cache = cache;
|
||||
_options = options;
|
||||
_error = error;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckOptions;
|
||||
if (string.IsNullOrEmpty(_error))
|
||||
{
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _error;
|
||||
}
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckOptions)
|
||||
{
|
||||
if (_options.BundleGUIDs == null || _options.BundleGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
return;
|
||||
}
|
||||
|
||||
_bundleGUIDs = _options.BundleGUIDs.ToList();
|
||||
_clearFileTotalCount = _options.BundleGUIDs.Count;
|
||||
_steps = ESteps.ClearCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearCache)
|
||||
{
|
||||
for (int i = _bundleGUIDs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string bundleGUID = _bundleGUIDs[i];
|
||||
_cache.RemoveEntry(bundleGUID);
|
||||
_bundleGUIDs.RemoveAt(i);
|
||||
if (IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_clearFileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - ((float)_bundleGUIDs.Count / _clearFileTotalCount);
|
||||
|
||||
if (_bundleGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb3347395a55d3048bcec202aca0e4a7
|
||||
guid: 0df121ea04074ca46b7fbe7932a5d452
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal struct FCClearCacheOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 清理指定缓存列表
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> BundleGUIDs { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,79 +1,7 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class FCInitializeOperation : AsyncOperationBase
|
||||
internal abstract class FCInitializeOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
SearchCacheFiles,
|
||||
VerifyCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BundleCache _cache;
|
||||
private readonly FCInitializeOptions _options;
|
||||
private SearchCacheFilesOperation _searchCacheFilesOp;
|
||||
private VerifyCacheFilesOperation _verifyCacheFilesOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public FCInitializeOperation(BundleCache cache, FCInitializeOptions options)
|
||||
{
|
||||
_cache = cache;
|
||||
_options = options;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.SearchCacheFiles;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.SearchCacheFiles)
|
||||
{
|
||||
if (_searchCacheFilesOp == null)
|
||||
{
|
||||
_searchCacheFilesOp = new SearchCacheFilesOperation(_cache);
|
||||
_searchCacheFilesOp.StartOperation();
|
||||
AddChildOperation(_searchCacheFilesOp);
|
||||
}
|
||||
|
||||
_searchCacheFilesOp.UpdateOperation();
|
||||
Progress = _searchCacheFilesOp.Progress;
|
||||
if (_searchCacheFilesOp.IsDone == false)
|
||||
return;
|
||||
|
||||
_steps = ESteps.VerifyCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyCacheFiles)
|
||||
{
|
||||
if (_verifyCacheFilesOp == null)
|
||||
{
|
||||
_verifyCacheFilesOp = new VerifyCacheFilesOperation(_cache, _options.FileVerifyLevel, _options.FileVerifyMaxConcurrency, _searchCacheFilesOp.Result);
|
||||
_verifyCacheFilesOp.StartOperation();
|
||||
AddChildOperation(_verifyCacheFilesOp);
|
||||
}
|
||||
|
||||
_verifyCacheFilesOp.UpdateOperation();
|
||||
Progress = _verifyCacheFilesOp.Progress;
|
||||
if (_verifyCacheFilesOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_verifyCacheFilesOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _verifyCacheFilesOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9be990c57fe162845ba3893188a68f8b
|
||||
guid: 22422599c3cb80342ad546cbc4b8adc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal struct FCInitializeOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件校验最大并发数
|
||||
/// </summary>
|
||||
public int FileVerifyMaxConcurrency { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件校验级别
|
||||
/// </summary>
|
||||
public EFileVerifyLevel FileVerifyLevel { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class FCLoadBundleOperation : AsyncOperationBase
|
||||
{
|
||||
public IBundleResult BundleResult { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查文件路径是否支持 FileIO 读取
|
||||
/// </summary>
|
||||
protected bool IsSupportFileIO(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
return true;
|
||||
if (filePath.StartsWith("jar:") || filePath.StartsWith("content:"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class FCLoadBundleErrorOperation : FCLoadBundleOperation
|
||||
{
|
||||
private readonly string _error;
|
||||
|
||||
internal FCLoadBundleErrorOperation(string error)
|
||||
{
|
||||
_error = error;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _error;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75f6c6588c154e145b09fa36cc6f2602
|
||||
guid: f80086e0af509ae47829d80ca2037f5c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class FCVerifyCacheOperation : AsyncOperationBase
|
||||
{
|
||||
}
|
||||
|
||||
internal class FCVerifyCacheCompleteOperation : FCVerifyCacheOperation
|
||||
{
|
||||
private readonly string _error;
|
||||
|
||||
public FCVerifyCacheCompleteOperation()
|
||||
{
|
||||
_error = null;
|
||||
}
|
||||
public FCVerifyCacheCompleteOperation(string error)
|
||||
{
|
||||
_error = error;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_error))
|
||||
{
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _error;
|
||||
}
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbe6c6f462ef0c9429568f9d1df559f6
|
||||
guid: 920884f1ed1f59948aeb0fe0acdab027
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal struct VerifyCacheOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 要验证的资源包
|
||||
/// </summary>
|
||||
public PackageBundle Bundle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 失败后直接移除缓存
|
||||
/// </summary>
|
||||
public bool FailedDeleteCache { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03f8c5e4c7af7df4387f56d045d8d357
|
||||
guid: b3daf736aed95a848a15feb00d81ed0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class FCWriteCacheOperation : AsyncOperationBase
|
||||
{
|
||||
}
|
||||
|
||||
internal class FCWriteCacheCompleteOperation : FCWriteCacheOperation
|
||||
{
|
||||
private readonly string _error;
|
||||
|
||||
public FCWriteCacheCompleteOperation()
|
||||
{
|
||||
_error = null;
|
||||
}
|
||||
public FCWriteCacheCompleteOperation(string error)
|
||||
{
|
||||
_error = error;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_error))
|
||||
{
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _error;
|
||||
}
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 773d121e67073ec44adaa843ebcb01a0
|
||||
guid: d7127f4341e3a9e43a7db51c48737241
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal struct FCStoreCacheOptions
|
||||
internal struct WriteCacheOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 要缓存的资源包
|
||||
@@ -12,5 +12,10 @@ namespace YooAsset
|
||||
/// 要缓存的文件路径
|
||||
/// </summary>
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 要缓存的文件数据
|
||||
/// </summary>
|
||||
public byte[] FileData { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cdea99ab2acded4ebd8c5766c8b3b7b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07e60a75ff092314cb4d9ba6d5b14296
|
||||
guid: 3fc8cc5c0f4f38941bcbad7d4866d535
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BuiltinFileCache : IFileCache
|
||||
{
|
||||
internal struct CacheConfig
|
||||
{
|
||||
public IDownloadBackend DownloadBackend { get; set; }
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, BuiltinFileCacheEntry> _caches = new Dictionary<string, BuiltinFileCacheEntry>(10000);
|
||||
|
||||
// 缓存配置
|
||||
internal readonly CacheConfig Config;
|
||||
|
||||
#region 接口属性
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存根目录
|
||||
/// </summary>
|
||||
public string RootPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 只读属性
|
||||
/// </summary>
|
||||
public bool IsReadOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存文件数量
|
||||
/// </summary>
|
||||
public int FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _caches.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已占用空间
|
||||
/// 说明:按缓存索引累计
|
||||
/// </summary>
|
||||
public long SpaceOccupied { get; private set; }
|
||||
#endregion
|
||||
|
||||
public BuiltinFileCache(string packageName, string rootPath, CacheConfig config)
|
||||
{
|
||||
PackageName = packageName;
|
||||
RootPath = rootPath;
|
||||
Config = config;
|
||||
IsReadOnly = true;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
public virtual FCInitializeOperation InitializeAsync()
|
||||
{
|
||||
var operation = new BFCInitializeOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
||||
{
|
||||
var operation = new FCWriteCacheCompleteOperation($"{nameof(BuiltinFileCache)} is readonly.");
|
||||
return operation;
|
||||
}
|
||||
public virtual FCClearCacheOperation ClearCacheAsync(ClearCacheOptions options)
|
||||
{
|
||||
var operation = new FCClearCacheCompleteOperation($"{nameof(BuiltinFileCache)} is readonly.");
|
||||
return operation;
|
||||
}
|
||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
||||
{
|
||||
var operation = new FCVerifyCacheCompleteOperation();
|
||||
return operation;
|
||||
}
|
||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
||||
{
|
||||
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||
{
|
||||
var operation = new BFCLoadAssetBundleOperation(this, options.Bundle);
|
||||
return operation;
|
||||
}
|
||||
else if (options.Bundle.BundleType == (int)EBundleType.RawBundle)
|
||||
{
|
||||
var operation = new BFCLoadRawBundleOperation(this, options.Bundle);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error = $"{nameof(BuiltinFileCache)} not support load bundle type : {options.Bundle.BundleType}";
|
||||
var operation = new FCLoadBundleErrorOperation(error);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
public virtual bool IsCached(string bundleGUID)
|
||||
{
|
||||
return _caches.ContainsKey(bundleGUID);
|
||||
}
|
||||
|
||||
#region 内部方法
|
||||
/// <summary>
|
||||
/// 获取指定缓存
|
||||
/// </summary>
|
||||
public BuiltinFileCacheEntry GetEntry(string bundleGUID)
|
||||
{
|
||||
if (_caches.TryGetValue(bundleGUID, out BuiltinFileCacheEntry entry))
|
||||
return entry;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加指定缓存
|
||||
/// </summary>
|
||||
internal void AddEntry(string bundleGUID, BuiltinFileCacheEntry entry)
|
||||
{
|
||||
if (_caches.ContainsKey(bundleGUID))
|
||||
throw new YooInternalException($"Cache entry already existed: {bundleGUID}");
|
||||
|
||||
_caches.Add(bundleGUID, entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Catalog文件加载路径
|
||||
/// </summary>
|
||||
internal string GetCatalogBinaryFileLoadPath()
|
||||
{
|
||||
return PathUtility.Combine(RootPath, BuiltinFileCatalogDefine.BinaryFileName);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91fdd72294b893b4a835072732641208
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BuiltinFileCacheEntry : ICacheEntry
|
||||
{
|
||||
public string BundleGUID { get; private set; }
|
||||
public string FilePath { get; private set; }
|
||||
|
||||
public BuiltinFileCacheEntry(string bundleGUID, string filePath)
|
||||
{
|
||||
BundleGUID = bundleGUID;
|
||||
FilePath = filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1ac8aeeac16de547bd0eff9bbaa3a23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CatalogFileConstants
|
||||
internal class BuiltinFileCatalogDefine
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件极限大小(100MB)
|
||||
@@ -17,5 +17,16 @@ namespace YooAsset
|
||||
/// 文件格式版本
|
||||
/// </summary>
|
||||
public const string FileVersion = "1.0.0";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// JSON文件名称
|
||||
/// </summary>
|
||||
public const string JsonFileName = "BuiltinCatalog.json";
|
||||
|
||||
/// <summary>
|
||||
/// 二进制文件名称
|
||||
/// </summary>
|
||||
public const string BinaryFileName = "BuiltinCatalog.bytes";
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class CatalogFileTools
|
||||
internal static class BuiltinFileCatalogTools
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
@@ -40,7 +40,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
|
||||
packageManifest = PackageManifestTools.DeserializeFromBinary(binaryData, services);
|
||||
packageManifest = PackageManifestTools.DeserializeManifestFromBinary(binaryData, services);
|
||||
}
|
||||
|
||||
// 获取文件名映射关系
|
||||
@@ -54,7 +54,7 @@ namespace YooAsset
|
||||
|
||||
// 创建内置清单实例
|
||||
var buildinFileCatalog = new BuiltinFileCatalog();
|
||||
buildinFileCatalog.FileVersion = CatalogFileConstants.FileVersion;
|
||||
buildinFileCatalog.FileVersion = BuiltinFileCatalogDefine.FileVersion;
|
||||
buildinFileCatalog.PackageName = packageName;
|
||||
buildinFileCatalog.PackageVersion = packageVersion;
|
||||
|
||||
@@ -63,8 +63,8 @@ namespace YooAsset
|
||||
{
|
||||
"link.xml",
|
||||
"buildlogtep.json",
|
||||
BuiltinFileSystemConstants.BuiltinCatalogJsonFileName,
|
||||
BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName
|
||||
BuiltinFileCatalogDefine.JsonFileName,
|
||||
BuiltinFileCatalogDefine.BinaryFileName
|
||||
};
|
||||
string packageVersionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
||||
string packageHashFileName = YooAssetSettingsData.GetPackageHashFileName(packageName, packageVersion);
|
||||
@@ -103,13 +103,13 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
// 创建输出文件
|
||||
string jsonFilePath = $"{packageDirectory}/{BuiltinFileSystemConstants.BuiltinCatalogJsonFileName}";
|
||||
string jsonFilePath = $"{packageDirectory}/{BuiltinFileCatalogDefine.JsonFileName}";
|
||||
if (File.Exists(jsonFilePath))
|
||||
File.Delete(jsonFilePath);
|
||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
||||
|
||||
// 创建输出文件
|
||||
string binaryFilePath = $"{packageDirectory}/{BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName}";
|
||||
string binaryFilePath = $"{packageDirectory}/{BuiltinFileCatalogDefine.BinaryFileName}";
|
||||
if (File.Exists(binaryFilePath))
|
||||
File.Delete(binaryFilePath);
|
||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
||||
@@ -126,18 +126,18 @@ namespace YooAsset
|
||||
{
|
||||
// 创建内置清单实例
|
||||
var buildinFileCatalog = new BuiltinFileCatalog();
|
||||
buildinFileCatalog.FileVersion = CatalogFileConstants.FileVersion;
|
||||
buildinFileCatalog.FileVersion = BuiltinFileCatalogDefine.FileVersion;
|
||||
buildinFileCatalog.PackageName = packageName;
|
||||
buildinFileCatalog.PackageVersion = packageVersion;
|
||||
|
||||
// 创建输出文件
|
||||
string jsonFilePath = $"{outputPath}/{BuiltinFileSystemConstants.BuiltinCatalogJsonFileName}";
|
||||
string jsonFilePath = $"{outputPath}/{BuiltinFileCatalogDefine.JsonFileName}";
|
||||
if (File.Exists(jsonFilePath))
|
||||
File.Delete(jsonFilePath);
|
||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
||||
|
||||
// 创建输出文件
|
||||
string binaryFilePath = $"{outputPath}/{BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName}";
|
||||
string binaryFilePath = $"{outputPath}/{BuiltinFileCatalogDefine.BinaryFileName}";
|
||||
if (File.Exists(binaryFilePath))
|
||||
File.Delete(binaryFilePath);
|
||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
||||
@@ -173,13 +173,13 @@ namespace YooAsset
|
||||
using (FileStream fs = new FileStream(savePath, FileMode.Create))
|
||||
{
|
||||
// 创建缓存器
|
||||
BufferWriter buffer = new BufferWriter(CatalogFileConstants.FileMaxSize);
|
||||
BufferWriter buffer = new BufferWriter(BuiltinFileCatalogDefine.FileMaxSize);
|
||||
|
||||
// 写入文件标记
|
||||
buffer.WriteUInt32(CatalogFileConstants.FileSign);
|
||||
buffer.WriteUInt32(BuiltinFileCatalogDefine.FileSign);
|
||||
|
||||
// 写入文件版本
|
||||
buffer.WriteUTF8(CatalogFileConstants.FileVersion);
|
||||
buffer.WriteUTF8(BuiltinFileCatalogDefine.FileVersion);
|
||||
|
||||
// 写入文件头信息
|
||||
buffer.WriteUTF8(catalog.PackageName);
|
||||
@@ -213,13 +213,13 @@ namespace YooAsset
|
||||
|
||||
// 读取文件标记
|
||||
uint fileSign = buffer.ReadUInt32();
|
||||
if (fileSign != CatalogFileConstants.FileSign)
|
||||
if (fileSign != BuiltinFileCatalogDefine.FileSign)
|
||||
throw new Exception("Invalid catalog file.");
|
||||
|
||||
// 读取文件版本
|
||||
string fileVersion = buffer.ReadUTF8();
|
||||
if (fileVersion != CatalogFileConstants.FileVersion)
|
||||
throw new Exception($"The catalog file version are not compatible : {fileVersion} != {CatalogFileConstants.FileVersion}");
|
||||
if (fileVersion != BuiltinFileCatalogDefine.FileVersion)
|
||||
throw new Exception($"The catalog file version are not compatible : {fileVersion} != {BuiltinFileCatalogDefine.FileVersion}");
|
||||
|
||||
BuiltinFileCatalog catalog = new BuiltinFileCatalog();
|
||||
{
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34b5f5fd59f780c40bd9e581c5c6a718
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BFCInitializeOperation : FCInitializeOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadCatalogFile,
|
||||
RecordFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileCache _fileCache;
|
||||
private LoadBuiltinCatalogFileOperation _loadBuiltinCatalogFileOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public BFCInitializeOperation(BuiltinFileCache cache)
|
||||
{
|
||||
_fileCache = cache;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadCatalogFile;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadCatalogFile)
|
||||
{
|
||||
if (_loadBuiltinCatalogFileOp == null)
|
||||
{
|
||||
_loadBuiltinCatalogFileOp = new LoadBuiltinCatalogFileOperation(_fileCache);
|
||||
_loadBuiltinCatalogFileOp.StartOperation();
|
||||
AddChildOperation(_loadBuiltinCatalogFileOp);
|
||||
}
|
||||
|
||||
_loadBuiltinCatalogFileOp.UpdateOperation();
|
||||
if (_loadBuiltinCatalogFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadBuiltinCatalogFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.RecordFiles;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadBuiltinCatalogFileOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.RecordFiles)
|
||||
{
|
||||
var catalog = _loadBuiltinCatalogFileOp.Catalog;
|
||||
foreach (var wrapper in catalog.Wrappers)
|
||||
{
|
||||
string filePath = PathUtility.Combine(_fileCache.RootPath, wrapper.FileName);
|
||||
var entry = new BuiltinFileCacheEntry(wrapper.BundleGUID, filePath);
|
||||
_fileCache.AddEntry(wrapper.BundleGUID, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1cd01c3a273ec8428ba5cca5aaed254
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BFCLoadAssetBundleOperation : FCLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadAssetBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileCache _fileCache;
|
||||
private readonly PackageBundle _bundle;
|
||||
private AssetBundleCreateRequest _createRequest;
|
||||
private AssetBundle _assetBundle;
|
||||
private string _filePath;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public BFCLoadAssetBundleOperation(BuiltinFileCache fileCache, PackageBundle bundle)
|
||||
{
|
||||
_fileCache = fileCache;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadAssetBundle;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadAssetBundle)
|
||||
{
|
||||
var entry = _fileCache.GetEntry(_bundle.BundleGUID);
|
||||
if (entry == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
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
|
||||
{
|
||||
if (_createRequest.isDone == false)
|
||||
return;
|
||||
_assetBundle = _createRequest.assetBundle;
|
||||
}
|
||||
}
|
||||
|
||||
if (_assetBundle == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load asset bundle : {_bundle.BundleName}";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
BundleResult = new AssetBundleResult(_filePath, _bundle, _assetBundle, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BFCLoadRawBundleOperation : FCLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadRawBundle,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileCache _fileCache;
|
||||
private readonly PackageBundle _bundle;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public BFCLoadRawBundleOperation(BuiltinFileCache fileCache, PackageBundle bundle)
|
||||
{
|
||||
_fileCache = fileCache;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadRawBundle;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadRawBundle)
|
||||
{
|
||||
var entry = _fileCache.GetEntry(_bundle.BundleGUID);
|
||||
if (entry == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
||||
return;
|
||||
}
|
||||
|
||||
string filePath = entry.FilePath;
|
||||
if (IsSupportFileIO(filePath) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"FileIO not supported for builtin path : {filePath}";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
|
||||
byte[] data = File.ReadAllBytes(filePath);
|
||||
var rawBundle = new RawBundle(data);
|
||||
BundleResult = new RawBundleResult(filePath, _bundle, rawBundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Can not found raw bundle file : {filePath}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc8b3f7e6178e2e4990674d5518eff33
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dd4916e71be0934883f2fc404dd18fc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
@@ -11,10 +11,11 @@ namespace YooAsset
|
||||
TryLoadFileData,
|
||||
RequestFileData,
|
||||
LoadCatalog,
|
||||
CheckResut,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly BuiltinFileCache _fileCache;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private byte[] _fileData;
|
||||
private ESteps _steps = ESteps.None;
|
||||
@@ -24,9 +25,9 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public BuiltinFileCatalog Catalog;
|
||||
|
||||
internal LoadBuiltinCatalogFileOperation(BuiltinFileSystem fileSystem)
|
||||
internal LoadBuiltinCatalogFileOperation(BuiltinFileCache fileCache)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_fileCache = fileCache;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -39,7 +40,7 @@ namespace YooAsset
|
||||
|
||||
if (_steps == ESteps.TryLoadFileData)
|
||||
{
|
||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||
string filePath = _fileCache.GetCatalogBinaryFileLoadPath();
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_fileData = File.ReadAllBytes(filePath);
|
||||
@@ -55,17 +56,17 @@ namespace YooAsset
|
||||
{
|
||||
if (_webDataRequestOp == null)
|
||||
{
|
||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||
string url = DownloadSystemTools.ToLocalURL(filePath);
|
||||
string filePath = _fileCache.GetCatalogBinaryFileLoadPath();
|
||||
string url = DownloadSystemTools.ToLocalUrl(filePath);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp = _fileCache.Config.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeeded)
|
||||
{
|
||||
_fileData = _webDataRequestOp.Result;
|
||||
_steps = ESteps.LoadCatalog;
|
||||
@@ -82,9 +83,8 @@ namespace YooAsset
|
||||
{
|
||||
try
|
||||
{
|
||||
Catalog = CatalogFileTools.DeserializeFromBinary(_fileData);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
Catalog = BuiltinFileCatalogTools.DeserializeFromBinary(_fileData);
|
||||
_steps = ESteps.CheckResut;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -93,6 +93,20 @@ namespace YooAsset
|
||||
Error = $"Failed to load catalog file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResut)
|
||||
{
|
||||
if (Catalog.PackageName != _fileCache.PackageName)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Catalog file package name {Catalog.PackageName} cannot match the file cache package name {_fileCache.PackageName}";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BundleCache : IFileCache<BundleCacheEntry>
|
||||
{
|
||||
private const int HashFolderLength = 2;
|
||||
|
||||
// 缓存索引
|
||||
private readonly Dictionary<string, BundleCacheEntry> _caches = new Dictionary<string, BundleCacheEntry>(10000);
|
||||
|
||||
// 路径缓存
|
||||
private readonly Dictionary<string, string> _dataFilePathMapping = new Dictionary<string, string>(10000);
|
||||
private readonly Dictionary<string, string> _infoFilePathMapping = new Dictionary<string, string>(10000);
|
||||
|
||||
// 共享缓冲区
|
||||
internal readonly BufferWriter SharedBuffer = new BufferWriter(1024);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存根目录
|
||||
/// </summary>
|
||||
public string RootPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 追加文件扩展名
|
||||
/// </summary>
|
||||
public readonly bool AppendFileExtension;
|
||||
|
||||
/// <summary>
|
||||
/// 只读属性
|
||||
/// </summary>
|
||||
public bool IsReadOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存文件数量
|
||||
/// </summary>
|
||||
public int FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _caches.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已占用空间
|
||||
/// 说明:按缓存索引累计
|
||||
/// </summary>
|
||||
public long SpaceOccupied { get; private set; }
|
||||
|
||||
|
||||
public BundleCache(string packageName, string rootPath, bool appendFileExtension)
|
||||
{
|
||||
PackageName = packageName;
|
||||
RootPath = rootPath;
|
||||
AppendFileExtension = appendFileExtension;
|
||||
IsReadOnly = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化缓存
|
||||
/// </summary>
|
||||
public FCInitializeOperation InitializeAsync(FCInitializeOptions options)
|
||||
{
|
||||
var operation = new FCInitializeOperation(this, options);
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 存储缓存文件
|
||||
/// </summary>
|
||||
public FCStoreCacheOperation StoreCacheAsync(FCStoreCacheOptions options)
|
||||
{
|
||||
var operation = new FCStoreCacheOperation(this, options);
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理缓存文件
|
||||
/// </summary>
|
||||
public FCClearCacheOperation ClearCacheAsync(FCClearCacheOptions options)
|
||||
{
|
||||
var operation = new FCClearCacheOperation(this, options);
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否已缓存指定 Bundle
|
||||
/// </summary>
|
||||
public bool IsCached(string bundleGUID)
|
||||
{
|
||||
return _caches.ContainsKey(bundleGUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存记录
|
||||
/// </summary>
|
||||
public BundleCacheEntry GetEntry(string bundleGUID)
|
||||
{
|
||||
if (_caches.TryGetValue(bundleGUID, out BundleCacheEntry entry))
|
||||
return entry;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有的缓存记录
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<BundleCacheEntry> GetAllEntries()
|
||||
{
|
||||
return _caches.Values;
|
||||
}
|
||||
|
||||
#region 内部方法
|
||||
/// <summary>
|
||||
/// 获取 Bundle 数据文件路径
|
||||
/// </summary>
|
||||
internal string GetDataFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_dataFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = GetHashFolderName(bundle.FileHash);
|
||||
filePath = PathUtility.Combine(RootPath, folderName, bundle.BundleGUID, BundleCacheDefine.BundleDataFileName);
|
||||
if (AppendFileExtension)
|
||||
filePath += bundle.FileExtension;
|
||||
_dataFilePathMapping.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 信息文件路径
|
||||
/// </summary>
|
||||
internal string GetInfoFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_infoFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = GetHashFolderName(bundle.FileHash);
|
||||
filePath = PathUtility.Combine(RootPath, folderName, bundle.BundleGUID, BundleCacheDefine.BundleInfoFileName);
|
||||
_infoFilePathMapping.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加指定缓存
|
||||
/// </summary>
|
||||
internal void AddEntry(string bundleGUID, BundleCacheEntry entry)
|
||||
{
|
||||
if (_caches.ContainsKey(bundleGUID))
|
||||
throw new YooInternalException($"Cache already existed: {bundleGUID}");
|
||||
|
||||
_caches.Add(bundleGUID, entry);
|
||||
SpaceOccupied += entry.DataFileSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定缓存
|
||||
/// </summary>
|
||||
internal void RemoveEntry(string bundleGUID)
|
||||
{
|
||||
if (_caches.TryGetValue(bundleGUID, out BundleCacheEntry entry))
|
||||
{
|
||||
_caches.Remove(bundleGUID);
|
||||
_dataFilePathMapping.Remove(bundleGUID);
|
||||
_infoFilePathMapping.Remove(bundleGUID);
|
||||
SpaceOccupied -= entry.DataFileSize;
|
||||
entry.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetHashFolderName(string fileHash)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fileHash))
|
||||
throw new YooInternalException();
|
||||
|
||||
if (fileHash.Length <= HashFolderLength)
|
||||
return fileHash;
|
||||
return fileHash.Substring(0, HashFolderLength);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,9 @@ namespace YooAsset
|
||||
|
||||
public override AssetBundle LoadFromMemory()
|
||||
{
|
||||
if (IsSupportFileIO(_options.FileLoadPath) == false)
|
||||
return null;
|
||||
|
||||
byte[] fileData = FileUtility.ReadAllBytes(_options.FileLoadPath);
|
||||
if (fileData == null || fileData.Length == 0)
|
||||
return null;
|
||||
@@ -198,7 +201,7 @@ namespace YooAsset
|
||||
|
||||
private AssetBundleCreateRequest _createRequest;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
public DefaultLoadAssetBundleFromMemoryOperation(LoadAssetBundleOptions options) : base(options) { }
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -26,7 +26,7 @@ namespace YooAsset
|
||||
|
||||
public DefaultLoadWebAssetBundleOperation(LoadWebAssetBundleOptions opionts) : base(opionts)
|
||||
{
|
||||
_failedTryAgain = opionts.FailedTryAgain;
|
||||
_failedTryAgain = opionts.RetryCount;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -56,7 +56,7 @@ namespace YooAsset
|
||||
if (_downloadAssetBundleRequest.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadAssetBundleRequest.Status == EDownloadRequestStatus.Succeed)
|
||||
if (_downloadAssetBundleRequest.Status == EDownloadRequestStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
@@ -67,7 +67,7 @@ namespace YooAsset
|
||||
if (_failedTryAgain > 0)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
YooLogger.Warning($"Failed download : {_downloadAssetBundleRequest.URL} Try again.");
|
||||
YooLogger.Warning($"Failed download : {_downloadAssetBundleRequest.Url} Try again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -136,7 +136,7 @@ namespace YooAsset
|
||||
|
||||
public DefaultLoadWebAssetBundleFromMemoryOperation(LoadWebAssetBundleOptions opionts) : base(opionts)
|
||||
{
|
||||
_failedTryAgain = opionts.FailedTryAgain;
|
||||
_failedTryAgain = opionts.RetryCount;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
@@ -167,7 +167,7 @@ namespace YooAsset
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeed)
|
||||
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
|
||||
{
|
||||
var rawData = Decryption(_downloadBytesRequest.Result);
|
||||
if (rawData == null || rawData.Length == 0)
|
||||
@@ -198,7 +198,7 @@ namespace YooAsset
|
||||
if (_failedTryAgain > 0)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
YooLogger.Warning($"Failed download : {_downloadBytesRequest.URL} Try again.");
|
||||
YooLogger.Warning($"Failed download : {_downloadBytesRequest.Url} Try again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d4152d48d076244fb4e339ebd34db0a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EditorFileCache : IFileCache
|
||||
{
|
||||
internal struct CacheConfig
|
||||
{
|
||||
public bool VirtualDownloadMode { get; set; }
|
||||
public bool VirtualWebGLMode { get; set; }
|
||||
public int AsyncSimulateMinFrame { get; set; }
|
||||
public int AsyncSimulateMaxFrame { get; set; }
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, EditorFileCacheEntry> _caches = new Dictionary<string, EditorFileCacheEntry>(10000);
|
||||
|
||||
// 缓存配置
|
||||
internal readonly CacheConfig Config;
|
||||
|
||||
#region 接口属性
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存根目录
|
||||
/// </summary>
|
||||
public string RootPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 只读属性
|
||||
/// </summary>
|
||||
public bool IsReadOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存文件数量
|
||||
/// </summary>
|
||||
public int FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _caches.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已占用空间
|
||||
/// 说明:按缓存索引累计
|
||||
/// </summary>
|
||||
public long SpaceOccupied { get; private set; }
|
||||
#endregion
|
||||
|
||||
public EditorFileCache(string packageName, string rootPath, CacheConfig config)
|
||||
{
|
||||
PackageName = packageName;
|
||||
RootPath = rootPath;
|
||||
Config = config;
|
||||
IsReadOnly = true;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
public virtual FCInitializeOperation InitializeAsync()
|
||||
{
|
||||
var operation = new EFCInitializeOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
||||
{
|
||||
var operation = new EFCWriteCacheOperation(this, options);
|
||||
return operation;
|
||||
}
|
||||
public virtual FCClearCacheOperation ClearCacheAsync(ClearCacheOptions options)
|
||||
{
|
||||
var operation = new FCClearCacheCompleteOperation();
|
||||
return operation;
|
||||
}
|
||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
||||
{
|
||||
var operation = new FCVerifyCacheCompleteOperation();
|
||||
return operation;
|
||||
}
|
||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
||||
{
|
||||
var operation = new EFCLoadVirtualBundleOperation(this, options.Bundle);
|
||||
return operation;
|
||||
}
|
||||
public virtual bool IsCached(string bundleGUID)
|
||||
{
|
||||
if (Config.VirtualDownloadMode)
|
||||
return _caches.ContainsKey(bundleGUID);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
#region 内部方法
|
||||
/// <summary>
|
||||
/// 获取指定缓存
|
||||
/// </summary>
|
||||
public EditorFileCacheEntry GetEntry(string bundleGUID)
|
||||
{
|
||||
if (_caches.TryGetValue(bundleGUID, out EditorFileCacheEntry entry))
|
||||
return entry;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加指定缓存
|
||||
/// </summary>
|
||||
internal void AddEntry(string bundleGUID, EditorFileCacheEntry entry)
|
||||
{
|
||||
if (_caches.ContainsKey(bundleGUID))
|
||||
throw new YooInternalException($"Cache entry already existed: {bundleGUID}");
|
||||
|
||||
_caches.Add(bundleGUID, entry);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8fe012ac4472e645a3f9235636be7e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EditorFileCacheEntry : ICacheEntry
|
||||
{
|
||||
public string BundleGUID { get; private set; }
|
||||
public string FilePath { get; private set; }
|
||||
|
||||
public EditorFileCacheEntry(string bundleGUID, string filePath)
|
||||
{
|
||||
BundleGUID = bundleGUID;
|
||||
FilePath = filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0381df9e70060b54bb4985fb7f5f9a77
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6b994fd3cded4a45b28ae75987780fa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFCInitializeOperation : FCInitializeOperation
|
||||
{
|
||||
private readonly EditorFileCache _fileCache;
|
||||
|
||||
public EFCInitializeOperation(EditorFileCache cache)
|
||||
{
|
||||
_fileCache = cache;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92dc2e40bf8f75e4aadcb2a137192c40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFCLoadVirtualBundleOperation : FCLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadVirtualBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly EditorFileCache _fileCache;
|
||||
private readonly PackageBundle _bundle;
|
||||
private int _asyncSimulateFrame;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public EFCLoadVirtualBundleOperation(EditorFileCache fileCache, PackageBundle bundle)
|
||||
{
|
||||
_fileCache = fileCache;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadVirtualBundle;
|
||||
_asyncSimulateFrame = GetAsyncSimulateFrame();
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadVirtualBundle)
|
||||
{
|
||||
var entry = _fileCache.GetEntry(_bundle.BundleGUID);
|
||||
if (entry == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
{
|
||||
if (_fileCache.Config.VirtualWebGLMode)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "WebGL mode only support asyn load method.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_asyncSimulateFrame--;
|
||||
if (_asyncSimulateFrame <= 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
|
||||
private int GetAsyncSimulateFrame()
|
||||
{
|
||||
return UnityEngine.Random.Range(_fileCache.Config.AsyncSimulateMinFrame, _fileCache.Config.AsyncSimulateMaxFrame + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35ea191497792124a9e76418e1b7f6d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFCWriteCacheOperation : FCWriteCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Check,
|
||||
CacheFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly EditorFileCache _cache;
|
||||
private readonly WriteCacheOptions _options;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public EFCWriteCacheOperation(EditorFileCache cache, WriteCacheOptions options)
|
||||
{
|
||||
_cache = cache;
|
||||
_options = options;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.Check;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Check)
|
||||
{
|
||||
if (_cache.IsCached(_options.Bundle.BundleGUID))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "The bundle is cached.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CacheFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CacheFile)
|
||||
{
|
||||
var cacheEntry = new EditorFileCacheEntry(_options.Bundle.BundleGUID, _options.FilePath);
|
||||
_cache.AddEntry(_options.Bundle.BundleGUID, cacheEntry);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 835873c2997792a4a9aaa2bc283de35a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,11 +3,6 @@ using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载 AssetBundle 的 Operation 工厂委托
|
||||
/// </summary>
|
||||
public delegate LoadAssetBundleOperation LoadAssetBundleOperationFactory(bool bundleEncrypted, LoadAssetBundleOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 加载 AssetBundle 的抽象基类
|
||||
/// 用户可继承此类实现自定义加载逻辑(如加密解密)
|
||||
@@ -2,11 +2,6 @@ using System.Text;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载 RawBundle 的 Operation 工厂委托
|
||||
/// </summary>
|
||||
public delegate LoadRawBundleOperation LoadRawBundleOperationFactory(bool bundleEncrypted, LoadRawBundleOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 加载 RawBundle 的抽象基类
|
||||
/// 用户可继承此类实现自定义加载逻辑(如加密解密)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user