diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloadSystemDefine.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadSystemDefine.cs
index 1fe19898..e693d1bc 100644
--- a/Assets/YooAsset/Runtime/DownloadSystem/DownloadSystemDefine.cs
+++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloadSystemDefine.cs
@@ -2,100 +2,6 @@ using System.Collections.Generic;
namespace YooAsset
{
- ///
- /// 下载器结束
- ///
- public struct DownloaderFinishData
- {
- ///
- /// 所属包裹名称
- ///
- public string PackageName;
-
- ///
- /// 是否成功
- ///
- public bool Succeed;
- }
-
- ///
- /// 下载器相关的更新数据
- ///
- public struct DownloadUpdateData
- {
- ///
- /// 所属包裹名称
- ///
- public string PackageName;
-
- ///
- /// 下载进度 (0-1f)
- ///
- public float Progress;
-
- ///
- /// 下载文件总数
- ///
- public int TotalDownloadCount;
-
- ///
- /// 当前完成的下载文件数量
- ///
- public int CurrentDownloadCount;
-
- ///
- /// 下载数据总大小(单位:字节)
- ///
- public long TotalDownloadBytes;
-
- ///
- /// 当前完成的下载数据大小(单位:字节)
- ///
- public long CurrentDownloadBytes;
- }
-
- ///
- /// 下载器相关的错误数据
- ///
- public struct DownloadErrorData
- {
- ///
- /// 所属包裹名称
- ///
- public string PackageName;
-
- ///
- /// 下载失败的文件名称
- ///
- public string FileName;
-
- ///
- /// 错误信息
- ///
- public string ErrorInfo;
- }
-
- ///
- /// 下载器相关的文件数据
- ///
- public struct DownloadFileData
- {
- ///
- /// 所属包裹名称
- ///
- public string PackageName;
-
- ///
- /// 下载的文件名称
- ///
- public string FileName;
-
- ///
- /// 下载的文件大小
- ///
- public long FileSize;
- }
-
///
/// 导入文件的信息
///
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/README.md b/Assets/YooAsset/Runtime/DownloadSystem/README.md
index 1f857d95..6800ab0a 100644
--- a/Assets/YooAsset/Runtime/DownloadSystem/README.md
+++ b/Assets/YooAsset/Runtime/DownloadSystem/README.md
@@ -41,20 +41,20 @@ DownloadSystem 的职责是提供“可替换后端 + 统一请求接口 + 轮
```
┌─────────────────────────────────────────────────────────┐
-│ 上层调用者 │
-│ (FileSystem / ResourceManager) │
+│ 上层调用者 │
+│ (FileSystem / ResourceManager) │
└─────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────▼───────────────────────────────┐
-│ IDownloadBackend │
+│ IDownloadBackend │
│ (后端接口) │
-│ 定义网络库合约,工厂模式创建请求 │
+│ 定义网络库合约,工厂模式创建请求 │
└─────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────▼───────────────────────────────┐
-│ IDownloadRequest │
+│ IDownloadRequest │
│ (请求接口) │
-│ 轮询式生命周期管理,状态机驱动 │
+│ 轮询式生命周期管理,状态机驱动 │
└─────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────▼───────────────────────────────┐
@@ -244,16 +244,6 @@ public struct DownloadSimulateRequestArgs
}
```
-### 回调数据结构体
-
-| 结构体 | 用途 | 关键字段 |
-|--------|------|----------|
-| `DownloaderFinishData` | 下载完成回调 | `PackageName`, `Succeed` |
-| `DownloadUpdateData` | 进度更新回调 | `Progress`, `TotalDownloadBytes`, `CurrentDownloadBytes` |
-| `DownloadErrorData` | 下载错误回调 | `FileName`, `ErrorInfo` |
-| `DownloadFileData` | 文件完成回调 | `FileName`, `FileSize` |
-| `ImportFileInfo` | 导入文件元数据 | `FilePath`, `BundleName`, `BundleGUID` |
-
---
## 核心类说明
diff --git a/Assets/YooAsset/Runtime/OperationSystem/README.md b/Assets/YooAsset/Runtime/OperationSystem/README.md
index 60b1f76a..dece1f34 100644
--- a/Assets/YooAsset/Runtime/OperationSystem/README.md
+++ b/Assets/YooAsset/Runtime/OperationSystem/README.md
@@ -32,23 +32,23 @@ OperationSystem 是 YooAsset 资源管理系统的**异步操作调度核心**
```
┌─────────────────────────────────────────────────────────┐
-│ 上层调用者 │
+│ 上层调用者 │
│ (ResourceManager / FileSystem / 业务层) │
└─────────────────────────┬───────────────────────────────┘
│ StartOperation()
┌─────────────────────────▼───────────────────────────────┐
-│ OperationSystem │
+│ OperationSystem │
│ (调度器) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
-│ │ 优先级队列 │ │ 时间切片 │ │ 回调通知 │ │
+│ │ 优先级队列 │ │ 时间切片 │ │ 回调通知 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────┬───────────────────────────────┘
│ UpdateOperation()
┌─────────────────────────▼───────────────────────────────┐
-│ AsyncOperationBase │
+│ AsyncOperationBase │
│ (操作基类) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
-│ │ 状态机 │ │ 子任务管理 │ │ 异步模式 │ │
+│ │ 状态机 │ │ 子任务管理 │ │ 异步模式 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
```
diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs
index de063aad..fa39a055 100644
--- a/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs
+++ b/Assets/YooAsset/Runtime/ResourcePackage/Operation/DownloaderOperation.cs
@@ -3,13 +3,115 @@ using System.Collections.Generic;
namespace YooAsset
{
+ #region 下载器相关类型定义
+ ///
+ /// 下载器结束
+ ///
+ public struct DownloaderFinishData
+ {
+ ///
+ /// 所属包裹名称
+ ///
+ public string PackageName;
+
+ ///
+ /// 是否成功
+ ///
+ public bool Succeed;
+ }
+
+ ///
+ /// 下载器相关的更新数据
+ ///
+ public struct DownloadUpdateData
+ {
+ ///
+ /// 所属包裹名称
+ ///
+ public string PackageName;
+
+ ///
+ /// 下载进度 (0-1f)
+ ///
+ public float Progress;
+
+ ///
+ /// 下载文件总数
+ ///
+ public int TotalDownloadCount;
+
+ ///
+ /// 当前完成的下载文件数量
+ ///
+ public int CurrentDownloadCount;
+
+ ///
+ /// 下载数据总大小(单位:字节)
+ ///
+ public long TotalDownloadBytes;
+
+ ///
+ /// 当前完成的下载数据大小(单位:字节)
+ ///
+ public long CurrentDownloadBytes;
+ }
+
+ ///
+ /// 下载器相关的错误数据
+ ///
+ public struct DownloadErrorData
+ {
+ ///
+ /// 所属包裹名称
+ ///
+ public string PackageName;
+
+ ///
+ /// 下载失败的文件名称
+ ///
+ public string FileName;
+
+ ///
+ /// 错误信息
+ ///
+ public string ErrorInfo;
+ }
+
+ ///
+ /// 下载器相关的文件数据
+ ///
+ public struct DownloadFileData
+ {
+ ///
+ /// 所属包裹名称
+ ///
+ public string PackageName;
+
+ ///
+ /// 资源包名称
+ ///
+ public string BundleName;
+
+ ///
+ /// 文件名称
+ ///
+ public string FileName;
+
+ ///
+ /// 文件大小
+ ///
+ public long FileSize;
+ }
+ #endregion
+
public abstract class DownloaderOperation : AsyncOperationBase
{
private enum ESteps
{
None,
Check,
- Loading,
+ Downloading,
+ Finish,
Done,
}
@@ -127,15 +229,37 @@ namespace YooAsset
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
- Error = "Download list is null.";
+ Error = "Download bundle list is null.";
+
+ if (DownloadFinishCallback != null)
+ {
+ var data = new DownloaderFinishData();
+ data.PackageName = _packageName;
+ data.Succeed = false;
+ DownloadFinishCallback.Invoke(data);
+ }
+ }
+ else if (_bundleInfoList.Count == 0)
+ {
+ _steps = ESteps.Done;
+ Status = EOperationStatus.Succeed;
+ Progress = 1f;
+
+ if (DownloadFinishCallback != null)
+ {
+ var data = new DownloaderFinishData();
+ data.PackageName = _packageName;
+ data.Succeed = true;
+ DownloadFinishCallback.Invoke(data);
+ }
}
else
{
- _steps = ESteps.Loading;
+ _steps = ESteps.Downloading;
}
}
- if (_steps == ESteps.Loading)
+ if (_steps == ESteps.Downloading)
{
// 检测下载器结果
_removeList.Clear();
@@ -172,7 +296,10 @@ namespace YooAsset
{
_lastDownloadBytes = downloadBytes;
_lastDownloadCount = _cachedDownloadCount;
- Progress = (float)_lastDownloadBytes / TotalDownloadBytes;
+ if (TotalDownloadBytes == 0)
+ Progress = (float)_lastDownloadCount / TotalDownloadCount;
+ else
+ Progress = (float)_lastDownloadBytes / TotalDownloadBytes;
if (DownloadUpdateCallback != null)
{
@@ -209,54 +336,60 @@ namespace YooAsset
{
var data = new DownloadFileData();
data.PackageName = _packageName;
- data.FileName = bundleInfo.Bundle.BundleName;
+ data.BundleName = bundleInfo.Bundle.BundleName;
+ data.FileName = bundleInfo.Bundle.FileName;
data.FileSize = bundleInfo.Bundle.FileSize;
DownloadFileBeginCallback.Invoke(data);
}
}
}
- // 下载结算
+ // 下载结束
if (_downloaders.Count == 0)
{
- if (_failedList.Count > 0)
+ _steps = ESteps.Finish;
+ }
+ }
+
+ if (_steps == ESteps.Finish)
+ {
+ if (_failedList.Count > 0)
+ {
+ var failedDownloader = _failedList[0];
+ string bundleName = failedDownloader.Bundle.BundleName;
+ _steps = ESteps.Done;
+ Status = EOperationStatus.Failed;
+ Error = $"Failed to download file : {bundleName}";
+
+ if (DownloadErrorCallback != null)
{
- var failedDownloader = _failedList[0];
- string bundleName = failedDownloader.Bundle.BundleName;
- _steps = ESteps.Done;
- Status = EOperationStatus.Failed;
- Error = $"Failed to download file : {bundleName}";
-
- if (DownloadErrorCallback != null)
- {
- var data = new DownloadErrorData();
- data.PackageName = _packageName;
- data.FileName = bundleName;
- data.ErrorInfo = failedDownloader.Error;
- DownloadErrorCallback.Invoke(data);
- }
-
- if (DownloadFinishCallback != null)
- {
- var data = new DownloaderFinishData();
- data.PackageName = _packageName;
- data.Succeed = false;
- DownloadFinishCallback.Invoke(data);
- }
+ var data = new DownloadErrorData();
+ data.PackageName = _packageName;
+ data.FileName = bundleName;
+ data.ErrorInfo = failedDownloader.Error;
+ DownloadErrorCallback.Invoke(data);
}
- else
- {
- // 结算成功
- _steps = ESteps.Done;
- Status = EOperationStatus.Succeed;
- if (DownloadFinishCallback != null)
- {
- var data = new DownloaderFinishData();
- data.PackageName = _packageName;
- data.Succeed = true;
- DownloadFinishCallback.Invoke(data);
- }
+ if (DownloadFinishCallback != null)
+ {
+ var data = new DownloaderFinishData();
+ data.PackageName = _packageName;
+ data.Succeed = false;
+ DownloadFinishCallback.Invoke(data);
+ }
+ }
+ else
+ {
+ // 结算成功
+ _steps = ESteps.Done;
+ Status = EOperationStatus.Succeed;
+
+ if (DownloadFinishCallback != null)
+ {
+ var data = new DownloaderFinishData();
+ data.PackageName = _packageName;
+ data.Succeed = true;
+ DownloadFinishCallback.Invoke(data);
}
}
}
diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs
index 87afcfcc..e7b1a455 100644
--- a/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs
+++ b/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs
@@ -91,7 +91,7 @@ namespace YooAsset
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
- Error = $"The manifest file version are not compatible : {fileVersion} != {ManifestDefine.FileVersion}";
+ Error = $"The manifest version is lower than the minimum compatible version : {fileVer} < {ver2025_8_28}";
return;
}
@@ -158,7 +158,7 @@ namespace YooAsset
FillAssetCollection(Manifest, packageAsset, replaceAssetPath);
_packageAssetCount--;
- Progress = 1f - _packageAssetCount / _progressTotalValue;
+ Progress = 1f - (_packageAssetCount / (float)_progressTotalValue);
if (IsBusy)
break;
}
@@ -192,7 +192,7 @@ namespace YooAsset
FillBundleCollection(Manifest, packageBundle);
_packageBundleCount--;
- Progress = 1f - _packageBundleCount / _progressTotalValue;
+ Progress = 1f - (_packageBundleCount / (float)_progressTotalValue);
if (IsBusy)
break;
}
diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/PlayModeImpl.cs b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/PlayModeImpl.cs
index b15f0b51..c14c8f0e 100644
--- a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/PlayModeImpl.cs
+++ b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/PlayModeImpl.cs
@@ -298,7 +298,8 @@ namespace YooAsset
return new List();
// 获取资源对象的资源包和所有依赖资源包
- List checkList = new List();
+ HashSet checkSet = new HashSet();
+ List checkList = new List(assetInfos.Length);
foreach (var assetInfo in assetInfos)
{
if (assetInfo.IsInvalid)
@@ -309,15 +310,21 @@ namespace YooAsset
// 注意:如果清单里未找到资源包会抛出异常!
PackageBundle mainBundle = manifest.GetMainPackageBundle(assetInfo.Asset);
- if (checkList.Contains(mainBundle) == false)
+ if (checkSet.Contains(mainBundle.BundleGUID) == false)
+ {
+ checkSet.Add(mainBundle.BundleGUID);
checkList.Add(mainBundle);
+ }
// 注意:如果清单里未找到资源包会抛出异常!
List mainDependBundles = manifest.GetAssetAllDependencies(assetInfo.Asset);
foreach (var dependBundle in mainDependBundles)
{
- if (checkList.Contains(dependBundle) == false)
+ if (checkSet.Contains(dependBundle.BundleGUID) == false)
+ {
+ checkSet.Add(dependBundle.BundleGUID);
checkList.Add(dependBundle);
+ }
}
// 下载主资源包内所有资源对象依赖的资源包
@@ -326,14 +333,20 @@ namespace YooAsset
foreach (var otherMainAsset in mainBundle.IncludeMainAssets)
{
var otherMainBundle = manifest.GetMainPackageBundle(otherMainAsset.BundleID);
- if (checkList.Contains(otherMainBundle) == false)
+ if (checkSet.Contains(otherMainBundle.BundleGUID) == false)
+ {
+ checkSet.Add(otherMainBundle.BundleGUID);
checkList.Add(otherMainBundle);
+ }
List otherDependBundles = manifest.GetAssetAllDependencies(otherMainAsset);
foreach (var dependBundle in otherDependBundles)
{
- if (checkList.Contains(dependBundle) == false)
+ if (checkSet.Contains(dependBundle.BundleGUID) == false)
+ {
+ checkSet.Add(dependBundle.BundleGUID);
checkList.Add(dependBundle);
+ }
}
}
}
diff --git a/Assets/YooAsset/Runtime/ResourcePackage/README.md b/Assets/YooAsset/Runtime/ResourcePackage/README.md
index 3cc7b297..b40987a6 100644
--- a/Assets/YooAsset/Runtime/ResourcePackage/README.md
+++ b/Assets/YooAsset/Runtime/ResourcePackage/README.md
@@ -372,6 +372,8 @@ public class PackageBundle
清单序列化工具类。
+> 注意:`DeserializeFromJson` 仅用于编辑器/调试用途,不保证运行时可用;运行时请优先使用二进制清单 `DeserializeFromBinary`。
+
```csharp
// 验证清单数据完整性
static bool VerifyManifestData(byte[] fileData, string hashValue);
@@ -381,6 +383,7 @@ static string SerializeToJson(PackageManifest manifest);
static byte[] SerializeToBinary(PackageManifest manifest);
// 反序列化
+// 注意:JSON 反序列化仅用于编辑器/调试用途,运行时请优先使用二进制清单。
static PackageManifest DeserializeFromJson(string jsonContent);
static PackageManifest DeserializeFromBinary(byte[] binaryData);
diff --git a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs
index e48a6dbd..d9f0af1f 100644
--- a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs
+++ b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs
@@ -1163,7 +1163,6 @@ namespace YooAsset
#endregion
#region 调试方法
- [Conditional("DEBUG")]
private void DebugCheckInitialize(bool checkActiveManifest = true)
{
if (_initializeStatus == EOperationStatus.None)