refactor : 重构代码

This commit is contained in:
何冠峰
2026-01-27 17:32:20 +08:00
parent 48a121f961
commit c2d8b8efcb
393 changed files with 7239 additions and 4598 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.cs text eol=lf

BIN
Assets/YooAsset.zip Normal file

Binary file not shown.

View File

@@ -204,7 +204,7 @@ namespace YooAsset.Editor
packageBundle.FileHash = PackageFileHash;
packageBundle.FileCRC = PackageFileCRC;
packageBundle.FileSize = PackageFileSize;
packageBundle.Encrypted = Encrypted;
packageBundle.IsEncrypted = Encrypted;
return packageBundle;
}
}

View File

@@ -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();

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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}";

View File

@@ -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);
}
}
}

View File

@@ -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)
{

View File

@@ -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();
}

View File

@@ -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()

View File

@@ -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();
}
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -47,7 +47,7 @@ namespace YooAsset
/// <summary>
/// 子任务列表
/// TODO : Serialization depth limit 10 exceeded
/// TODO序列化深度限制为10层
/// </summary>
public List<DiagnosticOperationInfo> Children;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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平台目前无法确定

View File

@@ -19,7 +19,7 @@ namespace YooAsset
/// <summary>
/// 已成功
/// </summary>
Succeed,
Succeeded,
/// <summary>
/// 已失败

View File

@@ -73,6 +73,6 @@ namespace YooAsset
/// </remarks>
/// <param name="args">模拟下载参数</param>
/// <returns>模拟下载请求实例</returns>
IDownloadFileRequest CreateSimulateRequest(DownloadSimulateRequestArgs args);
IDownloadFileRequest CreateSimulateRequest(SimulateDownloadRequestArgs args);
}
}

View File

@@ -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>

View File

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

View File

@@ -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()
{

View File

@@ -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>

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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
}
}

View File

@@ -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();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: fb3347395a55d3048bcec202aca0e4a7
guid: 0df121ea04074ca46b7fbe7932a5d452
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,12 +0,0 @@
using System.Collections.Generic;
namespace YooAsset
{
internal struct FCClearCacheOptions
{
/// <summary>
/// 清理指定缓存列表
/// </summary>
public IReadOnlyList<string> BundleGUIDs { get; set; }
}
}

View File

@@ -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;
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9be990c57fe162845ba3893188a68f8b
guid: 22422599c3cb80342ad546cbc4b8adc5
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,16 +0,0 @@
namespace YooAsset
{
internal struct FCInitializeOptions
{
/// <summary>
/// 文件校验最大并发数
/// </summary>
public int FileVerifyMaxConcurrency { get; set; }
/// <summary>
/// 文件校验级别
/// </summary>
public EFileVerifyLevel FileVerifyLevel { get; set; }
}
}

View File

@@ -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()
{
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 75f6c6588c154e145b09fa36cc6f2602
guid: f80086e0af509ae47829d80ca2037f5c
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -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()
{
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: cbe6c6f462ef0c9429568f9d1df559f6
guid: 920884f1ed1f59948aeb0fe0acdab027
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,16 @@
namespace YooAsset
{
internal struct VerifyCacheOptions
{
/// <summary>
/// 要验证的资源包
/// </summary>
public PackageBundle Bundle { get; set; }
/// <summary>
/// 失败后直接移除缓存
/// </summary>
public bool FailedDeleteCache { get; set; }
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 03f8c5e4c7af7df4387f56d045d8d357
guid: b3daf736aed95a848a15feb00d81ed0f
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -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()
{
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 773d121e67073ec44adaa843ebcb01a0
guid: d7127f4341e3a9e43a7db51c48737241
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -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; }
}
}

View File

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

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 07e60a75ff092314cb4d9ba6d5b14296
guid: 3fc8cc5c0f4f38941bcbad7d4866d535
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -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
}
}

View File

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

View File

@@ -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;
}
}
}

View File

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

View File

@@ -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";
}
}

View File

@@ -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();
{

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 34b5f5fd59f780c40bd9e581c5c6a718
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}
}

View File

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

View File

@@ -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();
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0dd4916e71be0934883f2fc404dd18fc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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()
{

View File

@@ -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
{

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d4152d48d076244fb4e339ebd34db0a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

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

View File

@@ -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;
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d6b994fd3cded4a45b28ae75987780fa
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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()
{
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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();
}
}
}

View File

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

View File

@@ -3,11 +3,6 @@ using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 加载 AssetBundle 的 Operation 工厂委托
/// </summary>
public delegate LoadAssetBundleOperation LoadAssetBundleOperationFactory(bool bundleEncrypted, LoadAssetBundleOptions options);
/// <summary>
/// 加载 AssetBundle 的抽象基类
/// 用户可继承此类实现自定义加载逻辑(如加密解密)

View File

@@ -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