diff --git a/Assets/YooAsset/Docs/1.命名准则.md b/Assets/YooAsset/Docs/1.命名准则.md index 4d9d6dca..fb6817c0 100644 --- a/Assets/YooAsset/Docs/1.命名准则.md +++ b/Assets/YooAsset/Docs/1.命名准则.md @@ -53,6 +53,8 @@ | `LogOff` | `logOff` | ~~LogOut~~ | | `Email` | `email` | ~~EMail~~ | +> ✔️ 在 Unity 项目中,`ID` 保持全大写以与 Unity API 风格一致(如 `GetInstanceID()`、`PropertyToID()`),项目内应保持风格统一。 + ### 1.5 区分大小写 - 不要假定所有语言都区分大小写 diff --git a/Assets/YooAsset/Docs/日志规范.md b/Assets/YooAsset/Docs/日志规范.md index 12ca0cd8..12c9fc19 100644 --- a/Assets/YooAsset/Docs/日志规范.md +++ b/Assets/YooAsset/Docs/日志规范.md @@ -14,12 +14,12 @@ ```csharp // ✔️ -$"File cache entry not found: '{bundleGUID}'." +$"File cache entry not found: '{bundleGuid}'." $"Invalid clear method: '{options.ClearMethod}'." $"Could not find file '{filePath}'." // ❌ -$"File cache entry not found: {bundleGUID}." +$"File cache entry not found: {bundleGuid}." ``` ### 1.2 数值变量不加引号 @@ -95,6 +95,17 @@ throw new Exception("catalog file data is null or empty"); "Bundle handle null." ``` +> **例外**:`not found` 等 .NET 生态中广泛使用的惯用短语,允许省略 `was`,以保持简洁和一致性。 + +```csharp +// ✔️ 惯用短语,省略 was +"File cache entry not found: '{bundleGuid}'." +"Asset not found: '{assetPath}'." + +// ❌ 冗余 +"File cache entry was not found: '{bundleGuid}'." +``` + ### 2.3 不要以冠词或变量开头 消息以关键实体词开头,不要以 `The` / `A` / `An` 或变量开头,便于日志搜索和排序。 @@ -103,11 +114,11 @@ throw new Exception("catalog file data is null or empty"); ```csharp // ✔️ -$"Cache entry already exists: '{bundleGUID}'." +$"Cache entry already exists: '{bundleGuid}'." $"Log file '{name}' is full." // ❌ -$"The cache entry already exists: '{bundleGUID}'." +$"The cache entry already exists: '{bundleGuid}'." $"'{name}' log file is full." ``` @@ -174,7 +185,7 @@ $"Exception in {this.GetType().Name}.InternalStart: {ex}." ```csharp // ✔️ 统一格式 -$"File cache entry not found: '{bundleGUID}'." // 所有缓存未命中统一使用此句式 +$"File cache entry not found: '{bundleGuid}'." // 所有缓存未命中统一使用此句式 $"Exception in {GetType().Name}.{MethodName}: {ex}." // 所有异常日志统一使用此句式 // ❌ 同一语义不同表达 @@ -199,7 +210,7 @@ $"Exception in {GetType().Name}.{MethodName}: {ex}." // 所有异常日志统一 | # | 规则 | 正确示例 | 错误示例 | |---|------|---------|---------| -| 1 | 字符串变量值加单引号 | `'{bundleGUID}'` | `{bundleGUID}` | +| 1 | 字符串变量值加单引号 | `'{bundleGuid}'` | `{bundleGuid}` | | 2 | 数值变量不加引号 | `{count}` | `'{count}'` | | 3 | 类型名作主语不加引号 | `TypeName is not ...` | `'TypeName' is not ...` | | 4 | 异常对象不加引号 | `{ex.Message}` | `'{ex.Message}'` | diff --git a/Assets/YooAsset/Docs/注释规范.md b/Assets/YooAsset/Docs/注释规范.md index 09c1cb16..e98f8a35 100644 --- a/Assets/YooAsset/Docs/注释规范.md +++ b/Assets/YooAsset/Docs/注释规范.md @@ -21,7 +21,6 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( | `` | 简要描述类型或成员的功能 | 所有公共类型和成员 | | `` | 描述方法参数 | 方法、构造函数 | | `` | 描述方法返回值 | 有返回值的方法 | -| `` | 说明可能抛出的异常 | 可能抛出异常的方法 | | `` | 补充说明,提供额外细节 | 需要详细解释的成员 | | `` | 描述属性所代表的值 | 属性 | @@ -41,7 +40,6 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( | `` | 在 `` 等标签内分段 | | `` | 创建列表或表格 | | `` | 多行代码示例 | -| `` | 行内代码片段 | | `` | 包含使用示例 | ### 2.4 泛型与继承标签 @@ -71,13 +69,15 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( |----------|---------|---------| | 类 / 结构 | `` | ``、`` | | 接口 | `` | `` | -| 方法 | ``、``、`` | ``、``、`` | -| 构造函数 | ``、`` | `` | -| 属性 | `` | ``、`` | +| 方法 | ``、``、`` | ``、`` | +| 构造函数 | ``、`` | — | +| 属性 | `` | `` | | 事件 | `` | `` | | 枚举类型 | `` | — | | 枚举值 | `` | — | | 委托 | ``、``、`` | — | +| 接口实现成员 | `` | — | +| override 方法 | **不添加**注释 | — | --- @@ -89,17 +89,46 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( ✔️ 以**第三人称动词**开头。 -✔️ 完整语句末尾**建议**使用句号,短语式描述可省略。 +✔️ 句号规则:注释内容含逗号、分号等分句标点时,末尾**加**句号;纯短语**不加**句号。 + +```csharp +// ✔️ 含逗号 → 加句号 +/// 超时时间(秒),0 表示不限制。 +/// 下载结果,包含状态码和错误信息。 + +// ✔️ 纯短语 → 不加句号 +/// 资源包的完整下载地址 +/// 初始化操作句柄 +``` ❌ **禁止**重复方法名或参数类型中已表达的信息。 +❌ **禁止**在注释中重复方法命名后缀已表达的语义。常见后缀包括: + +| 命名后缀 | 已表达的语义 | 注释中禁止使用 | +|----------|------------|--------------| +| `Async` | 异步执行 | "异步" | +| `Internal` | 内部实现 | "内部" | + ❌ **禁止**以"这个方法"、"该类"等冗余前缀开头。 -### 4.2 常见动词约定 +### 4.2 常见开头约定 + +#### 属性 —— 描述值本身,不加动词前缀 + +属性的 `{ get; }` / `{ get; set; }` 访问器已表达读写语义,summary 应直接描述**值的含义**,避免用"获取"、"获取或设置"等动词前缀重复已知信息。 + +| 属性类型 | 推荐写法 | 反例 | +|----------|---------|------| +| 只读属性 | 名词短语,如 "错误信息" | ~~"获取错误信息"~~ | +| 可读写属性 | 名词短语,如 "当前下载进度" | ~~"获取或设置当前下载进度"~~ | +| 返回 bool 的属性 | "是否……",如 "是否为只读缓存" | ~~"判断是否为只读缓存"~~ | + +#### 方法 —— 以动词开头 | 成员类型 | 推荐开头动词 | |----------|-------------| -| 返回 bool 的方法 / 属性 | "检查是否"、"判断是否" | +| 返回 bool 的方法 | "检查是否"、"判断是否" | | 获取类方法 | "获取"、"查询" | | 设置类方法 | "设置"、"更新" | | 创建类方法 | "创建"、"构建"、"生成" | @@ -112,8 +141,6 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( ✔️ 说明有效范围和边界值(如为 `null` 时的行为、取值范围)。 -✔️ 完整语句末尾**建议**使用句号,短语式描述可省略。 - ❌ **禁止**仅重复参数名或类型名,如"url 参数"。 ### 4.4 `` 书写规范 @@ -122,13 +149,25 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( ✔️ 说明**特殊返回值**的含义(如返回 `null` 表示未找到)。 -### 4.5 `` 书写规范 +### 4.5 `` 书写规范 -✔️ 指定异常的**具体类型**(`cref` 属性)。 +✔️ 多行内容**必须**用 `` 包裹每段,否则 IDE 会将多行合并显示为一行。 -✔️ 说明异常的**触发条件**。 +```csharp +// ✔️ 好:每段用 包裹 +/// +/// 下载并加载 Unity AssetBundle 资源包 +/// 支持 Unity 内置缓存机制和 CRC 校验 +/// -✔️ 使用 `` 引用相关参数。 +// ❌ 差:多行纯文本,IDE 显示时会合并为一行 +/// +/// 下载并加载 Unity AssetBundle 资源包 +/// 支持 Unity 内置缓存机制和 CRC 校验 +/// +``` + +✔️ 单行内容可直接书写,无需 ``。 --- @@ -141,8 +180,8 @@ C# 使用 XML 文档注释为代码提供结构化文档。编译器从 `///`( /// 资源包下载请求,负责管理单个资源包的下载生命周期。 /// /// -/// 支持断点续传和失败重试。 -/// 通过 控制重试策略。 +/// 支持断点续传和失败重试 +/// 通过 控制重试策略 /// public class BundleDownloadRequest { @@ -153,16 +192,12 @@ public class BundleDownloadRequest ```csharp /// -/// 从指定 URL 异步下载资源包并保存到本地磁盘。 +/// 从指定 URL 下载资源包并保存到本地磁盘 /// -/// 资源包的完整下载地址。 -/// 本地保存的目标路径。 +/// 资源包的完整下载地址 +/// 本地保存的目标路径 /// 超时时间(秒),0 表示不限制。 /// 下载结果,包含状态码和错误信息。 -/// -/// 当 null 时抛出。 -/// -/// 当下载超过指定时间时抛出。 public async Task DownloadAsync(string url, string savePath, int timeout = 30) { } @@ -172,7 +207,7 @@ public async Task DownloadAsync(string url, string savePath, int ```csharp /// -/// 获取当前下载进度。 +/// 当前下载进度 /// /// 取值范围 0.0 ~ 1.0,其中 1.0 表示下载完成。 public float Progress { get; private set; } @@ -182,7 +217,7 @@ public float Progress { get; private set; } ```csharp /// -/// 下载任务的运行状态。 +/// 下载任务的运行状态 /// public enum DownloadStatus { @@ -192,17 +227,17 @@ public enum DownloadStatus Pending, /// - /// 正在下载中。 + /// 正在下载中 /// Downloading, /// - /// 下载已完成。 + /// 下载已完成 /// Completed, /// - /// 下载失败。 + /// 下载失败 /// Failed } @@ -224,17 +259,17 @@ public class ObjectPool where T : IDisposable ```csharp /// -/// 定义下载请求的标准行为。 +/// 定义下载请求的标准行为 /// public interface IDownloadRequest { /// - /// 获取请求的远程 URL。 + /// 请求的远程 URL /// string URL { get; } /// - /// 取消当前下载请求。 + /// 取消当前下载请求 /// void Abort(); } @@ -242,6 +277,10 @@ public interface IDownloadRequest ### 5.7 使用 `` +#### 接口实现 —— 使用 `` + +实现接口成员时,使用 `` 继承接口中定义的文档: + ```csharp public class MyDownloadRequest : IDownloadRequest { @@ -255,14 +294,35 @@ public class MyDownloadRequest : IDownloadRequest } ``` +#### 基类继承(override) —— 不添加任何注释 + +重写基类方法时,**不需要**添加任何 XML 文档注释(包括 ``)。方法签名中的 `override` 关键字已明确表达继承关系,IDE 会自动展示基类文档。 + +```csharp +// ✔️ 好:override 方法不添加注释 +protected override void InternalStart() +{ +} + +protected override void InternalUpdate() +{ +} + +// ❌ 差:多余的 inheritdoc +/// +protected override void InternalStart() +{ +} +``` + ### 5.8 使用 `` 和 `` ```csharp /// -/// 根据资源路径异步加载资源对象。 +/// 根据资源路径加载资源对象 /// -/// 资源路径。 -/// 资源操作句柄,加载失败时资源对象为 null +/// 资源路径 +/// 资源操作句柄,加载失败时资源对象为 null。 /// /// 加载一个预制体: /// @@ -291,10 +351,10 @@ public void Download(string url, string savePath) { } // ✔️ 好:说明行为和目的 /// -/// 从远程服务器下载资源包并保存到本地磁盘。 +/// 从远程服务器下载资源包并保存到本地磁盘 /// -/// 资源包的完整下载地址。 -/// 本地保存的目标路径。 +/// 资源包的完整下载地址 +/// 本地保存的目标路径 public void Download(string url, string savePath) { } ``` @@ -302,20 +362,36 @@ public void Download(string url, string savePath) { } ```csharp // ❌ 差:仅重复参数名 -/// 名称。 +/// 名称 // ✔️ 好:说明含义和约束 -/// 资源包的唯一标识名称,不可为 null 或空字符串。 +/// 资源包的唯一标识名称 ``` -### 6.3 缺少边界说明 +### 6.3 重复命名后缀 + +```csharp +// ❌ 差:方法名 Async 后缀已表达异步语义 +/// +/// 异步加载资源对象 +/// +public AssetHandle LoadAssetAsync(string location) { } + +// ✔️ 好:描述功能意图,不重复后缀语义 +/// +/// 加载资源对象 +/// +public AssetHandle LoadAssetAsync(string location) { } +``` + +### 6.4 缺少边界说明 ```csharp // ❌ 差:未说明返回 null 的情况 -/// 资源对象。 +/// 资源对象 // ✔️ 好:说明特殊返回值 -/// 加载到的资源对象,如果资源不存在则返回 null +/// 加载到的资源对象 ``` --- @@ -350,4 +426,78 @@ if (count > maxCount) // 环形缓冲区写满后从头覆盖,避免无限增长 if (count > maxCount) count = 0; -``` \ No newline at end of file +``` + +--- + +## 八、术语翻译映射表 + +> 为保持注释用语统一,以下列出项目中常用英文类型/概念与其中文翻译的对应关系。 +> 撰写或审核注释时,请以此表为准。 + +### 8.1 核心领域类型 + +| 英文类型 / 概念 | 中文翻译 | 备注 | +|-----------------|---------|------| +| `PackageBundle` | 资源包描述 | 清单中的静态元数据(`Package*` = 描述) | +| `PackageAsset` | 资源描述 | 清单中的静态元数据(`Package*` = 描述) | +| `AssetInfo` | 资源信息 | 运行时上下文(`*Info` = 信息) | +| `BundleInfo` | 资源包信息 | 运行时上下文(`*Info` = 信息) | +| `ResourcePackage` | 资源包裹 | 顶层包裹容器 | +| `PackageManifest` | 包裹清单 / 资源清单 | — | +| `AssetBundle` | AssetBundle | Unity 引擎类型,保留英文 | +| `RawBundle` | 原生资源包 | 非 AssetBundle 的原始文件 | + +### 8.2 文件系统与缓存 + +| 英文类型 / 概念 | 中文翻译 | 备注 | +|-----------------|---------|------| +| `IFileSystem` | 文件系统 | — | +| `IBundleCache` | 缓存系统 | — | +| `ICacheEntry` | 缓存条目 | — | +| `BundleGuid` | 资源包 GUID / Bundle 唯一标识 | — | +| `ICacheEvictionPolicy` | 淘汰策略 | — | +| `EvictionResult` | 淘汰结果 | — | + +### 8.3 下载与网络 + +| 英文类型 / 概念 | 中文翻译 | 备注 | +|-----------------|---------|------| +| `IDownloadRequest` | 下载请求 | — | +| `IDownloadBackend` | 下载后台 | — | +| `IRemoteService` | 远端资源服务 | — | +| `IDownloadRetryPolicy` | 下载重试策略 | — | +| `IDownloadUrlPolicy` | URL 选择策略 | — | + +### 8.4 加密与解密 + +| 英文类型 / 概念 | 中文翻译 | 备注 | +|-----------------|---------|------| +| `IBundleEncryptor` | 资源包加密器 | — | +| `IBundleDecryptor` | 资源包解密器 | 基接口,需实现派生接口 | +| `IManifestEncryptor` | 资源清单加密器 | — | +| `IManifestDecryptor` | 资源清单解密器 | — | +| `BundleEncryptArgs` | 加密操作的输入参数 | — | +| `BundleDecryptArgs` | 解密操作的输入参数 | — | + +### 8.5 资源加载与句柄 + +| 英文类型 / 概念 | 中文翻译 | 备注 | +|-----------------|---------|------| +| `IBundleHandle` | 资源包句柄 | — | +| `AssetHandle` | 资源句柄 | — | +| `RawFileHandle` | 原生文件句柄 | — | +| `SubAssetsHandle` | 子资源句柄 | — | + +### 8.6 通用术语 + +| 英文术语 | 中文翻译 | 备注 | +|---------|---------|------| +| Package | 包裹 | 项目级容器 | +| Bundle | 资源包 | 构建产物单元 | +| Asset | 资源 | 单个资源文件 | +| Manifest | 清单 | — | +| Handle | 句柄 | — | +| Operation | 操作 / 异步操作 | — | +| Scheduler | 调度器 | — | +| Provider | 提供者 | — | \ No newline at end of file diff --git a/Assets/YooAsset/Docs/逻辑检测.md b/Assets/YooAsset/Docs/逻辑检测.md new file mode 100644 index 00000000..21d82e30 --- /dev/null +++ b/Assets/YooAsset/Docs/逻辑检测.md @@ -0,0 +1,200 @@ +# 逻辑检测 + +> **总则**:检查运行时代码的关键逻辑路径,确保宏分支、异步操作生命周期、参数完整性和资源释放均无遗漏。 + +## 1. 宏包裹代码逻辑 + +检查所有 `#if` / `#elif` / `#else` / `#endif` 包裹的代码: + +- 每个分支的变量赋值路径是否完整(不存在未赋值分支) +- `#else` 兜底分支是否覆盖所有未列出的平台 +- 各分支之间的语义是否一致(同一变量在不同分支中的类型和用途是否相同) +- 分支中引用的 API 是否与对应宏版本匹配(如 `UNITY_2020_3_OR_NEWER` 对应的 API) + +## 2. 子异步操作检查 + +**定义**:通过 `AddChildOperation()` 添加的操作为子异步操作。 + +### 2.1 同步等待传播 + +如果类实现了 `InternalWaitForCompletion()` 方法,所有子异步操作必须在该方法中主动调用 `WaitForCompletion()`。 + +``` +❌ 父操作实现了 InternalWaitForCompletion,但未对子操作调用 WaitForCompletion +✅ 父操作在 InternalWaitForCompletion 中对每个子操作调用 WaitForCompletion() +``` + +### 2.2 更新驱动 + +所有子异步操作必须在父操作的 `InternalUpdate()` 中主动调用 `UpdateOperation()`,确保子操作能被正常驱动。 + +``` +❌ 子操作被 AddChildOperation 添加后,未在 InternalUpdate 中调用 UpdateOperation +✅ 每个子操作在 InternalUpdate 中被调用 UpdateOperation() +``` + +## 3. 异步操作参数完整性 + +检查所有 Operation 的 Options 在 `new` 的位置是否完整填充了所有成员字段。 + +- 找到 Options 结构体的所有字段定义 +- 找到所有 `new XxxOptions(...)` 的调用点 +- 逐一比对构造参数是否覆盖了所有必填字段 +- 可选参数(有默认值)可以跳过 + +``` +❌ new DownloadFileRequestOptions(url, savePath, timeout) // 遗漏了 watchdogTimeout +✅ new DownloadFileRequestOptions(url, savePath, timeout, watchdogTimeout) +``` + +## 4. 整数溢出与取模安全 + +检查所有对 `int` 计数器执行 `%`(取模)运算的位置,确保不会因溢出产生负索引。 + +- 只增不减的 `int` 计数器(如失败计数、轮转索引),溢出 `int.MaxValue` 后变为负数 +- 负数 `%` 正数在 C# 中结果为负数,用作数组/列表索引会触发 `ArgumentOutOfRangeException` +- 使用 `& 0x7FFFFFFF` 清除符号位,保证结果始终为非负整数(.NET 中处理哈希取模的惯用手法) + +``` +❌ int index = _counter % list.Count; // _counter 溢出后 index 为负 +✅ int index = (_counter & 0x7FFFFFFF) % list.Count; // 始终非负 +``` + +## 5. 下载请求资源释放 + +### 5.1 IDownloadRequest 释放 + +检查所有持有 `IDownloadRequest`(及其子接口)实例的 Operation,是否在 `InternalDispose()` 中调用了 `Dispose()` 释放资源。 + +``` +❌ Operation 持有 IDownloadFileRequest 但未在 InternalDispose 中释放 +✅ protected override void InternalDispose() { _request?.Dispose(); } +``` + +### 5.2 下载数据完整性验证 + +检查文件数据下载完成后,是否有容错或数据完整性验证: + +- 是否校验文件大小(下载字节数与预期是否一致) +- 是否校验文件哈希(CRC / MD5 / SHA 等) +- 如果无校验,是否有其他容错机制(如重试、回退) +- 无任何验证且无容错机制的,标记为需要关注 + +## 6. 计时方式一致性 + +检查所有需要"测量经过时间"的逻辑,确保计时方式不会因帧率波动或 App 后台恢复而失真。 + +- 使用 `Time.unscaledDeltaTime` 累加计时的方式,在 App 从后台恢复时会产生巨大 spike(一帧跨越几十秒),导致等待逻辑在单帧内被直接跳过 +- 同一系统内应保持计时方式统一,避免一处用绝对时间戳、另一处用帧增量 +- 推荐使用 `TimeUtility.RealtimeSinceStartup` 记录起止时间戳做差值判断 + +``` +❌ _elapsed += Time.unscaledDeltaTime; return _elapsed >= delay; // 后台恢复时 spike 跳过等待 +✅ return TimeUtility.RealtimeSinceStartup - _startTime >= delay; // 绝对时间戳,不受 spike 影响 +``` + +## 7. 子类回调不得覆写基类已确定的状态 + +检查所有基类定义的"成功/失败回调"(如 `OnRequestSucceeded`、`OnRequestFailed`),子类在重写时不应直接修改基类已确定的 `Status`。 + +- 基类在调用回调前已设置 `Status = Succeeded`,若子类在回调中将其改为 `Failed`,后续基类逻辑可能与实际状态不一致 +- 回调应仅负责提取结果或设置错误信息,状态转换应由基类统一控制 +- 推荐将回调签名改为返回 `bool`(或通过 out 参数传递错误),基类根据返回值决定最终状态 + +``` +❌ protected override void OnRequestSucceeded() + { + if (result == null) Status = Failed; // 子类直接覆写基类已确定的 Succeeded 状态 + } +✅ protected override bool OnRequestSucceeded() + { + if (result == null) { Error = "..."; return false; } // 返回 false,由基类设置 Failed + return true; + } +``` + +## 8. 结构体不可变性检测 + +> 依据:[类型设计准则](2.类型设计准则.md) — "❌ **禁止**定义可变值类型" / "✔️ 声明不可变值类型时使用 `readonly struct` 修饰符" + +检查所有 `struct` 定义,**必须**声明为 `readonly struct`。存在可变 struct 即为违规。 + +检测要点: + +- `struct` 声明缺少 `readonly` 修饰符 +- 属性使用 `{ get; set; }` 而非 `{ get; }` +- 公共字段未声明为 `readonly` +- 缺少构造函数(依赖默认值逐字段赋值的模式) + +``` +❌ struct MutableConfig + { + public int Timeout { get; set; } // 可变属性 + public string Name { get; set; } + } + +✅ readonly struct ImmutableConfig + { + public int Timeout { get; } // 只读属性 + public string Name { get; } + public ImmutableConfig(int timeout, string name) + { + Timeout = timeout; + Name = name; + } + } +``` + +**禁止可变 struct 的原因**: + +- 值类型按值复制,可变成员修改作用于副本而非原值,极易产生静默 bug +- `readonly` 字段持有可变 struct 时,编译器每次访问都会产生防御性复制,造成不必要的性能开销 +- `readonly struct` 从根源上杜绝以上两类问题 + +## 9. 文件系统禁止重写 GetHashCode + +检查所有 `IFileSystem` 实现类,确认未重写 `GetHashCode()` 或 `Equals()`。 + +`BundleInfo.GetCombineKey()` 依赖 `RuntimeHelpers.GetHashCode(_fileSystem)` 获取基于引用标识的哈希值,用于下载器合并时的去重判断。如果文件系统实现类重写了 `GetHashCode()`,虽然 `RuntimeHelpers.GetHashCode` 本身不受影响,但会暗示该类型有自定义相等性语义,可能导致其他使用 `GetHashCode()` 的位置产生非预期的碰撞。 + +检测要点: + +- `IFileSystem` 实现类中存在 `override int GetHashCode()` 声明 +- `IFileSystem` 实现类中存在 `override bool Equals(object)` 声明 + +``` +❌ class SandboxFileSystem : IFileSystem + { + public override int GetHashCode() => PackageName.GetHashCode(); // 破坏引用标识语义 + } + +✅ class SandboxFileSystem : IFileSystem + { + // 不重写 GetHashCode,保持 object 默认的引用标识行为 + } +``` + +## 10. 不可变结构体命名参数检测 + +检测所有 `readonly struct` 构造函数调用中**位置参数 > 3 个**的位置,确认是否使用命名参数提高可读性。 + +`readonly struct` 只能通过构造函数一次性传入所有字段,参数数量通常较多,且参数顺序是唯一区分手段。同类型参数相邻时,顺序错误不会产生编译错误,容易引入静默 bug。 + +重点检查以下场景: + +- 构造函数参数 > 3 个 +- 多个同类型参数相邻(如连续多个 `bool`、`int`、接口类型) +- 参数名与属性名高度对应,使用命名参数可消除歧义 + +``` +❌ new Configuration(60, true, level, decryptor, backend, retryPolicy, urlPolicy); + +✅ new Configuration( + watchdogTimeout: 60, + disableUnityWebCache: true, + downloadVerifyLevel: level, + assetBundleDecryptor: decryptor, + downloadBackend: backend, + downloadRetryPolicy: retryPolicy, + downloadUrlPolicy: urlPolicy); +``` diff --git a/Assets/YooAsset/Docs/逻辑检测.md.meta b/Assets/YooAsset/Docs/逻辑检测.md.meta new file mode 100644 index 00000000..6562ca12 --- /dev/null +++ b/Assets/YooAsset/Docs/逻辑检测.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 200087470392cf24ebdd0efac8e44210 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildParameters.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildParameters.cs index 98c3bc68..cb46b982 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildParameters.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildParameters.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Collections; using System.Collections.Generic; @@ -146,7 +146,7 @@ namespace YooAsset.Editor string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineIsNullOrEmpty, "Build pipeline is null or empty !"); throw new Exception(message); } - if (BuildBundleType == (int)EBundleType.Unknown) + if (BuildBundleType == (int)EBundleType.None) { string message = BuildLogger.GetErrorMessage(ErrorCode.BuildBundleTypeIsUnknown, $"Build bundle type is unknown {BuildBundleType} !"); throw new Exception(message); diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs index 29550da4..d0589760 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs @@ -54,8 +54,8 @@ namespace YooAsset.Editor { foreach (var packageBundle in manifest.BundleList) { - string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}"; - string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}"; + string sourcePath = $"{packageOutputDirectory}/{packageBundle.GetFileName()}"; + string destPath = $"{buildinRootDirectory}/{packageBundle.GetFileName()}"; EditorTools.CopyFile(sourcePath, destPath, true); } } @@ -68,8 +68,8 @@ namespace YooAsset.Editor { if (packageBundle.HasAnyTag(tags) == false) continue; - string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}"; - string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}"; + string sourcePath = $"{packageOutputDirectory}/{packageBundle.GetFileName()}"; + string destPath = $"{buildinRootDirectory}/{packageBundle.GetFileName()}"; EditorTools.CopyFile(sourcePath, destPath, true); } } diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs index b6a7cf3f..03961747 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs @@ -35,7 +35,7 @@ namespace YooAsset.Editor manifest.EnableAddressable = buildMapContext.Command.EnableAddressable; manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless; manifest.LocationToLower = buildMapContext.Command.LocationToLower; - manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID; + manifest.IncludeAssetGuid = buildMapContext.Command.IncludeAssetGUID; manifest.ReplaceAssetPathWithAddress = replaceAssetPathWithAddress; manifest.OutputNameStyle = (int)buildParameters.FileNameStyle; manifest.BuildBundleType = buildParameters.BuildBundleType; @@ -152,7 +152,7 @@ namespace YooAsset.Editor PackageAsset packageAsset = new PackageAsset(); packageAsset.Address = buildMapContext.Command.EnableAddressable ? assetInfo.Address : string.Empty; packageAsset.AssetPath = assetInfo.AssetInfo.AssetPath; - packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty; + packageAsset.AssetGuid = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty; packageAsset.AssetTags = assetInfo.AssetTags.ToArray(); packageAsset.EditorUserData = assetInfo; result.Add(packageAsset); diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs index b2efbf87..a2d46a65 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs @@ -102,7 +102,7 @@ namespace YooAsset.Editor { ReportBundleInfo reportBundleInfo = new ReportBundleInfo(); reportBundleInfo.BundleName = packageBundle.BundleName; - reportBundleInfo.FileName = packageBundle.FileName; + reportBundleInfo.FileName = packageBundle.GetFileName(); reportBundleInfo.FileHash = packageBundle.FileHash; reportBundleInfo.FileCRC = packageBundle.FileCrc; reportBundleInfo.FileSize = packageBundle.FileSize; diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs index 2ad777e6..eb589f0c 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.IO; using System.Collections; @@ -24,15 +24,14 @@ namespace YooAsset.Editor string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory(); foreach (var bundleInfo in buildMapContext.Collection) { - BundleEncryptArgs args = new BundleEncryptArgs(); - args.BundleName = bundleInfo.BundleName; - args.FilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}"; + string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}"; + var args = new BundleEncryptArgs(bundleInfo.BundleName, filePath); var encryptResult = encryptionServices.Encrypt(args); - if (encryptResult.Encrypted) + if (encryptResult.IsEncrypted) { - string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt"; + string encryptedFilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt"; FileUtility.WriteAllBytes(filePath, encryptResult.EncryptedFileData); - bundleInfo.EncryptedFilePath = filePath; + bundleInfo.EncryptedFilePath = encryptedFilePath; bundleInfo.Encrypted = true; BuildLogger.Log($"Bundle file encryption complete: {filePath}"); } diff --git a/Assets/YooAsset/Editor/AssetBundleDebugger/AssetBundleDebuggerWindow.cs b/Assets/YooAsset/Editor/AssetBundleDebugger/AssetBundleDebuggerWindow.cs index 094ce07c..9bd2706e 100644 --- a/Assets/YooAsset/Editor/AssetBundleDebugger/AssetBundleDebuggerWindow.cs +++ b/Assets/YooAsset/Editor/AssetBundleDebugger/AssetBundleDebuggerWindow.cs @@ -1,4 +1,4 @@ -#if UNITY_2019_4_OR_NEWER +#if UNITY_2019_4_OR_NEWER using System; using System.Collections.Generic; using UnityEditor; @@ -255,7 +255,7 @@ namespace YooAsset.Editor { // 发送采集数据的命令 DiagnosticCommand command = new DiagnosticCommand(); - command.CommandType = (int)EDiagnosticCommandType.AutoSampling; + command.CommandType = EDiagnosticCommandType.AutoSampling; command.Parameter = evt.newValue ? "open" : "close"; byte[] data = DiagnosticCommand.Serialize(command); EditorConnection.instance.Send(DiagnosticSystemConsts.EditorToPlayerMessageId, data); @@ -266,7 +266,7 @@ namespace YooAsset.Editor { // 发送采集数据的命令 DiagnosticCommand command = new DiagnosticCommand(); - command.CommandType = (int)EDiagnosticCommandType.SampleOnce; + command.CommandType = EDiagnosticCommandType.SampleOnce; command.Parameter = string.Empty; byte[] data = DiagnosticCommand.Serialize(command); EditorConnection.instance.Send(DiagnosticSystemConsts.EditorToPlayerMessageId, data); diff --git a/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerAssetListViewer.cs b/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerAssetListViewer.cs index a382199c..97fe95d1 100644 --- a/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerAssetListViewer.cs +++ b/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerAssetListViewer.cs @@ -379,7 +379,9 @@ namespace YooAsset.Editor var sourceDatas = new List(providerInfo.Dependencies.Count); foreach (var bundleName in providerInfo.Dependencies) { - var dependBundleInfo = packageData.GetBundleInfo(bundleName); + if (packageData.TryGetBundleInfo(bundleName, out var dependBundleInfo) == false) + continue; + var rowData = new DependTableData(); rowData.BundleInfo = dependBundleInfo; rowData.AddStringValueCell("DependBundles", dependBundleInfo.BundleName); diff --git a/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerBundleListViewer.cs b/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerBundleListViewer.cs index 59c8a1e1..ebcd8100 100644 --- a/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerBundleListViewer.cs +++ b/Assets/YooAsset/Editor/AssetBundleDebugger/VisualViewers/DebuggerBundleListViewer.cs @@ -468,7 +468,9 @@ namespace YooAsset.Editor var sourceDatas = new List(1000); foreach (string referenceBundleName in selectBundleInfo.Referencers) { - var bundleInfo = packageData.GetBundleInfo(referenceBundleName); + if (packageData.TryGetBundleInfo(referenceBundleName, out var bundleInfo) == false) + continue; + var rowData = new ReferenceTableData(); rowData.BundleInfo = bundleInfo; rowData.AddStringValueCell("BundleName", bundleInfo.BundleName); diff --git a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs index a2f96c97..22e1fe1c 100644 --- a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs +++ b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs @@ -33,10 +33,10 @@ namespace YooAsset internal bool IsWaitForCompletion { get; private set; } /// - /// 判断当前帧时间切片是否已用完 + /// 当前帧时间切片是否已用完 /// /// - /// 同步等待时始终返回 false,以确保操作能持续执行直到完成 + /// 同步等待时始终返回 false,以确保操作能持续执行直到完成。 /// protected bool IsBusy { @@ -73,7 +73,7 @@ namespace YooAsset public float Progress { get; protected set; } /// - /// 判断异步操作是否已结束 + /// 异步操作是否已结束 /// public bool IsDone { @@ -103,7 +103,7 @@ namespace YooAsset /// 异步操作的完成事件 /// /// - /// 若注册时操作已完成,回调将立即执行 + /// 若注册时操作已完成,回调将立即执行。 /// public event Action Completed { @@ -119,7 +119,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"Exception in completion callback: {ex}."); + YooLogger.LogError($"Exception in completion callback: {ex}."); } } else @@ -178,7 +178,7 @@ namespace YooAsset { _error = $"Operation '{GetType().Name}' did not complete during synchronous wait."; _status = EOperationStatus.Failed; - YooLogger.Error(_error); + YooLogger.LogError(_error); } // 注意:强制收尾,确保Task能完成 @@ -209,7 +209,7 @@ namespace YooAsset // 内部逻辑抛出异常一律视为该异步任务失败。 _error = ex.ToString(); _status = EOperationStatus.Failed; - YooLogger.Error($"Exception in {GetType().Name}.InternalStart: {ex}."); + YooLogger.LogError($"Exception in {GetType().Name}.InternalStart: {ex}."); } // 注意:同步完成的操作立即收尾 @@ -243,7 +243,7 @@ namespace YooAsset // 内部逻辑抛出异常一律视为该异步任务失败。 _error = ex.ToString(); _status = EOperationStatus.Failed; - YooLogger.Error($"Exception in {GetType().Name}.InternalUpdate: {ex}."); + YooLogger.LogError($"Exception in {GetType().Name}.InternalUpdate: {ex}."); } } @@ -271,7 +271,7 @@ namespace YooAsset InternalAbort(); _error = "Operation was aborted."; _status = EOperationStatus.Failed; - YooLogger.Warning($"Async operation '{GetType().Name}' has been aborted."); + YooLogger.LogWarning($"Async operation '{GetType().Name}' has been aborted."); } // 注意:强制收尾,确保Task能完成 @@ -316,7 +316,7 @@ namespace YooAsset /// 内部同步等待方法(子类可选实现) /// /// - /// 默认抛出异常,子类应重写以支持同步等待 + /// 默认抛出异常,子类应重写以支持同步等待。 /// protected virtual void InternalWaitForCompletion() { @@ -327,7 +327,6 @@ namespace YooAsset /// /// 将操作标记为成功完成 /// - /// 操作已处于终结状态时抛出 protected void SetResult() { if (IsDone) @@ -340,7 +339,6 @@ namespace YooAsset /// 将操作标记为失败 /// /// 错误描述 - /// 操作已处于终结状态时抛出 protected void SetError(string error) { if (IsDone) @@ -350,6 +348,22 @@ namespace YooAsset _status = EOperationStatus.Failed; } + /// + /// 计算多阶段操作的整体进度 + /// + /// 当前阶段索引(从0开始) + /// 阶段总数 + /// 当前阶段剩余工作量 + /// 当前阶段总工作量 + /// 返回归一化的整体进度值(0-1) + protected float CalculateMultiStageProgress(int stageIndex, int stageCount, int remaining, int total) + { + if (total <= 0) + return (stageIndex + 1f) / stageCount; + float stageProgress = 1f - remaining / (float)total; + return (stageIndex + stageProgress) / stageCount; + } + /// /// 添加子任务 /// @@ -391,7 +405,7 @@ namespace YooAsset throw new YooInternalException("Child operation is null."); if (_children.Contains(child) == false) - throw new YooInternalException($"Child operation '{child.GetType().Name}' was not found."); + throw new YooInternalException($"Child operation '{child.GetType().Name}' not found."); #endif _children.Remove(child); @@ -411,7 +425,7 @@ namespace YooAsset /// /// 批量执行一定次数的更新逻辑 /// - /// 最大执行次数,默认1000次 + /// 最大执行次数,默认1000次。 /// /// 用于需要快速完成但又不想完全阻塞主线程的场景 /// @@ -438,7 +452,7 @@ namespace YooAsset /// /// 每次循环后的休眠时长(毫秒) /// - /// 该方法会阻塞调用线程,每次更新之间会短暂休眠以避免占满 CPU + /// 该方法会阻塞调用线程,每次更新之间会短暂休眠以避免占满 CPU。 /// protected void ExecuteUntilComplete(int sleepMilliseconds = 1) { @@ -475,7 +489,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"Exception in {GetType().Name}.InternalDispose: {ex}."); + YooLogger.LogError($"Exception in {GetType().Name}.InternalDispose: {ex}."); } InvokeCompletedCallbacks(); @@ -495,7 +509,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"Exception in completion callback: {ex}."); + YooLogger.LogError($"Exception in completion callback: {ex}."); } _completedCallback = null; } @@ -510,7 +524,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"Exception in completion callback: {ex}."); + YooLogger.LogError($"Exception in completion callback: {ex}."); } } _completedCallbackList = null; diff --git a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationScheduler.cs b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationScheduler.cs index f12bc76d..cc6ef815 100644 --- a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationScheduler.cs +++ b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationScheduler.cs @@ -47,7 +47,7 @@ namespace YooAsset /// /// 创建异步操作调度器实例 /// - /// 所属包裹的名称。 + /// 所属包裹的名称 /// 创建顺序,用于同优先级时的稳定排序。 public AsyncOperationScheduler(string packageName, int creationOrder) { @@ -60,7 +60,7 @@ namespace YooAsset /// /// 要启动的异步操作 /// - /// 操作立即启动,下一次 Update 时合并到执行队列 + /// 操作立即启动,下一次 Update 时合并到执行队列。 /// public void StartOperation(AsyncOperationBase operation) { @@ -146,7 +146,7 @@ namespace YooAsset /// /// 获取调试信息 /// - /// 包含所有运行中和待处理操作的诊断信息列表。 + /// 包含所有运行中和待处理操作的诊断信息列表 public List GetDiagnosticInfos() { int totalCount = _runningOperations.Count + _pendingOperations.Count; diff --git a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationSystem.cs b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationSystem.cs index 04926e7e..710ba88b 100644 --- a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationSystem.cs +++ b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationSystem.cs @@ -6,7 +6,7 @@ using System.Diagnostics; namespace YooAsset { /// - /// 异步操作系统,负责管理所有包裹的调度器 + /// 异步操作系统,负责管理所有包裹的调度器。 /// internal static class AsyncOperationSystem { @@ -40,7 +40,7 @@ namespace YooAsset /// /// 最小值为 毫秒,低于此值将被自动钳制。 /// - /// 设置过小会导致每帧可执行的操作极少,影响整体加载速度 + /// 设置过小会导致每帧可执行的操作极少,影响整体加载速度。 /// public static long MaxTimeSlice { @@ -53,7 +53,7 @@ namespace YooAsset if (value < MinTimeSlice) { _maxTimeSlice = MinTimeSlice; - YooLogger.Warning($"MaxTimeSlice must be at least {MinTimeSlice} ms, clamped to {MinTimeSlice}."); + YooLogger.LogWarning($"MaxTimeSlice must be at least {MinTimeSlice} ms, clamped to {MinTimeSlice}."); } else { @@ -63,7 +63,7 @@ namespace YooAsset } /// - /// 判断当前帧的时间切片预算是否已用完 + /// 当前帧的时间切片预算是否已用完 /// public static bool IsBusy { @@ -88,7 +88,7 @@ namespace YooAsset { if (_isInitialized) { - YooLogger.Warning("Operation system is already initialized."); + YooLogger.LogWarning("Operation system is already initialized."); return; } @@ -232,7 +232,7 @@ namespace YooAsset /// 设置指定包裹调度器的优先级 /// /// 包裹名称 - /// 优先级,值越大越优 + /// 优先级,值越大越优。 public static void SetSchedulerPriority(string packageName, uint priority) { DebugCheckInitialized(packageName); @@ -245,7 +245,7 @@ namespace YooAsset /// 获取指定包裹调度器的优先级 /// /// 包裹名称 - /// 调度器的当前优先级。 + /// 调度器的当前优先级 public static uint GetSchedulerPriority(string packageName) { DebugCheckInitialized(packageName); @@ -272,8 +272,8 @@ namespace YooAsset /// /// 获取指定包裹中所有操作的诊断信息 /// - /// 包裹名称。 - /// 该包裹下所有操作的诊断信息列表。 + /// 包裹名称 + /// 该包裹下所有操作的诊断信息列表 internal static List GetDiagnosticInfos(string packageName) { DebugCheckInitialized(packageName); diff --git a/Assets/YooAsset/Runtime/AsyncOperation/OperationAwaiter.cs b/Assets/YooAsset/Runtime/AsyncOperation/OperationAwaiter.cs index 34623e43..41e886b3 100644 --- a/Assets/YooAsset/Runtime/AsyncOperation/OperationAwaiter.cs +++ b/Assets/YooAsset/Runtime/AsyncOperation/OperationAwaiter.cs @@ -27,7 +27,7 @@ namespace YooAsset /// 获取操作结果 /// /// - /// 业务失败不视为异常,此处不抛出异常 + /// 业务失败不视为异常,此处不抛出异常。 /// public void GetResult() { @@ -45,4 +45,4 @@ namespace YooAsset _operation.Completed += (op) => continuation(); } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Interfaces/EvictionResult.cs b/Assets/YooAsset/Runtime/BundleCache/Interfaces/EvictionResult.cs index 92c3fb44..802ddbaa 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Interfaces/EvictionResult.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Interfaces/EvictionResult.cs @@ -7,56 +7,51 @@ namespace YooAsset /// internal readonly struct EvictionResult { + private readonly bool _initialized; + /// /// 错误信息 /// - public readonly string Error; + public string Error { get; } /// /// 需要清理的资源标识符集合 /// - public readonly List BundleGUIDs; + public IReadOnlyList BundleGuids { get; } /// - /// 是否成功 + /// 是否执行成功 /// public bool Succeeded { - get { return Error == null; } + get { return _initialized && Error == null; } } - /// - /// 创建失败结果 - /// - public EvictionResult(string error) + private EvictionResult(string error, IReadOnlyList bundleGuids) { + _initialized = true; Error = error; - BundleGUIDs = null; + BundleGuids = bundleGuids; } /// - /// 创建成功结果 + /// 创建表示执行成功的淘汰结果 /// - public EvictionResult(List bundleGUIDs) + /// 需要清理的资源包标识符列表 + /// 携带待清理列表的成功结果 + public static EvictionResult CreateSuccess(IReadOnlyList bundleGuids) { - Error = null; - BundleGUIDs = bundleGUIDs; + return new EvictionResult(null, bundleGuids); } /// - /// 创建成功结果 + /// 创建表示执行失败的淘汰结果 /// - public static EvictionResult Success(List bundleGUIDs) + /// 描述失败原因的错误信息 + /// 携带错误信息的失败结果 + public static EvictionResult CreateFailure(string error) { - return new EvictionResult(bundleGUIDs); - } - - /// - /// 创建失败结果 - /// - public static EvictionResult Failure(string error) - { - return new EvictionResult(error); + return new EvictionResult(error, null); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Interfaces/IBundleCache.cs b/Assets/YooAsset/Runtime/BundleCache/Interfaces/IBundleCache.cs index 38db3573..97f6dbcd 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Interfaces/IBundleCache.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Interfaces/IBundleCache.cs @@ -18,7 +18,7 @@ namespace YooAsset string RootPath { get; } /// - /// 只读属性 + /// 是否为只读缓存 /// bool IsReadOnly { get; } @@ -34,33 +34,44 @@ namespace YooAsset /// - /// 初始化文件缓存系统 + /// 初始化缓存系统 /// + /// 初始化异步操作对象 BCInitializeOperation InitializeAsync(); /// - /// 写入缓存文件 + /// 将资源包数据写入缓存 /// + /// 写入操作的配置参数 + /// 写入缓存异步操作对象 BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options); /// - /// 清理缓存文件 + /// 清理符合淘汰策略的缓存文件 /// + /// 清理操作的配置参数 + /// 清理缓存异步操作对象 BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options); /// - /// 验证缓存文件 + /// 验证缓存文件的完整性 /// + /// 验证操作的配置参数 + /// 验证缓存异步操作对象 BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options); /// - /// 加载资源包 + /// 加载指定资源包 /// + /// 加载操作的配置参数 + /// 加载资源包异步操作对象 BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options); /// - /// 是否已缓存指定 Bundle + /// 检查指定资源包是否已存在于缓存中 /// - bool IsCached(string bundleGUID); + /// 资源包的唯一标识符 + /// 如果缓存中存在该资源包则返回 true,否则返回 false。 + bool IsCached(string bundleGuid); } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEntry.cs b/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEntry.cs index d16606af..d2f3060e 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEntry.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEntry.cs @@ -7,8 +7,8 @@ namespace YooAsset internal interface ICacheEntry { /// - /// Bundle唯一标识 + /// Bundle 唯一标识 /// - string BundleGUID { get; } + string BundleGuid { get; } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEvictionPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEvictionPolicy.cs index ec6d37dd..4ddf7e52 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEvictionPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Interfaces/ICacheEvictionPolicy.cs @@ -8,8 +8,11 @@ namespace YooAsset internal interface ICacheEvictionPolicy { /// - /// 根据策略从缓存条目中选出需要清理的 BundleGUID 列表 + /// 选出需要清理的 BundleGuid 列表 /// + /// 当前全部缓存条目的只读集合 + /// 缓存清理的配置参数 + /// 包含待清理 BundleGuid 列表的执行结果,失败时携带错误信息。 EvictionResult SelectEvictionTargets(IReadOnlyCollection cacheEntries, BCClearCacheOptions options); } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOperation.cs index 76753894..29169ddb 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOperation.cs @@ -11,14 +11,22 @@ namespace YooAsset /// /// 清理缓存完成操作 /// - internal class BCClearCacheCompleteOperation : BCClearCacheOperation + internal sealed class BCClearCacheCompleteOperation : BCClearCacheOperation { private readonly string _error; + /// + /// 创建清理缓存完成操作实例 + /// public BCClearCacheCompleteOperation() { _error = null; } + + /// + /// 创建清理缓存完成操作实例 + /// + /// 错误信息 public BCClearCacheCompleteOperation(string error) { _error = error; diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOptions.cs index c6888834..3062a31a 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCClearCacheOptions.cs @@ -4,21 +4,28 @@ namespace YooAsset /// /// 清理缓存操作选项 /// - internal struct BCClearCacheOptions + internal readonly struct BCClearCacheOptions { /// /// 清理方式 /// - public string ClearMethod { get; set; } + public string ClearMethod { get; } /// /// 附加参数 /// - public object ClearParameter { get; set; } + public object ClearParameter { get; } /// /// 资源清单 /// - public PackageManifest Manifest { get; set; } + public PackageManifest Manifest { get; } + + public BCClearCacheOptions(string clearMethod, object clearParameter, PackageManifest manifest) + { + ClearMethod = clearMethod; + ClearParameter = clearParameter; + Manifest = manifest; + } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOperation.cs index 27c8f373..35be40fb 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOperation.cs @@ -6,6 +6,9 @@ namespace YooAsset /// internal abstract class BCLoadBundleOperation : AsyncOperationBase { + /// + /// 资源包加载的内部结果 + /// protected readonly struct LoadResult { /// @@ -14,22 +17,32 @@ namespace YooAsset public readonly string Error; /// - /// 是否成功 + /// 加载是否成功 /// public bool Succeeded { get { return Error == null; } } - public LoadResult(string error) + private LoadResult(string error) { Error = error; } + /// + /// 创建表示加载成功的默认结果 + /// + /// 不携带错误信息的成功结果 public static LoadResult Default() { return new LoadResult(null); } + + /// + /// 创建表示加载失败的结果 + /// + /// 错误信息 + /// 携带错误信息的失败结果 public static LoadResult Failure(string error) { return new LoadResult(error); @@ -49,6 +62,10 @@ namespace YooAsset { private readonly string _error; + /// + /// 创建加载资源包错误操作实例 + /// + /// 错误信息 internal BCLoadBundleErrorOperation(string error) { _error = error; diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOptions.cs index b8333305..b8861b23 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCLoadBundleOptions.cs @@ -7,10 +7,14 @@ namespace YooAsset internal readonly struct BCLoadBundleOptions { /// - /// 资源包 + /// 要加载的资源包 /// - public readonly PackageBundle Bundle; + public PackageBundle Bundle { get; } + /// + /// 创建加载资源包操作选项实例 + /// + /// 要加载的资源包描述 public BCLoadBundleOptions(PackageBundle bundle) { Bundle = bundle; diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOperation.cs index a626388a..543b775e 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOperation.cs @@ -11,14 +11,23 @@ namespace YooAsset /// /// 验证缓存完成操作 /// - internal class BCVerifyCacheCompleteOperation : BCVerifyCacheOperation + internal sealed class BCVerifyCacheCompleteOperation : BCVerifyCacheOperation { private readonly string _error; + + /// + /// 创建验证缓存完成操作实例 + /// public BCVerifyCacheCompleteOperation() { _error = null; } + + /// + /// 创建验证缓存完成操作实例 + /// + /// 错误信息 public BCVerifyCacheCompleteOperation(string error) { _error = error; diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOptions.cs index e42a1cda..74965f14 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCVerifyCacheOptions.cs @@ -4,16 +4,22 @@ namespace YooAsset /// /// 验证缓存操作选项 /// - internal struct BCVerifyCacheOptions + internal readonly struct BCVerifyCacheOptions { /// /// 要验证的资源包 /// - public PackageBundle Bundle { get; set; } + public PackageBundle Bundle { get; } /// /// 失败后直接移除缓存条目 /// - public bool DeleteCacheEntryOnFailure { get; set; } + public bool DeleteCacheEntryOnFailure { get; } + + public BCVerifyCacheOptions(PackageBundle bundle, bool deleteCacheEntryOnFailure) + { + Bundle = bundle; + DeleteCacheEntryOnFailure = deleteCacheEntryOnFailure; + } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOperation.cs index 61d8e4de..75e9a0c1 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOperation.cs @@ -11,14 +11,22 @@ namespace YooAsset /// /// 写入缓存完成操作 /// - internal class BCWriteCacheCompleteOperation : BCWriteCacheOperation + internal sealed class BCWriteCacheCompleteOperation : BCWriteCacheOperation { private readonly string _error; + /// + /// 创建写入缓存完成操作实例 + /// public BCWriteCacheCompleteOperation() { _error = null; } + + /// + /// 创建写入缓存完成操作实例 + /// + /// 错误信息 public BCWriteCacheCompleteOperation(string error) { _error = error; diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOptions.cs index 439ce2fb..1dfaeba0 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/BCWriteCacheOptions.cs @@ -4,21 +4,28 @@ namespace YooAsset /// /// 写入缓存操作选项 /// - internal struct BCWriteCacheOptions + internal readonly struct BCWriteCacheOptions { /// /// 要缓存的资源包 /// - public PackageBundle Bundle { get; set; } + public PackageBundle Bundle { get; } /// /// 要缓存的文件路径 /// - public string FilePath { get; set; } + public string FilePath { get; } /// /// 要缓存的文件数据(可选) /// - public byte[] FileData { get; set; } + public byte[] FileData { get; } + + public BCWriteCacheOptions(PackageBundle bundle, string filePath, byte[] fileData = null) + { + Bundle = bundle; + FilePath = filePath; + FileData = fileData; + } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOperation.cs index 1ff9041e..b5b5aeaa 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOperation.cs @@ -28,6 +28,10 @@ namespace YooAsset /// public BuiltinCatalog Catalog; + /// + /// 创建加载内置资源目录操作实例 + /// + /// 加载内置资源目录的配置选项 internal LoadBuiltinCatalogOperation(LoadBuiltinCatalogOptions options) { _options = options; @@ -69,7 +73,10 @@ namespace YooAsset if (_downloadBytesRequest == null) { string url = DownloadUrlHelper.ToLocalFileUrl(_options.FilePath); - var args = new DownloadDataRequestArgs(url, 60, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: 60, + watchdogTimeout: 0); _downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args); _downloadBytesRequest.SendRequest(); } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOptions.cs index b6c71680..b7abe902 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadBuiltinCatalogOptions.cs @@ -4,21 +4,28 @@ namespace YooAsset /// /// 加载内置资源目录操作选项 /// - internal struct LoadBuiltinCatalogOptions + internal readonly struct LoadBuiltinCatalogOptions { /// /// 包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 文件路径 /// - public string FilePath { get; set; } + public string FilePath { get; } /// /// 下载后台 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } + + public LoadBuiltinCatalogOptions(string packageName, string filePath, IDownloadBackend downloadBackend) + { + PackageName = packageName; + FilePath = filePath; + DownloadBackend = downloadBackend; + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOperation.cs index a102323d..e8e2fc9e 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 从本地文件加载 AssetBundle 操作 /// - internal class LoadLocalAssetBundleOperation : BCLoadBundleOperation + internal sealed class LoadLocalAssetBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -27,6 +27,10 @@ namespace YooAsset /// public bool UnityEngineLoadFailed { get; private set; } = false; + /// + /// 创建本地 AssetBundle 加载操作实例 + /// + /// 从本地加载 AssetBundle 的配置选项 public LoadLocalAssetBundleOperation(LoadLocalAssetBundleOptions options) { _options = options; @@ -95,7 +99,7 @@ namespace YooAsset if (IsWaitForCompletion) { // 强制挂起主线程(注意:该操作会很耗时) - YooLogger.Warning("Suspending the main thread to load Unity bundle."); + YooLogger.LogWarning("Suspending the main thread to load Unity bundle."); _assetBundle = _createRequest.assetBundle; } else @@ -135,10 +139,11 @@ namespace YooAsset } private LoadResult LoadFromFileWithOffset(IBundleOffsetDecryptor decryptor) { - var args = new BundleDecryptArgs(); - args.Bundle = _options.Bundle; - args.FilePath = _options.FilePath; - ulong offset = (ulong)decryptor.GetFileOffset(args); + var args = new BundleDecryptArgs(_options.Bundle, null, _options.FilePath); + long rawOffset = decryptor.GetFileOffset(args); + if (rawOffset < 0) + return LoadResult.Failure($"{_options.CacheName} decryptor returned negative offset: {rawOffset}."); + ulong offset = (ulong)rawOffset; if (IsWaitForCompletion) _assetBundle = AssetBundle.LoadFromFile(_options.FilePath, 0, offset); @@ -149,9 +154,7 @@ namespace YooAsset } private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor) { - var args = new BundleDecryptArgs(); - args.Bundle = _options.Bundle; - args.FilePath = _options.FilePath; + var args = new BundleDecryptArgs(_options.Bundle, null, _options.FilePath); var binaryData = decryptor.GetDecryptedData(args); if (binaryData == null) return LoadResult.Failure($"{_options.CacheName} decryptor returned null data."); @@ -165,9 +168,7 @@ namespace YooAsset } private LoadResult LoadFromStream(IBundleStreamDecryptor decryptor) { - var args = new BundleDecryptArgs(); - args.Bundle = _options.Bundle; - args.FilePath = _options.FilePath; + var args = new BundleDecryptArgs(_options.Bundle, null, _options.FilePath); uint bufferSize = (uint)decryptor.GetBufferSize(args); _loadStream = decryptor.CreateDecryptionStream(args); if (_loadStream == null) diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOptions.cs index 3f889601..1677bfb9 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalAssetBundleOptions.cs @@ -4,27 +4,35 @@ namespace YooAsset /// /// 加载 AssetBundle 的上下文信息 /// - internal struct LoadLocalAssetBundleOptions + internal readonly struct LoadLocalAssetBundleOptions { /// /// 文件缓存名称 /// - public string CacheName { get; set; } + public string CacheName { get; } /// - /// 资源包信息 + /// 资源包描述 /// - public PackageBundle Bundle { get; set; } + public PackageBundle Bundle { get; } /// /// 文件加载路径 /// - public string FilePath { get; set; } + public string FilePath { get; } /// /// AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; } + + public LoadLocalAssetBundleOptions(string cacheName, PackageBundle bundle, string filePath, IBundleDecryptor assetBundleDecryptor) + { + CacheName = cacheName; + Bundle = bundle; + FilePath = filePath; + AssetBundleDecryptor = assetBundleDecryptor; + } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOperation.cs index aab5895a..dcd947f9 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 从本地加载 RawBundle 操作 /// - internal class LoadLocalRawBundleOperation : BCLoadBundleOperation + internal sealed class LoadLocalRawBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -16,10 +16,14 @@ namespace YooAsset Done, } - protected readonly LoadLocalRawBundleOptions _options; + private readonly LoadLocalRawBundleOptions _options; private RawBundle _rawBundle; private ESteps _steps = ESteps.None; + /// + /// 创建本地 RawBundle 加载操作实例 + /// + /// 从本地加载 RawBundle 的配置选项 public LoadLocalRawBundleOperation(LoadLocalRawBundleOptions options) { _options = options; @@ -44,7 +48,13 @@ namespace YooAsset return; } - LoadFromFile(); + LoadResult result = LoadFromFile(); + if (result.Succeeded == false) + { + _steps = ESteps.Done; + SetError(result.Error); + return; + } } else { @@ -99,16 +109,22 @@ namespace YooAsset ExecuteBatch(); } - private void LoadFromFile() + private LoadResult LoadFromFile() { - byte[] data = File.ReadAllBytes(_options.FilePath); - _rawBundle = new RawBundle(data); + try + { + byte[] data = File.ReadAllBytes(_options.FilePath); + _rawBundle = new RawBundle(data); + return LoadResult.Default(); + } + catch (Exception ex) + { + return LoadResult.Failure($"Failed to read raw bundle file: {ex.Message}."); + } } private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor) { - var args = new BundleDecryptArgs(); - args.Bundle = _options.Bundle; - args.FilePath = _options.FilePath; + var args = new BundleDecryptArgs(_options.Bundle, null, _options.FilePath); var binaryData = decryptor.GetDecryptedData(args); if (binaryData == null) return LoadResult.Failure($"{_options.CacheName} decryptor returned null data."); diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOptions.cs index f7524714..8097f207 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadLocalRawBundleOptions.cs @@ -4,26 +4,34 @@ namespace YooAsset /// /// 加载 RawBundle 的上下文信息 /// - internal struct LoadLocalRawBundleOptions + internal readonly struct LoadLocalRawBundleOptions { /// /// 文件缓存名称 /// - public string CacheName { get; set; } + public string CacheName { get; } /// - /// 资源包信息 + /// 资源包描述 /// - public PackageBundle Bundle { get; set; } + public PackageBundle Bundle { get; } /// /// 文件加载路径 /// - public string FilePath { get; set; } + public string FilePath { get; } /// /// RawBundle 解密器 /// - public IBundleDecryptor RawBundleDecryptor { get; set; } + public IBundleDecryptor RawBundleDecryptor { get; } + + public LoadLocalRawBundleOptions(string cacheName, PackageBundle bundle, string filePath, IBundleDecryptor rawBundleDecryptor) + { + CacheName = cacheName; + Bundle = bundle; + FilePath = filePath; + RawBundleDecryptor = rawBundleDecryptor; + } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOperation.cs index 4e18a447..5a6e3dfd 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOperation.cs @@ -12,7 +12,7 @@ namespace YooAsset /// /// 从网络加载未加密 AssetBundle 操作 /// - internal class LoadWebNormalAssetBundleOperation : LoadWebAssetBundleOperation + internal sealed class LoadWebNormalAssetBundleOperation : LoadWebAssetBundleOperation { private enum ESteps { @@ -28,6 +28,10 @@ namespace YooAsset private IDownloadAssetBundleRequest _downloadAssetBundleRequest; private ESteps _steps = ESteps.None; + /// + /// 创建网络未加密 AssetBundle 加载操作实例 + /// + /// 从网络加载 AssetBundle 的配置选项 public LoadWebNormalAssetBundleOperation(LoadWebAssetBundleOptions options) { _options = options; @@ -47,7 +51,13 @@ namespace YooAsset if (_steps == ESteps.BundleRequest) { string url = GetRequestUrl(); - var args = new DownloadAssetBundleRequestArgs(url, 0, _options.WatchdogTimeout, _options.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCrc); + var args = new DownloadAssetBundleRequestArgs( + url: url, + timeout: 0, + watchdogTimeout: _options.WatchdogTimeout, + disableUnityWebCache: _options.DisableUnityWebCache, + fileHash: _options.Bundle.FileHash, + unityCrc: _options.Bundle.UnityCrc); _downloadAssetBundleRequest = _options.DownloadBackend.CreateAssetBundleRequest(args); _downloadAssetBundleRequest.SendRequest(); _steps = ESteps.CheckRequest; @@ -66,7 +76,7 @@ namespace YooAsset if (assetBundle == null) { _steps = ESteps.Done; - SetError($"Fatal error: downloaded asset bundle is null."); + SetError("Downloaded asset bundle is null."); } else { @@ -128,7 +138,7 @@ namespace YooAsset /// /// 从网络加载加密的 AssetBundle 操作 /// - internal class LoadWebEncryptedAssetBundleOperation : LoadWebAssetBundleOperation + internal sealed class LoadWebEncryptedAssetBundleOperation : LoadWebAssetBundleOperation { private enum ESteps { @@ -149,6 +159,10 @@ namespace YooAsset private AssetBundleCreateRequest _createRequest; private ESteps _steps = ESteps.None; + /// + /// 创建网络加密 AssetBundle 加载操作实例 + /// + /// 从网络加载 AssetBundle 的配置选项 public LoadWebEncryptedAssetBundleOperation(LoadWebAssetBundleOptions options) { _options = options; @@ -179,7 +193,10 @@ namespace YooAsset { _decryptor = decryptor as IBundleMemoryDecryptor; string url = GetRequestUrl(); - var args = new DownloadDataRequestArgs(url, 0, _options.WatchdogTimeout); + var args = new DownloadDataRequestArgs( + url: url, + timeout: 0, + watchdogTimeout: _options.WatchdogTimeout); _downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args); _downloadBytesRequest.SendRequest(); _steps = ESteps.CheckRequest; @@ -231,7 +248,7 @@ namespace YooAsset else if (_options.DownloadVerifyLevel == EFileVerifyLevel.High) verifyResult = FileVerifyHelper.VerifyFile(_downloadBytesRequest.Result, _options.Bundle.FileSize, _options.Bundle.FileCrc); else - throw new System.NotImplementedException(_options.DownloadVerifyLevel.ToString()); + throw new YooInternalException($"Unexpected verify level: {_options.DownloadVerifyLevel}."); if (verifyResult == EFileVerifyResult.Succeed) { @@ -240,7 +257,7 @@ namespace YooAsset else { string error = $"[WebBundleVerify] Verify failed. Url: '{_downloadBytesRequest.Url}' Level: {_options.DownloadVerifyLevel} Result: {verifyResult}."; - YooLogger.Warning(error); + YooLogger.LogWarning(error); if (IsWaitForCompletion == false && _downloadRetryController.HasRetriesRemaining()) { @@ -314,9 +331,7 @@ namespace YooAsset private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor, byte[] fileData) { - var args = new BundleDecryptArgs(); - args.Bundle = _options.Bundle; - args.FileData = fileData; + var args = new BundleDecryptArgs(_options.Bundle, fileData, null); var binaryData = decryptor.GetDecryptedData(args); if (binaryData == null) return LoadResult.Failure($"{_options.CacheName} decryptor returned null data."); diff --git a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOptions.cs b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOptions.cs index ed939c54..42def912 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOptions.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Operations/Common/LoadWebAssetBundleOptions.cs @@ -5,56 +5,70 @@ namespace YooAsset /// /// 加载 AssetBundle 的上下文信息 /// - internal struct LoadWebAssetBundleOptions + internal readonly struct LoadWebAssetBundleOptions { /// /// 文件缓存名称 /// - public string CacheName { get; set; } + public string CacheName { get; } /// - /// 资源包信息 + /// 资源包描述 /// - public PackageBundle Bundle { get; set; } + public PackageBundle Bundle { get; } /// /// 候选下载地址列表 /// - public IReadOnlyList CandidateUrls { get; set; } + public IReadOnlyList CandidateUrls { get; } /// /// AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; } /// /// 下载后台接口 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } /// /// 下载数据校验级别 /// - public EFileVerifyLevel DownloadVerifyLevel { get; set; } + public EFileVerifyLevel DownloadVerifyLevel { get; } /// /// 看门狗超时时间 /// - public int WatchdogTimeout { get; set; } + public int WatchdogTimeout { get; } /// /// 禁用Unity的网络缓存 /// - public bool DisableUnityWebCache { get; set; } + public bool DisableUnityWebCache { get; } /// /// 下载重试判定策略 /// - public IDownloadRetryPolicy DownloadRetryPolicy { get; set; } + public IDownloadRetryPolicy DownloadRetryPolicy { get; } /// /// URL 选择策略 /// - public IDownloadUrlPolicy DownloadUrlPolicy { get; set; } + public IDownloadUrlPolicy DownloadUrlPolicy { get; } + + public LoadWebAssetBundleOptions(string cacheName, PackageBundle bundle, IReadOnlyList candidateUrls, IBundleDecryptor assetBundleDecryptor, IDownloadBackend downloadBackend, EFileVerifyLevel downloadVerifyLevel, int watchdogTimeout, bool disableUnityWebCache, IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy) + { + CacheName = cacheName; + Bundle = bundle; + CandidateUrls = candidateUrls; + AssetBundleDecryptor = assetBundleDecryptor; + DownloadBackend = downloadBackend; + DownloadVerifyLevel = downloadVerifyLevel; + WatchdogTimeout = watchdogTimeout; + DisableUnityWebCache = disableUnityWebCache; + DownloadRetryPolicy = downloadRetryPolicy; + DownloadUrlPolicy = downloadUrlPolicy; + } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionAllPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionAllPolicy.cs index 262f18fd..1ddc9ecb 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionAllPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionAllPolicy.cs @@ -10,12 +10,12 @@ namespace YooAsset /// public EvictionResult SelectEvictionTargets(IReadOnlyCollection cacheEntries, BCClearCacheOptions options) { - var bundleGUIDs = new List(cacheEntries.Count); + var bundleGuids = new List(cacheEntries.Count); foreach (var entry in cacheEntries) { - bundleGUIDs.Add(entry.BundleGUID); + bundleGuids.Add(entry.BundleGuid); } - return EvictionResult.Success(bundleGUIDs); + return EvictionResult.CreateSuccess(bundleGuids); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs index f0ff6cf1..109b8036 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs @@ -14,9 +14,9 @@ namespace YooAsset public EvictionResult SelectEvictionTargets(IReadOnlyCollection cacheEntries, BCClearCacheOptions options) { if (options.Manifest == null) - return EvictionResult.Failure("Active package manifest not found."); + return EvictionResult.CreateFailure("Active package manifest not found."); if (options.ClearParameter == null) - return EvictionResult.Failure("Clear param is null."); + return EvictionResult.CreateFailure("Clear param is null."); string[] locations; if (options.ClearParameter is string str) @@ -26,19 +26,19 @@ namespace YooAsset else if (options.ClearParameter is string[] array) locations = array; else - return EvictionResult.Failure($"Invalid clear param: {options.ClearParameter.GetType().FullName}"); + return EvictionResult.CreateFailure($"Invalid clear param: {options.ClearParameter.GetType().FullName}"); - var bundleGUIDs = new List(locations.Length); + var bundleGuids = new List(locations.Length); foreach (var location in locations) { string assetPath = options.Manifest.TryMappingToAssetPath(location); if (options.Manifest.TryGetPackageAsset(assetPath, out PackageAsset packageAsset)) { PackageBundle bundle = options.Manifest.GetMainPackageBundle(packageAsset.BundleID); - bundleGUIDs.Add(bundle.BundleGuid); + bundleGuids.Add(bundle.BundleGuid); } } - return EvictionResult.Success(bundleGUIDs); + return EvictionResult.CreateSuccess(bundleGuids); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs index fded42e4..6a2b6ead 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs @@ -14,9 +14,9 @@ namespace YooAsset public EvictionResult SelectEvictionTargets(IReadOnlyCollection cacheEntries, BCClearCacheOptions options) { if (options.Manifest == null) - return EvictionResult.Failure("Active package manifest not found."); + return EvictionResult.CreateFailure("Active package manifest not found."); if (options.ClearParameter == null) - return EvictionResult.Failure("Clear param is null."); + return EvictionResult.CreateFailure("Clear param is null."); string[] tags; if (options.ClearParameter is string str) @@ -26,18 +26,18 @@ namespace YooAsset else if (options.ClearParameter is string[] array) tags = array; else - return EvictionResult.Failure($"Invalid clear param: {options.ClearParameter.GetType().FullName}"); + return EvictionResult.CreateFailure($"Invalid clear param: {options.ClearParameter.GetType().FullName}"); - var bundleGUIDs = new List(cacheEntries.Count); + var bundleGuids = new List(cacheEntries.Count); foreach (var entry in cacheEntries) { - if (options.Manifest.TryGetPackageBundleByBundleGUID(entry.BundleGUID, out PackageBundle bundle)) + if (options.Manifest.TryGetPackageBundleByBundleGuid(entry.BundleGuid, out PackageBundle bundle)) { if (bundle.HasAnyTag(tags)) - bundleGUIDs.Add(bundle.BundleGuid); + bundleGuids.Add(bundle.BundleGuid); } } - return EvictionResult.Success(bundleGUIDs); + return EvictionResult.CreateSuccess(bundleGuids); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionUnusedPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionUnusedPolicy.cs index b37ead47..a09ab958 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionUnusedPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionUnusedPolicy.cs @@ -11,17 +11,17 @@ namespace YooAsset public EvictionResult SelectEvictionTargets(IReadOnlyCollection cacheEntries, BCClearCacheOptions options) { if (options.Manifest == null) - return EvictionResult.Failure("Active package manifest not found."); + return EvictionResult.CreateFailure("Active package manifest not found."); - var bundleGUIDs = new List(cacheEntries.Count); + var bundleGuids = new List(cacheEntries.Count); foreach (var entry in cacheEntries) { - if (options.Manifest.ContainsBundle(entry.BundleGUID) == false) + if (options.Manifest.ContainsBundle(entry.BundleGuid) == false) { - bundleGUIDs.Add(entry.BundleGUID); + bundleGuids.Add(entry.BundleGuid); } } - return EvictionResult.Success(bundleGUIDs); + return EvictionResult.CreateSuccess(bundleGuids); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCache.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCache.cs index eceba1f7..5595645d 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCache.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCache.cs @@ -4,29 +4,36 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 内置文件缓存系统,用于管理 StreamingAssets 中的资源包 + /// 内置文件缓存系统,用于管理 StreamingAssets 中的资源包。 /// internal class BuiltinBundleCache : IBundleCache { /// /// 内置文件缓存配置 /// - internal struct Configuration + internal readonly struct Configuration { /// /// AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; } /// /// RawBundle 解密器 /// - public IBundleDecryptor RawBundleDecryptor { get; set; } + public IBundleDecryptor RawBundleDecryptor { get; } /// /// 下载后台 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } + + public Configuration(IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor, IDownloadBackend downloadBackend) + { + AssetBundleDecryptor = assetBundleDecryptor; + RawBundleDecryptor = rawBundleDecryptor; + DownloadBackend = downloadBackend; + } } private readonly Dictionary _cacheEntries = new Dictionary(10000); @@ -48,7 +55,7 @@ namespace YooAsset public string RootPath { get; } /// - /// 只读属性 + /// 是否为只读缓存 /// public bool IsReadOnly { get; } @@ -88,62 +95,64 @@ namespace YooAsset { } /// - public virtual BCInitializeOperation InitializeAsync() + public BCInitializeOperation InitializeAsync() { var operation = new BBCInitializeOperation(this); return operation; } /// - public virtual BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) + public BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) { var operation = new BCWriteCacheCompleteOperation($"{nameof(BuiltinBundleCache)} is readonly."); return operation; } /// - public virtual BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) + public BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) { var operation = new BCClearCacheCompleteOperation(); return operation; } /// - public virtual BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) + public BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) { var operation = new BCVerifyCacheCompleteOperation(); return operation; } /// - public virtual BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) + public BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) { - if (options.Bundle.BundleType == (int)EBundleType.AssetBundle) + if (options.Bundle.GetBundleType() == (int)EBundleType.AssetBundle) { var operation = new BBCLoadAssetBundleOperation(this, options.Bundle); return operation; } - else if (options.Bundle.BundleType == (int)EBundleType.RawBundle) + else if (options.Bundle.GetBundleType() == (int)EBundleType.RawBundle) { var operation = new BBCLoadRawBundleOperation(this, options.Bundle); return operation; } else { - string error = $"{nameof(BuiltinBundleCache)} does not support bundle type: {options.Bundle.BundleType}."; + string error = $"{nameof(BuiltinBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}."; var operation = new BCLoadBundleErrorOperation(error); return operation; } } /// - public virtual bool IsCached(string bundleGUID) + public bool IsCached(string bundleGuid) { - return _cacheEntries.ContainsKey(bundleGUID); + return _cacheEntries.ContainsKey(bundleGuid); } #region 内部方法 /// /// 获取指定缓存条目 /// - internal BuiltinBundleCacheEntry GetEntry(string bundleGUID) + /// 资源包 GUID + /// 对应的内置缓存条目 + internal BuiltinBundleCacheEntry GetEntry(string bundleGuid) { - if (_cacheEntries.TryGetValue(bundleGUID, out BuiltinBundleCacheEntry entry)) + if (_cacheEntries.TryGetValue(bundleGuid, out BuiltinBundleCacheEntry entry)) return entry; else return null; @@ -152,21 +161,24 @@ namespace YooAsset /// /// 添加指定缓存条目 /// - internal void AddEntry(string bundleGUID, BuiltinBundleCacheEntry cacheEntry) + /// 资源包 GUID + /// 内置缓存条目 + internal void AddEntry(string bundleGuid, BuiltinBundleCacheEntry cacheEntry) { - if (_cacheEntries.ContainsKey(bundleGUID)) - throw new YooInternalException($"Cache entry already exists: '{bundleGUID}'."); + if (_cacheEntries.ContainsKey(bundleGuid)) + throw new YooInternalException($"Cache entry already exists: '{bundleGuid}'."); - _cacheEntries.Add(bundleGUID, cacheEntry); + _cacheEntries.Add(bundleGuid, cacheEntry); } /// /// 获取Catalog文件加载路径 /// + /// 完整加载路径 internal string GetCatalogBinaryFileLoadPath() { return PathUtility.Combine(RootPath, BuiltinCatalogConsts.BinaryFileName); } #endregion } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCacheEntry.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCacheEntry.cs index c3783037..1e86d6a8 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCacheEntry.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinBundleCacheEntry.cs @@ -9,7 +9,7 @@ namespace YooAsset /// /// 资源包唯一标识 /// - public string BundleGUID { get; private set; } + public string BundleGuid { get; private set; } /// /// 资源包文件路径 @@ -17,13 +17,13 @@ namespace YooAsset public string FilePath { get; private set; } /// - /// 创建内置文件缓存条目 + /// 创建内置文件缓存条目实例 /// - /// 资源包唯一标识 + /// 资源包唯一标识 /// 资源包文件路径 - public BuiltinBundleCacheEntry(string bundleGUID, string filePath) + public BuiltinBundleCacheEntry(string bundleGuid, string filePath) { - BundleGUID = bundleGUID; + BundleGuid = bundleGuid; FilePath = filePath; } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalog.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalog.cs index 146b4743..463a3324 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalog.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalog.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Collections.Generic; namespace YooAsset @@ -19,7 +18,7 @@ namespace YooAsset /// /// 资源包唯一标识 /// - public string BundleGUID; + public string BundleGuid; /// /// 资源包文件名 diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogConsts.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogConsts.cs index 1e1b4e67..217c8763 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogConsts.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogConsts.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置资源目录常量定义 /// - internal class BuiltinCatalogConsts + internal static class BuiltinCatalogConsts { /// /// 文件极限大小(100MB) diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogHelper.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogHelper.cs index 273e3188..299924eb 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogHelper.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/BuiltinCatalogHelper.cs @@ -13,8 +13,12 @@ namespace YooAsset #if UNITY_EDITOR /// /// 生成包裹的内置资源目录文件 - /// 说明:根据指定目录下的文件生成清单文件。 + /// 说明:根据指定目录下的文件生成清单文件 /// + /// 资源清单解密器 + /// 包裹名称 + /// 包裹在目录路径 + /// 是否创建文件成功 public static bool CreateFile(IManifestDecryptor decryptor, string packageName, string packageDirectory) { // 获取资源清单版本 @@ -51,7 +55,7 @@ namespace YooAsset { foreach (var packageBundle in packageManifest.BundleList) { - fileMapping.Add(packageBundle.FileName, packageBundle.BundleGuid); + fileMapping.Add(packageBundle.GetFileName(), packageBundle.BundleGuid); } } @@ -92,10 +96,10 @@ namespace YooAsset continue; string fileName = fileInfo.Name; - if (fileMapping.TryGetValue(fileName, out string bundleGUID)) + if (fileMapping.TryGetValue(fileName, out string bundleGuid)) { var fileEntry = new BuiltinCatalog.CatalogEntry(); - fileEntry.BundleGUID = bundleGUID; + fileEntry.BundleGuid = bundleGuid; fileEntry.FileName = fileName; buildinCatalog.Entries.Add(fileEntry); } @@ -125,6 +129,10 @@ namespace YooAsset /// /// 生成空的包裹内置资源目录文件 /// + /// 包裹名称 + /// 包裹版本 + /// 输出目录路径 + /// 是否创建文件成功 public static bool CreateEmptyFile(string packageName, string packageVersion, string outputPath) { // 创建内置清单实例 @@ -153,6 +161,8 @@ namespace YooAsset /// /// 序列化为 JSON 文件 /// + /// 文件的保存路径 + /// 要序列化的内置目录 public static void SerializeToJson(string savePath, BuiltinCatalog catalog) { string json = JsonUtility.ToJson(catalog, true); @@ -162,6 +172,8 @@ namespace YooAsset /// /// 序列化为二进制文件 /// + /// 文件的保存路径 + /// 要序列化的内置目录 public static void SerializeToBinary(string savePath, BuiltinCatalog catalog) { using (FileStream fs = new FileStream(savePath, FileMode.Create)) @@ -184,7 +196,7 @@ namespace YooAsset for (int i = 0; i < catalog.Entries.Count; i++) { var fileWrapper = catalog.Entries[i]; - buffer.WriteString(fileWrapper.BundleGUID); + buffer.WriteString(fileWrapper.BundleGuid); buffer.WriteString(fileWrapper.FileName); } @@ -198,6 +210,8 @@ namespace YooAsset /// /// 从 JSON 反序列化 /// + /// 文本内容 + /// 反序列化得到的内置目录对象 public static BuiltinCatalog DeserializeFromJson(string jsonContent) { return JsonUtility.FromJson(jsonContent); @@ -206,6 +220,8 @@ namespace YooAsset /// /// 从二进制数据反序列化 /// + /// 二进制数据 + /// 反序列化得到的内置目录对象 public static BuiltinCatalog DeserializeFromBinary(byte[] binaryData) { if (binaryData == null || binaryData.Length == 0) @@ -217,12 +233,12 @@ namespace YooAsset // 读取文件标记 uint fileMagic = buffer.ReadUInt32(); if (fileMagic != BuiltinCatalogConsts.FileMagic) - throw new Exception("Invalid catalog file."); + throw new Exception("Catalog file is invalid."); // 读取文件版本 int fileVersion = buffer.ReadInt32(); if (fileVersion != BuiltinCatalogConsts.FileVersion) - throw new Exception($"The catalog file version is not compatible: {fileVersion} != {BuiltinCatalogConsts.FileVersion}."); + throw new Exception($"Catalog file version is not compatible: {fileVersion} != {BuiltinCatalogConsts.FileVersion}."); BuiltinCatalog catalog = new BuiltinCatalog(); { @@ -237,7 +253,7 @@ namespace YooAsset for (int i = 0; i < fileCount; i++) { var fileEntry = new BuiltinCatalog.CatalogEntry(); - fileEntry.BundleGUID = buffer.ReadString(); + fileEntry.BundleGuid = buffer.ReadString(); fileEntry.FileName = buffer.ReadString(); catalog.Entries.Add(fileEntry); } @@ -246,4 +262,4 @@ namespace YooAsset return catalog; } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCInitializeOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCInitializeOperation.cs index 95eb97a7..335ba0f5 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件缓存初始化操作 /// - internal class BBCInitializeOperation : BCInitializeOperation + internal sealed class BBCInitializeOperation : BCInitializeOperation { private enum ESteps { @@ -18,6 +18,10 @@ namespace YooAsset private LoadBuiltinCatalogOperation _loadBuiltinCatalogOp; private ESteps _steps = ESteps.None; + /// + /// 创建内置缓存初始化操作实例 + /// + /// 内置文件缓存系统 public BBCInitializeOperation(BuiltinBundleCache fileCache) { _fileCache = fileCache; @@ -35,10 +39,10 @@ namespace YooAsset { if (_loadBuiltinCatalogOp == null) { - var options = new LoadBuiltinCatalogOptions(); - options.PackageName = _fileCache.PackageName; - options.FilePath = _fileCache.GetCatalogBinaryFileLoadPath(); - options.DownloadBackend = _fileCache.Config.DownloadBackend; + var options = new LoadBuiltinCatalogOptions( + packageName: _fileCache.PackageName, + filePath: _fileCache.GetCatalogBinaryFileLoadPath(), + downloadBackend: _fileCache.Config.DownloadBackend); _loadBuiltinCatalogOp = new LoadBuiltinCatalogOperation(options); _loadBuiltinCatalogOp.StartOperation(); AddChildOperation(_loadBuiltinCatalogOp); @@ -65,8 +69,8 @@ namespace YooAsset foreach (var fileEntry in catalog.Entries) { string filePath = PathUtility.Combine(_fileCache.RootPath, fileEntry.FileName); - var cacheEntry = new BuiltinBundleCacheEntry(fileEntry.BundleGUID, filePath); - _fileCache.AddEntry(fileEntry.BundleGUID, cacheEntry); + var cacheEntry = new BuiltinBundleCacheEntry(fileEntry.BundleGuid, filePath); + _fileCache.AddEntry(fileEntry.BundleGuid, cacheEntry); } _steps = ESteps.Done; diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCLoadBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCLoadBundleOperation.cs index 9bdf373e..95be3718 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/BuiltinBundleCache/Operations/BBCLoadBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件缓存加载 AssetBundle 操作 /// - internal class BBCLoadAssetBundleOperation : BCLoadBundleOperation + internal sealed class BBCLoadAssetBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -20,6 +20,11 @@ namespace YooAsset private BuiltinBundleCacheEntry _cacheEntry; private ESteps _steps = ESteps.None; + /// + /// 创建内置 AssetBundle 加载操作实例 + /// + /// 内置文件缓存系统 + /// 资源包描述 public BBCLoadAssetBundleOperation(BuiltinBundleCache fileCache, PackageBundle bundle) { _fileCache = fileCache; @@ -52,11 +57,11 @@ namespace YooAsset { if (_loadLocalAssetBundleOp == null) { - var options = new LoadLocalAssetBundleOptions(); - options.CacheName = _fileCache.GetType().Name; - options.Bundle = _bundle; - options.FilePath = _cacheEntry.FilePath; - options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor; + var options = new LoadLocalAssetBundleOptions( + cacheName: _fileCache.GetType().Name, + bundle: _bundle, + filePath: _cacheEntry.FilePath, + assetBundleDecryptor: _fileCache.Config.AssetBundleDecryptor); _loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options); _loadLocalAssetBundleOp.StartOperation(); AddChildOperation(_loadLocalAssetBundleOp); @@ -94,7 +99,7 @@ namespace YooAsset /// /// 内置文件缓存加载 RawBundle 操作 /// - internal class BBCLoadRawBundleOperation : BCLoadBundleOperation + internal sealed class BBCLoadRawBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -142,11 +147,11 @@ namespace YooAsset { if(_loadLocalRawBundleOp == null) { - var options = new LoadLocalRawBundleOptions(); - options.CacheName = _fileCache.GetType().Name; - options.Bundle = _bundle; - options.FilePath = _cacheEntry.FilePath; - options.RawBundleDecryptor = _fileCache.Config.RawBundleDecryptor; + var options = new LoadLocalRawBundleOptions( + cacheName: _fileCache.GetType().Name, + bundle: _bundle, + filePath: _cacheEntry.FilePath, + rawBundleDecryptor: _fileCache.Config.RawBundleDecryptor); _loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options); _loadLocalRawBundleOp.StartOperation(); AddChildOperation(_loadLocalRawBundleOp); diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCache.cs b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCache.cs index b036bc60..d6c08ecd 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCache.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCache.cs @@ -4,34 +4,42 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 编辑器文件缓存系统,用于编辑器模式下的资源模拟加载 + /// 编辑器文件缓存系统,用于编辑器模式下的资源模拟加载。 /// internal class EditorBundleCache : IBundleCache { /// /// 编辑器文件缓存配置 /// - internal struct Configuration + internal readonly struct Configuration { /// - /// 虚拟下载模式,模拟资源下载流程 + /// 虚拟下载模式,模拟资源下载流程。 /// - public bool VirtualDownloadMode { get; set; } + public bool VirtualDownloadMode { get; } /// /// 虚拟WebGL模式 /// - public bool VirtualWebGLMode { get; set; } + public bool VirtualWebGLMode { get; } /// /// 异步模拟最小帧数 /// - public int AsyncSimulateMinFrame { get; set; } + public int AsyncSimulateMinFrame { get; } /// /// 异步模拟最大帧数 /// - public int AsyncSimulateMaxFrame { get; set; } + public int AsyncSimulateMaxFrame { get; } + + public Configuration(bool virtualDownloadMode, bool virtualWebGLMode, int asyncSimulateMinFrame, int asyncSimulateMaxFrame) + { + VirtualDownloadMode = virtualDownloadMode; + VirtualWebGLMode = virtualWebGLMode; + AsyncSimulateMinFrame = asyncSimulateMinFrame; + AsyncSimulateMaxFrame = asyncSimulateMaxFrame; + } } private readonly Dictionary _cacheEntries = new Dictionary(10000); @@ -53,7 +61,7 @@ namespace YooAsset public string RootPath { get; } /// - /// 只读属性 + /// 是否为只读缓存 /// public bool IsReadOnly { get; } @@ -71,7 +79,7 @@ namespace YooAsset /// /// 已占用空间 /// - /// 按缓存索引累计 + /// 编辑器缓存为虚拟缓存,不占用磁盘空间。 public long SpaceOccupied { get; private set; } #endregion @@ -93,19 +101,19 @@ namespace YooAsset { } /// - public virtual BCInitializeOperation InitializeAsync() + public BCInitializeOperation InitializeAsync() { var operation = new EBCInitializeOperation(this); return operation; } /// - public virtual BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) + public BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) { var operation = new EBCWriteCacheOperation(this, options); return operation; } /// - public virtual BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) + public BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) { ICacheEvictionPolicy policy = CreateEvictionPolicy(options); if (policy == null) @@ -117,7 +125,9 @@ namespace YooAsset /// /// 根据 ClearMethod 创建对应的淘汰策略实例 /// - protected virtual ICacheEvictionPolicy CreateEvictionPolicy(BCClearCacheOptions options) + /// 清理缓存选项 + /// 淘汰策略实例 + protected ICacheEvictionPolicy CreateEvictionPolicy(BCClearCacheOptions options) { if (options.ClearMethod == ClearCacheMethods.ClearAllBundleFiles) return new EvictionAllPolicy(); @@ -134,31 +144,31 @@ namespace YooAsset return null; } /// - public virtual BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) + public BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) { var operation = new BCVerifyCacheCompleteOperation(); return operation; } /// - public virtual BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) + public BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) { - if (options.Bundle.BundleType == (int)EBundleType.VirtualBundle) + if (options.Bundle.GetBundleType() == (int)EBundleType.VirtualBundle) { var operation = new EBCLoadBundleOperation(this, options.Bundle); return operation; } else { - string error = $"{nameof(EditorBundleCache)} does not support bundle type: {options.Bundle.BundleType}."; + string error = $"{nameof(EditorBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}."; var operation = new BCLoadBundleErrorOperation(error); return operation; } } /// - public virtual bool IsCached(string bundleGUID) + public bool IsCached(string bundleGuid) { if (Config.VirtualDownloadMode) - return _cacheEntries.ContainsKey(bundleGUID); + return _cacheEntries.ContainsKey(bundleGuid); else return true; } @@ -167,6 +177,7 @@ namespace YooAsset /// /// 获取所有缓存条目 /// + /// 当前字典中全部缓存条目的只读集合 internal IReadOnlyCollection GetAllEntries() { return _cacheEntries.Values; @@ -175,24 +186,27 @@ namespace YooAsset /// /// 添加指定缓存条目 /// - internal void AddEntry(string bundleGUID, EditorBundleCacheEntry cacheEntry) + /// 资源包 GUID + /// 编辑器缓存条目 + internal void AddEntry(string bundleGuid, EditorBundleCacheEntry cacheEntry) { - if (_cacheEntries.ContainsKey(bundleGUID)) - throw new YooInternalException($"Cache entry already exists: '{bundleGUID}'."); + if (_cacheEntries.ContainsKey(bundleGuid)) + throw new YooInternalException($"Cache entry already exists: '{bundleGuid}'."); - _cacheEntries.Add(bundleGUID, cacheEntry); + _cacheEntries.Add(bundleGuid, cacheEntry); } /// /// 删除指定缓存条目 /// - internal void RemoveEntry(string bundleGUID) + /// 资源包 GUID + internal void RemoveEntry(string bundleGuid) { - if (_cacheEntries.TryGetValue(bundleGUID, out EditorBundleCacheEntry entry)) + if (_cacheEntries.TryGetValue(bundleGuid, out EditorBundleCacheEntry entry)) { - _cacheEntries.Remove(bundleGUID); + _cacheEntries.Remove(bundleGuid); } } #endregion } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCacheEntry.cs b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCacheEntry.cs index 70a99fbd..e5586b33 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCacheEntry.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/EditorBundleCacheEntry.cs @@ -9,7 +9,7 @@ namespace YooAsset /// /// 资源包唯一标识 /// - public string BundleGUID { get; private set; } + public string BundleGuid { get; private set; } /// /// 资源包文件路径 @@ -17,13 +17,13 @@ namespace YooAsset public string FilePath { get; private set; } /// - /// 创建编辑器文件缓存条目 + /// 创建编辑器文件缓存条目实例 /// - /// 资源包唯一标识 + /// 资源包唯一标识 /// 资源包文件路径 - public EditorBundleCacheEntry(string bundleGUID, string filePath) + public EditorBundleCacheEntry(string bundleGuid, string filePath) { - BundleGUID = bundleGUID; + BundleGuid = bundleGuid; FilePath = filePath; } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCClearCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCClearCacheOperation.cs index 86a4e05a..2d2c20dc 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCClearCacheOperation.cs @@ -18,9 +18,15 @@ namespace YooAsset private readonly EditorBundleCache _fileCache; private readonly BCClearCacheOptions _options; private readonly ICacheEvictionPolicy _policy; - private List _bundleGUIDs; + private IReadOnlyList _bundleGuids; private ESteps _steps = ESteps.None; + /// + /// 创建编辑器清理缓存操作实例 + /// + /// 编辑器文件缓存系统 + /// 清理缓存选项 + /// 缓存逐出策略 internal EBCClearCacheOperation(EditorBundleCache fileCache, BCClearCacheOptions options, ICacheEvictionPolicy policy) { _fileCache = fileCache; @@ -48,15 +54,15 @@ namespace YooAsset return; } - _bundleGUIDs = clearResult.BundleGUIDs; + _bundleGuids = clearResult.BundleGuids; _steps = ESteps.ClearCacheFiles; } if (_steps == ESteps.ClearCacheFiles) { - foreach (var bundleGUID in _bundleGUIDs) + foreach (var bundleGuid in _bundleGuids) { - _fileCache.RemoveEntry(bundleGUID); + _fileCache.RemoveEntry(bundleGuid); } _steps = ESteps.Done; diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCInitializeOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCInitializeOperation.cs index bcb066d4..4e9cfe35 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件缓存初始化操作 /// - internal class EBCInitializeOperation : BCInitializeOperation + internal sealed class EBCInitializeOperation : BCInitializeOperation { private readonly EditorBundleCache _fileCache; diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCLoadBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCLoadBundleOperation.cs index e91f8d2a..a4a2d24c 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCLoadBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件缓存加载资源包操作 /// - internal class EBCLoadBundleOperation : BCLoadBundleOperation + internal sealed class EBCLoadBundleOperation : BCLoadBundleOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCWriteCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCWriteCacheOperation.cs index 15874e67..1a6e11a4 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCWriteCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/EditorBundleCache/Operations/EBCWriteCacheOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件缓存写入操作 /// - internal class EBCWriteCacheOperation : BCWriteCacheOperation + internal sealed class EBCWriteCacheOperation : BCWriteCacheOperation { private enum ESteps { @@ -18,9 +18,14 @@ namespace YooAsset private readonly BCWriteCacheOptions _options; private ESteps _steps = ESteps.None; - public EBCWriteCacheOperation(EditorBundleCache cache, BCWriteCacheOptions options) + /// + /// 创建编辑器写入缓存操作实例 + /// + /// 编辑器文件缓存系统 + /// 写入缓存选项 + public EBCWriteCacheOperation(EditorBundleCache fileCache, BCWriteCacheOptions options) { - _fileCache = cache; + _fileCache = fileCache; _options = options; } protected override void InternalStart() @@ -37,7 +42,7 @@ namespace YooAsset if (_fileCache.IsCached(_options.Bundle.BundleGuid)) { _steps = ESteps.Done; - SetError("The bundle is already cached."); + SetError("Bundle is already cached."); } else { diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/FileVerifyHelper.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/FileVerifyHelper.cs index 482ba772..722a5088 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/FileVerifyHelper.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/FileVerifyHelper.cs @@ -13,9 +13,9 @@ namespace YooAsset /// /// 文件路径 /// 期望的文件大小 - /// 期望的文件CRC值 + /// 期望的文件CRC值 /// 校验结果 - public static EFileVerifyResult VerifyFile(string filePath, long fileSize, uint fileCRC) + public static EFileVerifyResult VerifyFile(string filePath, long fileSize, uint fileCrc) { try { @@ -23,6 +23,7 @@ namespace YooAsset return EFileVerifyResult.DataFileNotExisted; // 可选条件:验证文件大小 + // fileSize == 0 表示调用方不要求大小校验(哨兵值) if (fileSize > 0) { long size = FileUtility.GetFileSize(filePath); @@ -33,10 +34,11 @@ namespace YooAsset } // 可选条件:验证文件CRC - if (fileCRC > 0) + // fileCRC == 0 表示调用方不要求 CRC 校验(哨兵值) + if (fileCrc > 0) { uint crc = HashUtility.ComputeFileCrc32AsUInt(filePath); - if (crc == fileCRC) + if (crc == fileCrc) return EFileVerifyResult.Succeed; else return EFileVerifyResult.DataFileCrcError; @@ -48,7 +50,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"File verification exception: {ex.Message}."); + YooLogger.LogError($"File verification exception: {ex.Message}."); return EFileVerifyResult.Exception; } } @@ -58,9 +60,9 @@ namespace YooAsset /// /// 文件数据 /// 期望的文件大小 - /// 期望的文件CRC值 + /// 期望的文件CRC值 /// 校验结果 - public static EFileVerifyResult VerifyFile(byte[] fileData, long fileSize, uint fileCRC) + public static EFileVerifyResult VerifyFile(byte[] fileData, long fileSize, uint fileCrc) { try { @@ -68,6 +70,7 @@ namespace YooAsset return EFileVerifyResult.DataFileInvalid; // 可选条件:验证文件大小 + // fileSize == 0 表示调用方不要求大小校验(哨兵值) if (fileSize > 0) { long size = fileData.Length; @@ -78,10 +81,11 @@ namespace YooAsset } // 可选条件:验证文件CRC - if (fileCRC > 0) + // fileCRC == 0 表示调用方不要求 CRC 校验(哨兵值) + if (fileCrc > 0) { uint crc = HashUtility.ComputeCrc32AsUInt(fileData); - if (crc == fileCRC) + if (crc == fileCrc) return EFileVerifyResult.Succeed; else return EFileVerifyResult.DataFileCrcError; @@ -93,7 +97,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"File verification exception: {ex.Message}."); + YooLogger.LogError($"File verification exception: {ex.Message}."); return EFileVerifyResult.Exception; } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/ClearCacheFilesOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/ClearCacheFilesOperation.cs index 8130ea98..36a48d3a 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/ClearCacheFilesOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/ClearCacheFilesOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 清理缓存文件操作 /// - internal class ClearCacheFilesOperation : AsyncOperationBase + internal sealed class ClearCacheFilesOperation : AsyncOperationBase { private enum ESteps { @@ -16,14 +16,19 @@ namespace YooAsset } private readonly SandboxBundleCache _fileCache; - private readonly List _bundleGUIDs; + private readonly List _bundleGuids; private int _fileTotalCount; private ESteps _steps = ESteps.None; - public ClearCacheFilesOperation(SandboxBundleCache fileCache, List bundleGUIDs) + /// + /// 创建清理缓存文件操作实例 + /// + /// 沙盒文件缓存系统 + /// 要清理的资源包 GUID 列表 + public ClearCacheFilesOperation(SandboxBundleCache fileCache, List bundleGuids) { _fileCache = fileCache; - _bundleGUIDs = bundleGUIDs; + _bundleGuids = bundleGuids; } protected override void InternalStart() { @@ -36,24 +41,24 @@ namespace YooAsset if (_steps == ESteps.CheckParam) { - if (_bundleGUIDs == null || _bundleGUIDs.Count == 0) + if (_bundleGuids == null || _bundleGuids.Count == 0) { _steps = ESteps.Done; SetResult(); return; } - _fileTotalCount = _bundleGUIDs.Count; + _fileTotalCount = _bundleGuids.Count; _steps = ESteps.ClearCache; } if (_steps == ESteps.ClearCache) { - for (int i = _bundleGUIDs.Count - 1; i >= 0; i--) + for (int i = _bundleGuids.Count - 1; i >= 0; i--) { - string bundleGUID = _bundleGUIDs[i]; - _fileCache.RemoveEntry(bundleGUID); - _bundleGUIDs.RemoveAt(i); + string bundleGuid = _bundleGuids[i]; + _fileCache.RemoveEntry(bundleGuid); + _bundleGuids.RemoveAt(i); if (IsBusy) break; } @@ -61,9 +66,9 @@ namespace YooAsset if (_fileTotalCount == 0) Progress = 1.0f; else - Progress = 1.0f - ((float)_bundleGUIDs.Count / _fileTotalCount); + Progress = 1.0f - ((float)_bundleGuids.Count / _fileTotalCount); - if (_bundleGUIDs.Count == 0) + if (_bundleGuids.Count == 0) { _steps = ESteps.Done; SetResult(); diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/SearchCacheFilesOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/SearchCacheFilesOperation.cs index f511b77b..54613a6c 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/SearchCacheFilesOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/SearchCacheFilesOperation.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 搜索缓存文件操作,扫描缓存目录中的文件 + /// 搜索缓存文件操作,扫描缓存目录中的文件。 /// internal sealed class SearchCacheFilesOperation : AsyncOperationBase { @@ -28,7 +28,10 @@ namespace YooAsset /// public readonly List Result = new List(5000); - + /// + /// 创建搜索缓存文件操作实例 + /// + /// 沙盒文件缓存系统 internal SearchCacheFilesOperation(SandboxBundleCache fileCache) { _fileCache = fileCache; @@ -69,7 +72,15 @@ namespace YooAsset _steps = ESteps.Done; SetResult(); double costTime = TimeUtility.RealtimeSinceStartup - _verifyStartTime; - YooLogger.Log($"Search cache files elapsed time {costTime:f1} seconds"); + YooLogger.Log($"Cache file search completed in {costTime:f1} seconds."); + } + } + protected override void InternalDispose() + { + if (_filesEnumerator != null) + { + _filesEnumerator.Dispose(); + _filesEnumerator = null; } } @@ -86,15 +97,15 @@ namespace YooAsset var childDirectories = Directory.EnumerateDirectories(rootFolder); foreach (var childDirectory in childDirectories) { - string bundleGUID = Path.GetFileName(childDirectory); - if (_fileCache.IsCached(bundleGUID)) + string bundleGuid = Path.GetFileName(childDirectory); + if (_fileCache.IsCached(bundleGuid)) continue; // 创建验证元素类 string fileRootPath = childDirectory; string dataFilePath = PathUtility.Combine(fileRootPath, SandboxBundleCacheConsts.BundleDataFileName); string infoFilePath = PathUtility.Combine(fileRootPath, SandboxBundleCacheConsts.BundleInfoFileName); - var element = new SearchFileInfo(bundleGUID, fileRootPath, dataFilePath, infoFilePath); + var element = new SearchFileInfo(bundleGuid, fileRootPath, dataFilePath, infoFilePath); Result.Add(element); } @@ -105,4 +116,4 @@ namespace YooAsset return isFindItem; } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyCacheFilesOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyCacheFilesOperation.cs index 8f31bdf5..b443c1c1 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyCacheFilesOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyCacheFilesOperation.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Threading; @@ -7,7 +6,7 @@ using System.Threading; namespace YooAsset { /// - /// 缓存文件验证(线程版),验证缓存目录中的文件 + /// 缓存文件验证(线程版),验证缓存目录中的文件。 /// internal sealed class VerifyCacheFilesOperation : AsyncOperationBase { @@ -31,7 +30,13 @@ namespace YooAsset private int _failedCount; private ESteps _steps = ESteps.None; - + /// + /// 创建缓存文件验证操作实例 + /// + /// 沙盒文件缓存系统 + /// 文件校验等级 + /// 文件校验最大并发数 + /// 待验证的搜索文件信息列表 internal VerifyCacheFilesOperation(SandboxBundleCache fileCache, EFileVerifyLevel verifyLevel, int fileVerifyMaxConcurrency, List elements) { _fileCache = fileCache; @@ -56,7 +61,7 @@ namespace YooAsset if (_maxConcurrentVerifyCount < 1) _maxConcurrentVerifyCount = 1; - YooLogger.Log($"Verify max concurrency: {_maxConcurrentVerifyCount}"); + YooLogger.Log($"Maximum verify concurrency is {_maxConcurrentVerifyCount}."); _activeVerifyList = new List(_maxConcurrentVerifyCount); _verifyStartTime = TimeUtility.RealtimeSinceStartup; _verifyTotalCount = _pendingVerifyList.Count; @@ -76,13 +81,13 @@ namespace YooAsset if (resultCode == (int)EFileVerifyResult.Succeed) { _successCount++; - var cacheEntry = new SandboxBundleCacheEntry(verifyElement.BundleGUID, verifyElement.InfoFilePath, verifyElement.DataFilePath); - _fileCache.AddEntry(verifyElement.BundleGUID, cacheEntry); + var cacheEntry = new SandboxBundleCacheEntry(verifyElement.BundleGuid, verifyElement.InfoFilePath, verifyElement.DataFilePath); + _fileCache.AddEntry(verifyElement.BundleGuid, cacheEntry); } else { _failedCount++; - YooLogger.Warning($"File verification failed (code: {verifyElement.VerifyResultCode}). Deleting files: '{verifyElement.FolderPath}'."); + YooLogger.LogWarning($"File verification failed (code: {resultCode}). Deleting files: '{verifyElement.FolderPath}'."); verifyElement.DeleteCacheFolder(); } } @@ -94,7 +99,7 @@ namespace YooAsset _steps = ESteps.Done; SetResult(); double costTime = TimeUtility.RealtimeSinceStartup - _verifyStartTime; - YooLogger.Log($"Verify cache files elapsed time {costTime:f1} seconds"); + YooLogger.Log($"Cache file verification completed in {costTime:f1} seconds."); } for (int i = _pendingVerifyList.Count - 1; i >= 0; i--) @@ -163,13 +168,13 @@ namespace YooAsset else if (verifyLevel == EFileVerifyLevel.High) return FileVerifyHelper.VerifyFile(element.DataFilePath, dataFileSize, dataFileCRC); else - throw new System.NotImplementedException(verifyLevel.ToString()); + throw new YooInternalException($"Unexpected verify level: {verifyLevel}."); } catch (Exception ex) { - YooLogger.Error($"File verification exception: {ex.Message}."); + YooLogger.LogError($"File verification exception: {ex.Message}."); return EFileVerifyResult.Exception; } } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyTempFileOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyTempFileOperation.cs index 08a5e8f9..9d82e0f3 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyTempFileOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/Internal/VerifyTempFileOperation.cs @@ -24,7 +24,10 @@ namespace YooAsset /// public EFileVerifyResult VerifyResult { private set; get; } - + /// + /// 创建下载文件验证(线程版)实例 + /// + /// 临时文件信息 internal VerifyTempFileOperation(TempFileInfo element) { _element = element; @@ -75,7 +78,7 @@ namespace YooAsset private void VerifyFileInThread(object obj) { TempFileInfo element = (TempFileInfo)obj; - int resultCode = (int)FileVerifyHelper.VerifyFile(element.FilePath, element.FileSize, element.FileCRC); + int resultCode = (int)FileVerifyHelper.VerifyFile(element.FilePath, element.FileSize, element.FileCrc); element.VerifyResultCode = resultCode; //注意: 一次命令赋值 } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCClearCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCClearCacheOperation.cs index d3b3c89d..42abdddd 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCClearCacheOperation.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; namespace YooAsset { @@ -20,6 +21,12 @@ namespace YooAsset private ClearCacheFilesOperation _clearCacheFilesOp; private ESteps _steps = ESteps.None; + /// + /// 创建沙盒清理缓存操作实例 + /// + /// 沙盒文件缓存系统 + /// 清理缓存选项 + /// 缓存淘汰策略 internal SBCClearCacheOperation(SandboxBundleCache fileCache, BCClearCacheOptions options, ICacheEvictionPolicy policy) { _fileCache = fileCache; @@ -48,7 +55,7 @@ namespace YooAsset return; } - _clearCacheFilesOp = new ClearCacheFilesOperation(_fileCache, clearResult.BundleGUIDs); + _clearCacheFilesOp = new ClearCacheFilesOperation(_fileCache, new List(clearResult.BundleGuids)); _clearCacheFilesOp.StartOperation(); AddChildOperation(_clearCacheFilesOp); _steps = ESteps.ClearCacheFiles; diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCInitializeOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCInitializeOperation.cs index e3c9adf9..d00e4377 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件缓存初始化操作 /// - internal class SBCInitializeOperation : BCInitializeOperation + internal sealed class SBCInitializeOperation : BCInitializeOperation { private enum ESteps { @@ -19,6 +19,10 @@ namespace YooAsset private VerifyCacheFilesOperation _verifyCacheFilesOp; private ESteps _steps = ESteps.None; + /// + /// 创建沙盒缓存初始化操作实例 + /// + /// 沙盒文件缓存系统 public SBCInitializeOperation(SandboxBundleCache fileCache) { _fileCache = fileCache; diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCLoadBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCLoadBundleOperation.cs index 0aaa9d8d..c160ccd2 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCLoadBundleOperation.cs @@ -7,7 +7,7 @@ namespace YooAsset /// /// 沙盒文件缓存加载 AssetBundle 操作 /// - internal class SBCLoadAssetBundleOperation : BCLoadBundleOperation + internal sealed class SBCLoadAssetBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -26,10 +26,15 @@ namespace YooAsset private SandboxBundleCacheEntry _cacheEntry; private ESteps _steps = ESteps.None; - public SBCLoadAssetBundleOperation(SandboxBundleCache fileCache, PackageBundle bundle) + /// + /// 创建沙盒 AssetBundle 加载操作实例 + /// + /// 沙盒文件缓存系统 + /// 资源包描述 + public SBCLoadAssetBundleOperation(SandboxBundleCache fileCache, PackageBundle packageBundle) { _fileCache = fileCache; - _bundle = bundle; + _bundle = packageBundle; } protected override void InternalStart() { @@ -58,11 +63,11 @@ namespace YooAsset { if (_loadLocalAssetBundleOp == null) { - var options = new LoadLocalAssetBundleOptions(); - options.CacheName = _fileCache.GetType().Name; - options.Bundle = _bundle; - options.FilePath = _cacheEntry.DataFilePath; - options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor; + var options = new LoadLocalAssetBundleOptions( + cacheName: _fileCache.GetType().Name, + bundle: _bundle, + filePath: _cacheEntry.DataFilePath, + assetBundleDecryptor: _fileCache.Config.AssetBundleDecryptor); _loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options); _loadLocalAssetBundleOp.StartOperation(); AddChildOperation(_loadLocalAssetBundleOp); @@ -105,9 +110,7 @@ namespace YooAsset // 说明:在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性! if (_verifyCacheOp == null) { - var options = new BCVerifyCacheOptions(); - options.Bundle = _bundle; - options.DeleteCacheEntryOnFailure = true; + var options = new BCVerifyCacheOptions(_bundle, true); _verifyCacheOp = _fileCache.VerifyCacheAsync(options); _verifyCacheOp.StartOperation(); AddChildOperation(_verifyCacheOp); @@ -178,23 +181,39 @@ namespace YooAsset private AssetBundle FallbackLoadAssetBundle() { - byte[] fileData = FileUtility.ReadAllBytes(_cacheEntry.DataFilePath); - return AssetBundle.LoadFromMemory(fileData); + try + { + byte[] fileData = FileUtility.ReadAllBytes(_cacheEntry.DataFilePath); + return AssetBundle.LoadFromMemory(fileData); + } + catch (Exception ex) + { + YooLogger.LogWarning($"Fallback load failed: {ex.Message}."); + return null; + } } private AssetBundle FallbackLoadEncryptedAssetBundle(IBundleMemoryDecryptor decryptor) { - var args = new BundleDecryptArgs(); - args.Bundle = _bundle; - args.FilePath = _cacheEntry.DataFilePath; - var fileData = decryptor.GetDecryptedData(args); - return AssetBundle.LoadFromMemory(fileData); + try + { + var args = new BundleDecryptArgs(_bundle, null, _cacheEntry.DataFilePath); + var fileData = decryptor.GetDecryptedData(args); + if (fileData == null) + return null; + return AssetBundle.LoadFromMemory(fileData); + } + catch (Exception ex) + { + YooLogger.LogWarning($"Fallback encrypted load failed: {ex.Message}."); + return null; + } } } /// /// 沙盒文件缓存加载 RawBundle 操作 /// - internal class SBCLoadRawBundleOperation : BCLoadBundleOperation + internal sealed class SBCLoadRawBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -211,6 +230,11 @@ namespace YooAsset private ESteps _steps = ESteps.None; + /// + /// 创建沙盒 RawBundle 加载操作实例 + /// + /// 沙盒文件缓存系统 + /// 资源包描述 public SBCLoadRawBundleOperation(SandboxBundleCache fileCache, PackageBundle bundle) { _fileCache = fileCache; @@ -243,11 +267,11 @@ namespace YooAsset { if (_loadLocalRawBundleOp == null) { - var options = new LoadLocalRawBundleOptions(); - options.CacheName = _fileCache.GetType().Name; - options.Bundle = _bundle; - options.FilePath = _cacheEntry.DataFilePath; - options.RawBundleDecryptor = _fileCache.Config.RawBundleDecryptor; + var options = new LoadLocalRawBundleOptions( + cacheName: _fileCache.GetType().Name, + bundle: _bundle, + filePath: _cacheEntry.DataFilePath, + rawBundleDecryptor: _fileCache.Config.RawBundleDecryptor); _loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options); _loadLocalRawBundleOp.StartOperation(); AddChildOperation(_loadLocalRawBundleOp); @@ -283,7 +307,7 @@ namespace YooAsset } #if TUANJIE_1_7_OR_NEWER - internal class SBCLoadInstantBundleOperation : BCLoadBundleOperation + internal sealed class SBCLoadInstantBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -295,11 +319,11 @@ namespace YooAsset protected override void InternalStart() { - throw new NotImplementedException(); + throw new NotImplementedException($"{nameof(SBCLoadInstantBundleOperation)} is not implemented."); } protected override void InternalUpdate() { - throw new NotImplementedException(); + throw new NotImplementedException($"{nameof(SBCLoadInstantBundleOperation)} is not implemented."); } } #endif diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCVerifyCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCVerifyCacheOperation.cs index 11e5b4f3..532007bf 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCVerifyCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCVerifyCacheOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件缓存验证操作 /// - internal class SBCVerifyCacheOperation : BCVerifyCacheOperation + internal sealed class SBCVerifyCacheOperation : BCVerifyCacheOperation { private enum ESteps { @@ -19,9 +19,14 @@ namespace YooAsset private VerifyTempFileOperation _verifyTempFileOp; private ESteps _steps = ESteps.None; - public SBCVerifyCacheOperation(SandboxBundleCache cache, BCVerifyCacheOptions options) + /// + /// 创建沙盒验证缓存操作实例 + /// + /// 沙盒文件缓存系统 + /// 验证缓存选项 + public SBCVerifyCacheOperation(SandboxBundleCache fileCache, BCVerifyCacheOptions options) { - _fileCache = cache; + _fileCache = fileCache; _options = options; } protected override void InternalStart() @@ -38,7 +43,7 @@ namespace YooAsset if (_fileCache.IsCached(_options.Bundle.BundleGuid) == false) { _steps = ESteps.Done; - SetError("Cached bundle not found."); + SetError($"File cache entry not found: '{_options.Bundle.BundleGuid}'."); } else { @@ -51,6 +56,13 @@ namespace YooAsset if (_verifyTempFileOp == null) { var entry = _fileCache.GetEntry(_options.Bundle.BundleGuid); + if (entry == null) + { + _steps = ESteps.Done; + SetError($"File cache entry not found: '{_options.Bundle.BundleGuid}'."); + return; + } + var element = new TempFileInfo(entry.DataFilePath, _options.Bundle.FileCrc, _options.Bundle.FileSize); _verifyTempFileOp = new VerifyTempFileOperation(element); _verifyTempFileOp.StartOperation(); @@ -76,7 +88,7 @@ namespace YooAsset if (_options.DeleteCacheEntryOnFailure) { - YooLogger.Error($"Found corrupted bundle file. Removing cache entry: '{_options.Bundle.BundleGuid}'."); + YooLogger.LogError($"Found corrupted bundle file. Removing cache entry: '{_options.Bundle.BundleGuid}'."); _fileCache.RemoveEntry(_options.Bundle.BundleGuid); } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCWriteCacheOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCWriteCacheOperation.cs index e24d8d03..356f8edf 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCWriteCacheOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/Operations/SBCWriteCacheOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 沙盒文件缓存写入操作 /// - internal class SBCWriteCacheOperation : BCWriteCacheOperation + internal sealed class SBCWriteCacheOperation : BCWriteCacheOperation { private enum ESteps { @@ -22,6 +22,11 @@ namespace YooAsset private VerifyTempFileOperation _verifyTempFileOp; private ESteps _steps = ESteps.None; + /// + /// 创建沙盒写入缓存操作实例 + /// + /// 沙盒文件缓存系统 + /// 写入缓存选项 public SBCWriteCacheOperation(SandboxBundleCache fileCache, BCWriteCacheOptions options) { _fileCache = fileCache; @@ -41,7 +46,7 @@ namespace YooAsset if (_fileCache.IsCached(_options.Bundle.BundleGuid)) { _steps = ESteps.Done; - SetError("The bundle is already cached."); + SetError("Bundle is already cached."); } else { @@ -120,8 +125,8 @@ namespace YooAsset catch (Exception ex) { _steps = ESteps.Done; - SetError($"Failed to write cache file. Error: {ex.Message}."); - YooLogger.Error(Error); + SetError($"Failed to write cache file: {ex.Message}."); + YooLogger.LogError(Error); // 回滚:清理临时文件,正式文件不受影响 DeleteFileSafely(dataTempPath); @@ -150,7 +155,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Warning($"Failed to delete file '{filePath}'. Error: {ex.Message}."); + YooLogger.LogWarning($"Failed to delete file '{filePath}': {ex.Message}."); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCache.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCache.cs index 9288e4ef..1e60cc90 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCache.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCache.cs @@ -4,39 +4,49 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 沙盒文件缓存系统,用于管理下载到本地的资源包缓存 + /// 沙盒文件缓存系统,用于管理下载到本地的资源包缓存。 /// internal class SandboxBundleCache : IBundleCache { /// /// 沙盒文件缓存配置 /// - internal struct Configuration + internal readonly struct Configuration { /// /// 文件校验最大并发数 /// - public int FileVerifyMaxConcurrency { get; set; } + public int FileVerifyMaxConcurrency { get; } /// /// 文件校验级别 /// - public EFileVerifyLevel FileVerifyLevel { get; set; } + public EFileVerifyLevel FileVerifyLevel { get; } /// /// AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; } /// /// RawBundle 解密器 /// - public IBundleDecryptor RawBundleDecryptor { get; set; } + public IBundleDecryptor RawBundleDecryptor { get; } /// /// AssetBundle 备用解密器 /// - public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; } + public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; } + + public Configuration(int fileVerifyMaxConcurrency, EFileVerifyLevel fileVerifyLevel, + IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor, IBundleMemoryDecryptor assetBundleFallbackDecryptor) + { + FileVerifyMaxConcurrency = fileVerifyMaxConcurrency; + FileVerifyLevel = fileVerifyLevel; + AssetBundleDecryptor = assetBundleDecryptor; + RawBundleDecryptor = rawBundleDecryptor; + AssetBundleFallbackDecryptor = assetBundleFallbackDecryptor; + } } private const int HashFolderNameLength = 2; @@ -61,7 +71,7 @@ namespace YooAsset public string RootPath { get; } /// - /// 只读属性 + /// 是否为只读缓存 /// public bool IsReadOnly { get; } @@ -101,19 +111,19 @@ namespace YooAsset { } /// - public virtual BCInitializeOperation InitializeAsync() + public BCInitializeOperation InitializeAsync() { var operation = new SBCInitializeOperation(this); return operation; } /// - public virtual BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) + public BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) { var operation = new SBCWriteCacheOperation(this, options); return operation; } /// - public virtual BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) + public BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) { ICacheEvictionPolicy policy = CreateEvictionPolicy(options); if (policy == null) @@ -125,7 +135,9 @@ namespace YooAsset /// /// 根据 ClearMethod 创建对应的淘汰策略实例 /// - protected virtual ICacheEvictionPolicy CreateEvictionPolicy(BCClearCacheOptions options) + /// 清理缓存选项 + /// 与清理方式匹配的淘汰策略实例 + protected ICacheEvictionPolicy CreateEvictionPolicy(BCClearCacheOptions options) { if (options.ClearMethod == ClearCacheMethods.ClearAllBundleFiles) return new EvictionAllPolicy(); @@ -142,41 +154,43 @@ namespace YooAsset return null; } /// - public virtual BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) + public BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) { var operation = new SBCVerifyCacheOperation(this, options); return operation; } /// - public virtual BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) + public BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) { - if (options.Bundle.BundleType == (int)EBundleType.AssetBundle) + if (options.Bundle.GetBundleType() == (int)EBundleType.AssetBundle) { var operation = new SBCLoadAssetBundleOperation(this, options.Bundle); return operation; } - else if (options.Bundle.BundleType == (int)EBundleType.RawBundle) + else if (options.Bundle.GetBundleType() == (int)EBundleType.RawBundle) { var operation = new SBCLoadRawBundleOperation(this, options.Bundle); return operation; } else { - string error = $"{nameof(SandboxBundleCache)} does not support bundle type: {options.Bundle.BundleType}."; + string error = $"{nameof(SandboxBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}."; var operation = new BCLoadBundleErrorOperation(error); return operation; } } /// - public virtual bool IsCached(string bundleGUID) + public bool IsCached(string bundleGuid) { - return _cacheEntries.ContainsKey(bundleGUID); + return _cacheEntries.ContainsKey(bundleGuid); } #region 内部方法 /// /// 获取 Bundle 数据文件路径 /// + /// 资源包描述 + /// 数据文件的完整路径 internal string GetDataFilePath(PackageBundle bundle) { if (_dataFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) @@ -191,6 +205,8 @@ namespace YooAsset /// /// 获取 Bundle 信息文件路径 /// + /// 资源包描述 + /// 信息文件的完整路径 internal string GetInfoFilePath(PackageBundle bundle) { if (_infoFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) @@ -205,6 +221,8 @@ namespace YooAsset /// /// 获取 Bundle 数据临时文件路径 /// + /// 资源包描述 + /// 数据临时文件的完整路径 internal string GetDataTempFilePath(PackageBundle bundle) { string folderName = GetHashFolderName(bundle.FileHash); @@ -214,6 +232,8 @@ namespace YooAsset /// /// 获取 Bundle 信息临时文件路径 /// + /// 资源包描述 + /// 信息临时文件的完整路径 internal string GetInfoTempFilePath(PackageBundle bundle) { string folderName = GetHashFolderName(bundle.FileHash); @@ -223,9 +243,11 @@ namespace YooAsset /// /// 获取指定缓存条目 /// - internal SandboxBundleCacheEntry GetEntry(string bundleGUID) + /// 资源包 GUID + /// 对应的沙盒缓存条目 + internal SandboxBundleCacheEntry GetEntry(string bundleGuid) { - if (_cacheEntries.TryGetValue(bundleGUID, out SandboxBundleCacheEntry entry)) + if (_cacheEntries.TryGetValue(bundleGuid, out SandboxBundleCacheEntry entry)) return entry; else return null; @@ -234,6 +256,7 @@ namespace YooAsset /// /// 获取所有缓存条目 /// + /// 当前字典中全部沙盒缓存条目的只读集合 internal IReadOnlyCollection GetAllEntries() { return _cacheEntries.Values; @@ -242,26 +265,31 @@ namespace YooAsset /// /// 添加指定缓存条目 /// - internal void AddEntry(string bundleGUID, SandboxBundleCacheEntry cacheEntry) + /// 资源包 GUID + /// 沙盒缓存条目 + internal void AddEntry(string bundleGuid, SandboxBundleCacheEntry cacheEntry) { - if (_cacheEntries.ContainsKey(bundleGUID)) - throw new YooInternalException($"Cache entry already exists: '{bundleGUID}'."); + if (_cacheEntries.ContainsKey(bundleGuid)) + throw new YooInternalException($"Cache entry already exists: '{bundleGuid}'."); - _cacheEntries.Add(bundleGUID, cacheEntry); + _cacheEntries.Add(bundleGuid, cacheEntry); SpaceOccupied += cacheEntry.GetFileSize(); } /// /// 删除指定缓存条目 /// - internal void RemoveEntry(string bundleGUID) + /// 资源包 GUID + internal void RemoveEntry(string bundleGuid) { - if (_cacheEntries.TryGetValue(bundleGUID, out SandboxBundleCacheEntry entry)) + if (_cacheEntries.TryGetValue(bundleGuid, out SandboxBundleCacheEntry entry)) { - _cacheEntries.Remove(bundleGUID); - _dataFilePathMapping.Remove(bundleGUID); - _infoFilePathMapping.Remove(bundleGUID); + _cacheEntries.Remove(bundleGuid); + _dataFilePathMapping.Remove(bundleGuid); + _infoFilePathMapping.Remove(bundleGuid); SpaceOccupied -= entry.GetFileSize(); + if (SpaceOccupied < 0) + SpaceOccupied = 0; entry.Delete(); } } @@ -277,4 +305,4 @@ namespace YooAsset } #endregion } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheConsts.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheConsts.cs index 3a5f9e22..ea71fe8a 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheConsts.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheConsts.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件缓存常量定义 /// - internal class SandboxBundleCacheConsts + internal static class SandboxBundleCacheConsts { /// /// 数据文件名称 diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheEntry.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheEntry.cs index 4ecb7069..a3c02b85 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheEntry.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SandboxBundleCacheEntry.cs @@ -13,7 +13,7 @@ namespace YooAsset /// /// 资源包唯一标识 /// - public string BundleGUID { get; private set; } + public string BundleGuid { get; private set; } /// /// 信息文件路径 @@ -27,14 +27,14 @@ namespace YooAsset /// - /// 创建沙盒文件缓存条目 + /// 创建沙盒文件缓存条目实例 /// - /// 资源包唯一标识 + /// 资源包唯一标识 /// 信息文件路径 /// 数据文件路径 - public SandboxBundleCacheEntry(string bundleGUID, string infoFilePath, string dataFilePath) + public SandboxBundleCacheEntry(string bundleGuid, string infoFilePath, string dataFilePath) { - BundleGUID = bundleGUID; + BundleGuid = bundleGuid; InfoFilePath = infoFilePath; DataFilePath = dataFilePath; } @@ -61,7 +61,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"Failed to delete sandbox file. Error: {ex.Message}."); + YooLogger.LogError($"Failed to delete sandbox file: {ex.Message}."); return false; } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SearchFileInfo.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SearchFileInfo.cs index d376de2c..042fe2f4 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SearchFileInfo.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/SearchFileInfo.cs @@ -3,14 +3,14 @@ using System.IO; namespace YooAsset { /// - /// 搜索的文件信息,用于缓存文件校验流程 + /// 搜索的文件信息,用于缓存文件校验流程。 /// internal class SearchFileInfo { /// /// 资源包唯一标识 /// - public string BundleGUID { get; private set; } + public string BundleGuid { get; private set; } /// /// 缓存文件夹路径 @@ -33,15 +33,15 @@ namespace YooAsset public volatile int VerifyResultCode = 0; /// - /// 创建验证文件信息 + /// 创建验证文件信息实例 /// - /// 资源包唯一标识 + /// 资源包唯一标识 /// 缓存文件夹路径 /// 数据文件路径 /// 信息文件路径 - public SearchFileInfo(string bundleGUID, string folderPath, string dataFilePath, string infoFilePath) + public SearchFileInfo(string bundleGuid, string folderPath, string dataFilePath, string infoFilePath) { - BundleGUID = bundleGUID; + BundleGuid = bundleGuid; FolderPath = folderPath; DataFilePath = dataFilePath; InfoFilePath = infoFilePath; @@ -58,8 +58,8 @@ namespace YooAsset } catch (System.Exception ex) { - YooLogger.Warning($"Failed to delete cache bundle folder: {ex}."); + YooLogger.LogWarning($"Failed to delete cache bundle folder: {ex}."); } } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/TempFileInfo.cs b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/TempFileInfo.cs index 38d72746..2ec8ce19 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/TempFileInfo.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/SandboxBundleCache/TempFileInfo.cs @@ -2,41 +2,41 @@ namespace YooAsset { /// - /// 临时的文件信息,用于存储待验证的下载文件 + /// 临时的文件信息,用于存储待验证的下载文件。 /// internal class TempFileInfo { /// /// 临时文件路径 /// - public string FilePath { private set; get; } + public string FilePath { get; private set; } /// /// 文件CRC校验值 /// - public uint FileCRC { private set; get; } + public uint FileCrc { get; private set; } /// /// 文件大小(字节) /// - public long FileSize { private set; get; } + public long FileSize { get; private set; } /// - /// 验证结果码(原子操作对象,用于线程安全) + /// 验证结果码(原子操作对象,用于线程安全)。 /// public volatile int VerifyResultCode = 0; /// - /// 创建临时文件信息 + /// 创建临时文件信息实例 /// /// 临时文件路径 - /// 文件CRC校验值 + /// 文件CRC校验值 /// 文件大小(字节) - public TempFileInfo(string filePath, uint fileCRC, long fileSize) + public TempFileInfo(string filePath, uint fileCrc, long fileSize) { FilePath = filePath; - FileCRC = fileCRC; + FileCrc = fileCrc; FileSize = fileSize; } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCInitializeOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCInitializeOperation.cs index b53b56c7..5552e28a 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCInitializeOperation.cs @@ -4,13 +4,17 @@ namespace YooAsset /// /// Web远端文件缓存初始化操作 /// - internal class WRBCInitializeOperation : BCInitializeOperation + internal sealed class WRBCInitializeOperation : BCInitializeOperation { private readonly WebRemoteBundleCache _fileCache; - public WRBCInitializeOperation(WebRemoteBundleCache cache) + /// + /// 创建 Web 远端缓存初始化操作实例 + /// + /// Web 远端文件缓存系统 + public WRBCInitializeOperation(WebRemoteBundleCache fileCache) { - _fileCache = cache; + _fileCache = fileCache; } protected override void InternalStart() { diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCLoadBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCLoadBundleOperation.cs index 34076688..551df3a2 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/Operations/WRBCLoadBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web远端文件缓存加载 AssetBundle 操作 /// - internal class WRBCLoadAssetBundleOperation : BCLoadBundleOperation + internal sealed class WRBCLoadAssetBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -20,6 +20,11 @@ namespace YooAsset private WebRemoteBundleCacheEntry _cacheEntry; private ESteps _steps = ESteps.None; + /// + /// 创建 Web 远端 AssetBundle 加载操作实例 + /// + /// Web 远端文件缓存系统 + /// 加载资源包操作选项 public WRBCLoadAssetBundleOperation(WebRemoteBundleCache fileCache, BCLoadBundleOptions options) { _fileCache = fileCache; @@ -52,17 +57,17 @@ namespace YooAsset { if (_loadWebAssetBundleOp == null) { - var options = new LoadWebAssetBundleOptions(); - options.CacheName = _fileCache.GetType().Name; - options.Bundle = _options.Bundle; - options.CandidateUrls = _cacheEntry.URLs; - options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor; - options.DownloadBackend = _fileCache.Config.DownloadBackend; - options.DownloadVerifyLevel = _fileCache.Config.DownloadVerifyLevel; - options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout; - options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache; - options.DownloadRetryPolicy = _fileCache.Config.DownloadRetryPolicy; - options.DownloadUrlPolicy = _fileCache.Config.DownloadUrlPolicy; + var options = new LoadWebAssetBundleOptions( + cacheName: _fileCache.GetType().Name, + bundle: _options.Bundle, + candidateUrls: _cacheEntry.URLs, + assetBundleDecryptor: _fileCache.Config.AssetBundleDecryptor, + downloadBackend: _fileCache.Config.DownloadBackend, + downloadVerifyLevel: _fileCache.Config.DownloadVerifyLevel, + watchdogTimeout: _fileCache.Config.WatchdogTimeout, + disableUnityWebCache: _fileCache.Config.DisableUnityWebCache, + downloadRetryPolicy: _fileCache.Config.DownloadRetryPolicy, + downloadUrlPolicy: _fileCache.Config.DownloadUrlPolicy); if (_options.Bundle.IsEncrypted) _loadWebAssetBundleOp = new LoadWebEncryptedAssetBundleOperation(options); @@ -99,7 +104,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError($"{nameof(WebRemoteBundleCache)} does not support synchronous asset bundle loading."); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCache.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCache.cs index 1a4b5718..962412ff 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCache.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCache.cs @@ -4,54 +4,68 @@ using System.Collections.Generic; namespace YooAsset { /// - /// Web远端文件缓存系统,用于从远程服务器加载资源 + /// Web远端文件缓存系统,用于从远程服务器加载资源。 /// internal class WebRemoteBundleCache : IBundleCache { /// /// Web远端文件缓存配置 /// - internal struct Configuration + internal readonly struct Configuration { /// /// 看门狗超时时间 /// - public int WatchdogTimeout { get; set; } + public int WatchdogTimeout { get; } /// /// 禁用Unity的网络缓存 /// - public bool DisableUnityWebCache { get; set; } + public bool DisableUnityWebCache { get; } /// /// 下载数据校验级别 /// - public EFileVerifyLevel DownloadVerifyLevel { get; set; } + public EFileVerifyLevel DownloadVerifyLevel { get; } /// /// AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; } /// /// 远程服务接口 /// - public IRemoteService RemoteService { get; set; } + public IRemoteService RemoteService { get; } /// /// 下载后台接口 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } /// /// 下载重试判定策略 /// - public IDownloadRetryPolicy DownloadRetryPolicy { get; set; } + public IDownloadRetryPolicy DownloadRetryPolicy { get; } /// /// URL 选择策略 /// - public IDownloadUrlPolicy DownloadUrlPolicy { get; set; } + public IDownloadUrlPolicy DownloadUrlPolicy { get; } + + public Configuration(int watchdogTimeout, bool disableUnityWebCache, + EFileVerifyLevel downloadVerifyLevel, IBundleDecryptor assetBundleDecryptor, IRemoteService remoteService, + IDownloadBackend downloadBackend, IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy) + { + WatchdogTimeout = watchdogTimeout; + DisableUnityWebCache = disableUnityWebCache; + DownloadVerifyLevel = downloadVerifyLevel; + AssetBundleDecryptor = assetBundleDecryptor; + RemoteService = remoteService; + DownloadBackend = downloadBackend; + DownloadRetryPolicy = downloadRetryPolicy; + DownloadUrlPolicy = downloadUrlPolicy; + } } private readonly Dictionary _cacheEntries = new Dictionary(10000); @@ -73,7 +87,7 @@ namespace YooAsset public string RootPath { get; } /// - /// 只读属性 + /// 是否为只读缓存 /// public bool IsReadOnly { get; } @@ -113,46 +127,46 @@ namespace YooAsset { } /// - public virtual BCInitializeOperation InitializeAsync() + public BCInitializeOperation InitializeAsync() { var operation = new WRBCInitializeOperation(this); return operation; } /// - public virtual BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) + public BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) { var operation = new BCWriteCacheCompleteOperation($"{nameof(WebRemoteBundleCache)} is readonly."); return operation; } /// - public virtual BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) + public BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) { var operation = new BCClearCacheCompleteOperation(); return operation; } /// - public virtual BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) + public BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) { var operation = new BCVerifyCacheCompleteOperation(); return operation; } /// - public virtual BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) + public BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) { - if (options.Bundle.BundleType == (int)EBundleType.AssetBundle) + if (options.Bundle.GetBundleType() == (int)EBundleType.AssetBundle) { var operation = new WRBCLoadAssetBundleOperation(this, options); return operation; } else { - string error = $"{nameof(WebRemoteBundleCache)} does not support bundle type: {options.Bundle.BundleType}."; + string error = $"{nameof(WebRemoteBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}."; var operation = new BCLoadBundleErrorOperation(error); return operation; } } /// - public virtual bool IsCached(string bundleGUID) + public bool IsCached(string bundleGuid) { return true; } @@ -161,6 +175,8 @@ namespace YooAsset /// /// 获取或创建指定资源包的缓存条目 /// + /// 资源包描述 + /// 已存在则返回对应条目;否则创建并登记后返回新条目。 internal WebRemoteBundleCacheEntry GetEntry(PackageBundle bundle) { if (_cacheEntries.TryGetValue(bundle.BundleGuid, out WebRemoteBundleCacheEntry entry)) @@ -169,7 +185,7 @@ namespace YooAsset } else { - var urls = Config.RemoteService.GetRemoteUrls(bundle.FileName); + var urls = Config.RemoteService.GetRemoteUrls(bundle.GetFileName()); var newEntry = new WebRemoteBundleCacheEntry(bundle.BundleGuid, urls); _cacheEntries.Add(bundle.BundleGuid, newEntry); return newEntry; @@ -177,4 +193,4 @@ namespace YooAsset } #endregion } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCacheEntry.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCacheEntry.cs index d9e80013..388cd7f6 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCacheEntry.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebRemoteBundleCache/WebRemoteBundleCacheEntry.cs @@ -10,7 +10,7 @@ namespace YooAsset /// /// 资源包唯一标识 /// - public string BundleGUID { get; private set; } + public string BundleGuid { get; private set; } /// /// 候选下载地址列表 @@ -18,13 +18,13 @@ namespace YooAsset public IReadOnlyList URLs { get; private set; } /// - /// 创建Web远端文件缓存条目 + /// 创建 Web 远端文件缓存条目实例 /// - /// 资源包唯一标识 + /// 资源包唯一标识 /// 候选下载地址列表 - public WebRemoteBundleCacheEntry(string bundleGUID, IReadOnlyList urls) + public WebRemoteBundleCacheEntry(string bundleGuid, IReadOnlyList urls) { - BundleGUID = bundleGUID; + BundleGuid = bundleGuid; URLs = urls; } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCInitializeOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCInitializeOperation.cs index 48d00b11..0ea83290 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web服务器文件缓存初始化操作 /// - internal class WSBCInitializeOperation : BCInitializeOperation + internal sealed class WSBCInitializeOperation : BCInitializeOperation { private enum ESteps { @@ -18,9 +18,13 @@ namespace YooAsset private LoadBuiltinCatalogOperation _loadBuiltinCatalogOp; private ESteps _steps = ESteps.None; - public WSBCInitializeOperation(WebServerBundleCache cache) + /// + /// 创建 Web 服务器缓存初始化操作实例 + /// + /// Web 服务器文件缓存系统 + public WSBCInitializeOperation(WebServerBundleCache fileCache) { - _fileCache = cache; + _fileCache = fileCache; } protected override void InternalStart() { @@ -35,10 +39,10 @@ namespace YooAsset { if (_loadBuiltinCatalogOp == null) { - var options = new LoadBuiltinCatalogOptions(); - options.PackageName = _fileCache.PackageName; - options.FilePath = _fileCache.GetCatalogBinaryFileLoadPath(); - options.DownloadBackend = _fileCache.Config.DownloadBackend; + var options = new LoadBuiltinCatalogOptions( + packageName: _fileCache.PackageName, + filePath: _fileCache.GetCatalogBinaryFileLoadPath(), + downloadBackend: _fileCache.Config.DownloadBackend); _loadBuiltinCatalogOp = new LoadBuiltinCatalogOperation(options); _loadBuiltinCatalogOp.StartOperation(); AddChildOperation(_loadBuiltinCatalogOp); @@ -65,8 +69,8 @@ namespace YooAsset foreach (var fileEntry in catalog.Entries) { string filePath = PathUtility.Combine(_fileCache.RootPath, fileEntry.FileName); - var cacheEntry = new WebServerBundleCacheEntry(fileEntry.BundleGUID, filePath); - _fileCache.AddEntry(fileEntry.BundleGUID, cacheEntry); + var cacheEntry = new WebServerBundleCacheEntry(fileEntry.BundleGuid, filePath); + _fileCache.AddEntry(fileEntry.BundleGuid, cacheEntry); } _steps = ESteps.Done; diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCLoadBundleOperation.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCLoadBundleOperation.cs index 7fef2f05..1833c1ce 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/Operations/WSBCLoadBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web服务器文件缓存加载 AssetBundle 操作 /// - internal class WSBCLoadAssetBundleOperation : BCLoadBundleOperation + internal sealed class WSBCLoadAssetBundleOperation : BCLoadBundleOperation { private enum ESteps { @@ -20,6 +20,11 @@ namespace YooAsset private WebServerBundleCacheEntry _cacheEntry; private ESteps _steps = ESteps.None; + /// + /// 创建 Web 服务器 AssetBundle 加载操作实例 + /// + /// Web 服务器文件缓存系统 + /// 加载资源包操作选项 public WSBCLoadAssetBundleOperation(WebServerBundleCache fileCache, BCLoadBundleOptions options) { _fileCache = fileCache; @@ -53,17 +58,17 @@ namespace YooAsset if (_loadWebAssetBundleOp == null) { string url = DownloadUrlHelper.ToLocalFileUrl(_cacheEntry.FilePath); - var options = new LoadWebAssetBundleOptions(); - options.CacheName = _fileCache.GetType().Name; - options.Bundle = _options.Bundle; - options.CandidateUrls = new[] { url }; - options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor; - options.DownloadBackend = _fileCache.Config.DownloadBackend; - options.DownloadVerifyLevel = _fileCache.Config.DownloadVerifyLevel; - options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout; - options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache; - options.DownloadRetryPolicy = _fileCache.Config.DownloadRetryPolicy; - options.DownloadUrlPolicy = _fileCache.Config.DownloadUrlPolicy; + var options = new LoadWebAssetBundleOptions( + cacheName: _fileCache.GetType().Name, + bundle: _options.Bundle, + candidateUrls: new[] { url }, + assetBundleDecryptor: _fileCache.Config.AssetBundleDecryptor, + downloadBackend: _fileCache.Config.DownloadBackend, + downloadVerifyLevel: _fileCache.Config.DownloadVerifyLevel, + watchdogTimeout: _fileCache.Config.WatchdogTimeout, + disableUnityWebCache: _fileCache.Config.DisableUnityWebCache, + downloadRetryPolicy: _fileCache.Config.DownloadRetryPolicy, + downloadUrlPolicy: _fileCache.Config.DownloadUrlPolicy); if (_options.Bundle.IsEncrypted) _loadWebAssetBundleOp = new LoadWebEncryptedAssetBundleOperation(options); @@ -100,7 +105,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError($"{nameof(WebServerBundleCache)} does not support synchronous asset bundle loading."); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCache.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCache.cs index d53f1ae2..f531a746 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCache.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCache.cs @@ -4,49 +4,62 @@ using System.Collections.Generic; namespace YooAsset { /// - /// Web服务器文件缓存系统,用于WebGL平台从服务器加载资源 + /// Web服务器文件缓存系统,用于WebGL平台从服务器加载资源。 /// internal class WebServerBundleCache : IBundleCache { /// /// Web服务器文件缓存配置 /// - internal struct Configuration + internal readonly struct Configuration { /// /// 看门狗超时时间 /// - public int WatchdogTimeout { get; set; } + public int WatchdogTimeout { get; } /// /// 禁用Unity的网络缓存 /// - public bool DisableUnityWebCache { get; set; } + public bool DisableUnityWebCache { get; } /// /// 下载数据校验级别 /// - public EFileVerifyLevel DownloadVerifyLevel { get; set; } + public EFileVerifyLevel DownloadVerifyLevel { get; } /// /// AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; } /// /// 下载后台 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } /// /// 下载重试判定策略 /// - public IDownloadRetryPolicy DownloadRetryPolicy { get; set; } + public IDownloadRetryPolicy DownloadRetryPolicy { get; } /// /// URL 选择策略 /// - public IDownloadUrlPolicy DownloadUrlPolicy { get; set; } + public IDownloadUrlPolicy DownloadUrlPolicy { get; } + + public Configuration(int watchdogTimeout, bool disableUnityWebCache, + EFileVerifyLevel downloadVerifyLevel, IBundleDecryptor assetBundleDecryptor, + IDownloadBackend downloadBackend, IDownloadRetryPolicy downloadRetryPolicy, IDownloadUrlPolicy downloadUrlPolicy) + { + WatchdogTimeout = watchdogTimeout; + DisableUnityWebCache = disableUnityWebCache; + DownloadVerifyLevel = downloadVerifyLevel; + AssetBundleDecryptor = assetBundleDecryptor; + DownloadBackend = downloadBackend; + DownloadRetryPolicy = downloadRetryPolicy; + DownloadUrlPolicy = downloadUrlPolicy; + } } private readonly Dictionary _cacheEntries = new Dictionary(10000); @@ -68,7 +81,7 @@ namespace YooAsset public string RootPath { get; } /// - /// 只读属性 + /// 是否为只读缓存 /// public bool IsReadOnly { get; } @@ -108,57 +121,59 @@ namespace YooAsset { } /// - public virtual BCInitializeOperation InitializeAsync() + public BCInitializeOperation InitializeAsync() { var operation = new WSBCInitializeOperation(this); return operation; } /// - public virtual BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) + public BCWriteCacheOperation WriteCacheAsync(BCWriteCacheOptions options) { var operation = new BCWriteCacheCompleteOperation($"{nameof(WebServerBundleCache)} is readonly."); return operation; } /// - public virtual BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) + public BCClearCacheOperation ClearCacheAsync(BCClearCacheOptions options) { var operation = new BCClearCacheCompleteOperation(); return operation; } /// - public virtual BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) + public BCVerifyCacheOperation VerifyCacheAsync(BCVerifyCacheOptions options) { var operation = new BCVerifyCacheCompleteOperation(); return operation; } /// - public virtual BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) + public BCLoadBundleOperation LoadBundleAsync(BCLoadBundleOptions options) { - if (options.Bundle.BundleType == (int)EBundleType.AssetBundle) + if (options.Bundle.GetBundleType() == (int)EBundleType.AssetBundle) { var operation = new WSBCLoadAssetBundleOperation(this, options); return operation; } else { - string error = $"{nameof(WebServerBundleCache)} does not support bundle type: {options.Bundle.BundleType}."; + string error = $"{nameof(WebServerBundleCache)} does not support bundle type: {options.Bundle.GetBundleType()}."; var operation = new BCLoadBundleErrorOperation(error); return operation; } } /// - public virtual bool IsCached(string bundleGUID) + public bool IsCached(string bundleGuid) { - return _cacheEntries.ContainsKey(bundleGUID); + return _cacheEntries.ContainsKey(bundleGuid); } #region 内部方法 /// /// 获取指定缓存条目 /// - internal WebServerBundleCacheEntry GetEntry(string bundleGUID) + /// 资源包 GUID + /// 对应的 Web 服务器缓存条目 + internal WebServerBundleCacheEntry GetEntry(string bundleGuid) { - if (_cacheEntries.TryGetValue(bundleGUID, out WebServerBundleCacheEntry entry)) + if (_cacheEntries.TryGetValue(bundleGuid, out WebServerBundleCacheEntry entry)) return entry; else return null; @@ -167,21 +182,24 @@ namespace YooAsset /// /// 添加指定缓存条目 /// - internal void AddEntry(string bundleGUID, WebServerBundleCacheEntry cacheEntry) + /// 资源包 GUID + /// Web 服务器缓存条目 + internal void AddEntry(string bundleGuid, WebServerBundleCacheEntry cacheEntry) { - if (_cacheEntries.ContainsKey(bundleGUID)) - throw new YooInternalException($"Cache entry already exists: '{bundleGUID}'."); + if (_cacheEntries.ContainsKey(bundleGuid)) + throw new YooInternalException($"Cache entry already exists: '{bundleGuid}'."); - _cacheEntries.Add(bundleGUID, cacheEntry); + _cacheEntries.Add(bundleGuid, cacheEntry); } /// /// 获取Catalog文件加载路径 /// + /// 文件的完整加载路径 internal string GetCatalogBinaryFileLoadPath() { return PathUtility.Combine(RootPath, BuiltinCatalogConsts.BinaryFileName); } #endregion } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCacheEntry.cs b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCacheEntry.cs index 571c1d55..fb065112 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCacheEntry.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Services/WebServerBundleCache/WebServerBundleCacheEntry.cs @@ -9,7 +9,7 @@ namespace YooAsset /// /// 资源包唯一标识 /// - public string BundleGUID { get; private set; } + public string BundleGuid { get; private set; } /// /// 资源包文件路径 @@ -17,13 +17,13 @@ namespace YooAsset public string FilePath { get; private set; } /// - /// 创建Web服务器文件缓存条目 + /// 创建 Web 服务器文件缓存条目实例 /// - /// 资源包唯一标识 + /// 资源包唯一标识 /// 资源包文件路径 - public WebServerBundleCacheEntry(string bundleGUID, string filePath) + public WebServerBundleCacheEntry(string bundleGuid, string filePath) { - BundleGUID = bundleGUID; + BundleGuid = bundleGuid; FilePath = filePath; } } diff --git a/Assets/YooAsset/Runtime/BundleHandle/EBundleType.cs b/Assets/YooAsset/Runtime/BundleHandle/EBundleType.cs index eec5483b..bfe3881e 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/EBundleType.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/EBundleType.cs @@ -2,14 +2,14 @@ namespace YooAsset { /// - /// 资源包类型枚举 + /// 资源包的类型 /// public enum EBundleType { /// - /// 未知类型 + /// 未指定类型 /// - Unknown = 0, + None = 0, /// /// 虚拟资源包 diff --git a/Assets/YooAsset/Runtime/BundleHandle/Interfaces/IBundleHandle.cs b/Assets/YooAsset/Runtime/BundleHandle/Interfaces/IBundleHandle.cs index 2316b954..03286a6a 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Interfaces/IBundleHandle.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Interfaces/IBundleHandle.cs @@ -3,7 +3,7 @@ using UnityEngine.SceneManagement; namespace YooAsset { /// - /// 资源包句柄接口,提供对已加载资源包的操作能力 + /// 资源包句柄接口,提供对已加载资源包的操作能力。 /// internal interface IBundleHandle { @@ -18,33 +18,33 @@ namespace YooAsset void UnloadBundle(); /// - /// 异步加载指定的主资源对象 + /// 加载指定的主资源对象 /// /// 待加载资源的描述信息 /// 用于跟踪加载过程的异步操作对象 BHLoadAssetOperation LoadAssetAsync(AssetInfo assetInfo); /// - /// 异步加载资源包内的全部资源对象 + /// 加载资源包内的全部资源对象 /// /// 待加载资源的描述信息 /// 用于跟踪加载过程的异步操作对象 BHLoadAllAssetsOperation LoadAllAssetsAsync(AssetInfo assetInfo); /// - /// 异步加载指定资源对应的全部子资源对象 + /// 加载指定资源对应的全部子资源对象 /// /// 待加载资源的描述信息 /// 用于跟踪加载过程的异步操作对象 BHLoadSubAssetsOperation LoadSubAssetsAsync(AssetInfo assetInfo); /// - /// 异步加载指定的场景资源 + /// 加载指定的场景资源 /// /// 待加载场景的资源信息 - /// 场景加载参数 + /// 场景加载选项 /// 是否允许场景在加载完成后立即激活 /// 用于跟踪场景加载过程的异步操作对象 BHLoadSceneOperation LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool allowSceneActivation); } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleHandle/Operations/BHLoadSceneOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Operations/BHLoadSceneOperation.cs index c339b701..a7665688 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Operations/BHLoadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Operations/BHLoadSceneOperation.cs @@ -14,6 +14,14 @@ namespace YooAsset /// /// 允许场景在加载完成后进入激活阶段 /// - public abstract void AllowSceneActivation(); + public void AllowSceneActivation() + { + InternalAllowSceneActivation(); + } + + /// + /// 执行场景激活的方法 + /// + protected abstract void InternalAllowSceneActivation(); } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/AssetBundleHandle.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/AssetBundleHandle.cs index d1d5b08c..c5eee776 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/AssetBundleHandle.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/AssetBundleHandle.cs @@ -7,7 +7,7 @@ namespace YooAsset /// /// AssetBundle资源包句柄 /// - internal class AssetBundleHandle : IBundleHandle + internal sealed class AssetBundleHandle : IBundleHandle { private readonly string _bundleFilePath; private readonly PackageBundle _packageBundle; @@ -22,6 +22,13 @@ namespace YooAsset get { return _bundleFilePath; } } + /// + /// 创建AssetBundle资源包句柄实例 + /// + /// 资源包文件的本地路径 + /// 资源包描述 + /// 已加载的 Unity AssetBundle 对象 + /// 加载 AssetBundle 时使用的文件流 public AssetBundleHandle(string bundleFilePath, PackageBundle packageBundle, AssetBundle assetBundle, Stream bundleStream) { _bundleFilePath = bundleFilePath; @@ -42,7 +49,6 @@ namespace YooAsset if (_bundleStream != null) { - _bundleStream.Close(); _bundleStream.Dispose(); } } diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAllAssetsOperation.cs index 67b28e71..580aeb1e 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAllAssetsOperation.cs @@ -3,11 +3,11 @@ using UnityEngine; namespace YooAsset { /// - /// AssetBundle的加载所有资源操作 + /// 从 AssetBundle 中加载全部资源对象 /// - internal class ABHLoadAllAssetsOperation : BHLoadAllAssetsOperation + internal sealed class ABHLoadAllAssetsOperation : BHLoadAllAssetsOperation { - protected enum ESteps + private enum ESteps { None, CheckBundle, @@ -22,6 +22,12 @@ namespace YooAsset private AssetBundleRequest _request; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 已加载的 Unity AssetBundle 对象 + /// 待加载资源信息 public ABHLoadAllAssetsOperation(PackageBundle packageBundle, AssetBundle assetBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -42,7 +48,7 @@ namespace YooAsset if (_assetBundle == null) { _steps = ESteps.Done; - SetError($"The bundle {_packageBundle.BundleName} has been destroyed due to Unity engine bugs."); + SetError($"Bundle '{_packageBundle.BundleName}' has been destroyed due to Unity engine bugs."); return; } @@ -77,7 +83,7 @@ namespace YooAsset if (IsWaitForCompletion) { // 强制挂起主线程(注意:该操作会很耗时) - YooLogger.Warning("Blocking the main thread while loading Unity assets."); + YooLogger.LogWarning("Blocking the main thread while loading Unity assets."); Result = _request.allAssets; } else @@ -93,13 +99,13 @@ namespace YooAsset { string error; if (_assetInfo.AssetType == null) - error = $"Failed to load all assets: {_assetInfo.AssetPath} AssetType: null AssetBundle: {_packageBundle.BundleName}"; + error = $"Failed to load all assets: '{_assetInfo.AssetPath}' AssetType: null AssetBundle: '{_packageBundle.BundleName}'."; else - error = $"Failed to load all assets: {_assetInfo.AssetPath} AssetType: {_assetInfo.AssetType} AssetBundle: {_packageBundle.BundleName}"; + error = $"Failed to load all assets: '{_assetInfo.AssetPath}' AssetType: {_assetInfo.AssetType} AssetBundle: '{_packageBundle.BundleName}'."; _steps = ESteps.Done; SetError(error); - YooLogger.Error(error); + YooLogger.LogError(error); } else { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAssetOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAssetOperation.cs index e7503ab0..2ad52778 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAssetOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadAssetOperation.cs @@ -3,11 +3,11 @@ using UnityEngine; namespace YooAsset { /// - /// AssetBundle的加载单个资源操作 + /// 从 AssetBundle 中加载单个资源对象 /// - internal class ABHLoadAssetOperation : BHLoadAssetOperation + internal sealed class ABHLoadAssetOperation : BHLoadAssetOperation { - protected enum ESteps + private enum ESteps { None, CheckBundle, @@ -22,6 +22,12 @@ namespace YooAsset private AssetBundleRequest _request; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 已加载的 Unity AssetBundle 对象 + /// 待加载资源信息 public ABHLoadAssetOperation(PackageBundle packageBundle, AssetBundle assetBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -42,7 +48,7 @@ namespace YooAsset if (_assetBundle == null) { _steps = ESteps.Done; - SetError($"The bundle {_packageBundle.BundleName} has been destroyed due to Unity engine bugs."); + SetError($"Bundle '{_packageBundle.BundleName}' has been destroyed due to Unity engine bugs."); return; } @@ -77,7 +83,7 @@ namespace YooAsset if (IsWaitForCompletion) { // 强制挂起主线程(注意:该操作会很耗时) - YooLogger.Warning("Blocking the main thread while loading a Unity asset."); + YooLogger.LogWarning("Blocking the main thread while loading a Unity asset."); Result = _request.asset; } else @@ -93,13 +99,13 @@ namespace YooAsset { string error; if (_assetInfo.AssetType == null) - error = $"Failed to load asset: {_assetInfo.AssetPath} AssetType: null AssetBundle: {_packageBundle.BundleName}"; + error = $"Failed to load asset: '{_assetInfo.AssetPath}' AssetType: null AssetBundle: '{_packageBundle.BundleName}'."; else - error = $"Failed to load asset: {_assetInfo.AssetPath} AssetType: {_assetInfo.AssetType} AssetBundle: {_packageBundle.BundleName}"; + error = $"Failed to load asset: '{_assetInfo.AssetPath}' AssetType: {_assetInfo.AssetType} AssetBundle: '{_packageBundle.BundleName}'."; _steps = ESteps.Done; SetError(error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } else { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSceneOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSceneOperation.cs index 0a35c8b7..ac1c9588 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSceneOperation.cs @@ -4,11 +4,11 @@ using UnityEngine.SceneManagement; namespace YooAsset { /// - /// AssetBundle的场景加载操作 + /// 从 AssetBundle 中加载场景资源 /// - internal class ABHLoadSceneOperation : BHLoadSceneOperation + internal sealed class ABHLoadSceneOperation : BHLoadSceneOperation { - protected enum ESteps + private enum ESteps { None, LoadScene, @@ -22,6 +22,12 @@ namespace YooAsset private AsyncOperation _asyncOperation; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 待加载场景信息 + /// 控制场景加载的选项 + /// 是否允许场景在加载完成后立即激活 public ABHLoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool allowSceneActivation) { _assetInfo = assetInfo; @@ -60,8 +66,8 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"Failed to load scene: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Failed to load scene: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); } } } @@ -73,7 +79,7 @@ namespace YooAsset if (IsWaitForCompletion) { // 注意:场景加载无法强制异步转同步 - YooLogger.Error("The scene is already loading asynchronously."); + YooLogger.LogError("The scene is already loading asynchronously."); } else { @@ -98,8 +104,8 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"The loaded scene is invalid: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Loaded scene is invalid: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); } } } @@ -108,7 +114,7 @@ namespace YooAsset //注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法! ExecuteOnce(); } - public override void AllowSceneActivation() + protected override void InternalAllowSceneActivation() { _allowSceneActivation = true; } diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSubAssetsOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSubAssetsOperation.cs index 7d47901e..42d25e1c 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSubAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/AssetBundleHandle/Operations/ABHLoadSubAssetsOperation.cs @@ -3,11 +3,11 @@ using UnityEngine; namespace YooAsset { /// - /// AssetBundle的加载子资源操作 + /// 从 AssetBundle 中加载指定资源的全部子资源对象 /// - internal class ABHLoadSubAssetsOperation : BHLoadSubAssetsOperation + internal sealed class ABHLoadSubAssetsOperation : BHLoadSubAssetsOperation { - protected enum ESteps + private enum ESteps { None, CheckBundle, @@ -22,6 +22,12 @@ namespace YooAsset private AssetBundleRequest _request; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 已加载的 Unity AssetBundle 对象 + /// 待加载资源信息 public ABHLoadSubAssetsOperation(PackageBundle packageBundle, AssetBundle assetBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -42,7 +48,7 @@ namespace YooAsset if (_assetBundle == null) { _steps = ESteps.Done; - SetError($"The bundle {_packageBundle.BundleName} has been destroyed due to Unity engine bugs."); + SetError($"Bundle '{_packageBundle.BundleName}' has been destroyed due to Unity engine bugs."); return; } @@ -77,7 +83,7 @@ namespace YooAsset if (IsWaitForCompletion) { // 强制挂起主线程(注意:该操作会很耗时) - YooLogger.Warning("Blocking the main thread while loading Unity assets."); + YooLogger.LogWarning("Blocking the main thread while loading Unity assets."); Result = _request.allAssets; } else @@ -93,13 +99,13 @@ namespace YooAsset { string error; if (_assetInfo.AssetType == null) - error = $"Failed to load sub-assets: {_assetInfo.AssetPath} AssetType: null AssetBundle: {_packageBundle.BundleName}"; + error = $"Failed to load sub-assets: '{_assetInfo.AssetPath}' AssetType: null AssetBundle: '{_packageBundle.BundleName}'."; else - error = $"Failed to load sub-assets: {_assetInfo.AssetPath} AssetType: {_assetInfo.AssetType} AssetBundle: {_packageBundle.BundleName}"; + error = $"Failed to load sub-assets: '{_assetInfo.AssetPath}' AssetType: {_assetInfo.AssetType} AssetBundle: '{_packageBundle.BundleName}'."; _steps = ESteps.Done; SetError(error); - YooLogger.Error(error); + YooLogger.LogError(error); } else { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAllAssetsOperation.cs index d3e4bd3e..dd9ca11e 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAllAssetsOperation.cs @@ -2,9 +2,9 @@ namespace YooAsset { /// - /// 原生资源包的加载所有资源操作(不支持) + /// 全部资源加载操作(原生资源包不支持) /// - internal class RBHLoadAllAssetsOperation : BHLoadAllAssetsOperation + internal sealed class RBHLoadAllAssetsOperation : BHLoadAllAssetsOperation { protected override void InternalStart() { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAssetOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAssetOperation.cs index 1930d860..525508bf 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAssetOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadAssetOperation.cs @@ -2,11 +2,11 @@ namespace YooAsset { /// - /// 原生资源包的加载单个资源操作 + /// 从原生资源包中加载单个资源对象 /// - internal class RBHLoadAssetOperation : BHLoadAssetOperation + internal sealed class RBHLoadAssetOperation : BHLoadAssetOperation { - protected enum ESteps + private enum ESteps { None, LoadObject, @@ -19,6 +19,12 @@ namespace YooAsset private readonly AssetInfo _assetInfo; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 已加载的原生资源包数据对象 + /// 待加载资源信息 public RBHLoadAssetOperation(PackageBundle packageBundle, RawBundle rawBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -45,8 +51,8 @@ namespace YooAsset if (Result == null) { _steps = ESteps.Done; - SetError($"Failed to load raw file object: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Failed to load raw file object: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); } else { @@ -55,5 +61,9 @@ namespace YooAsset } } } + protected override void InternalWaitForCompletion() + { + ExecuteBatch(); + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSceneOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSceneOperation.cs index f02574a8..0d68604c 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSceneOperation.cs @@ -2,9 +2,9 @@ namespace YooAsset { /// - /// 原生资源包的场景加载操作(不支持) + /// 场景加载操作(原生资源包不支持) /// - internal class RBHLoadSceneOperation : BHLoadSceneOperation + internal sealed class RBHLoadSceneOperation : BHLoadSceneOperation { protected override void InternalStart() { @@ -13,7 +13,7 @@ namespace YooAsset protected override void InternalUpdate() { } - public override void AllowSceneActivation() + protected override void InternalAllowSceneActivation() { } } diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSubAssetsOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSubAssetsOperation.cs index 0e0d2db7..a9a73744 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSubAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/Operations/RBHLoadSubAssetsOperation.cs @@ -2,9 +2,9 @@ namespace YooAsset { /// - /// 原生资源包的加载子资源操作(不支持) + /// 子资源加载操作(原生资源包不支持) /// - internal class RBHLoadSubAssetsOperation : BHLoadSubAssetsOperation + internal sealed class RBHLoadSubAssetsOperation : BHLoadSubAssetsOperation { protected override void InternalStart() { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundle.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundle.cs index cba32dd9..9beddf73 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundle.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundle.cs @@ -1,25 +1,37 @@ +using System; namespace YooAsset { /// /// 封装原生文件字节数据的资源包对象 /// - public class RawBundle + internal class RawBundle { private byte[] _bytes; + private RawFileObject _cachedObject; + /// + /// 创建实例 + /// + /// 原生文件的字节数据 public RawBundle(byte[] bytes) { + if (bytes == null) + throw new ArgumentNullException(nameof(bytes)); _bytes = bytes; } /// - /// 根据当前字节数据创建可访问的原生文件对象 + /// 创建基于当前字节数据的原生文件对象 /// /// 创建得到的原生文件对象 public RawFileObject CreateRawFileObject() { - return RawFileObject.CreateFromBytes(_bytes); + if (_bytes == null) + throw new InvalidOperationException($"{nameof(RawBundle)} has been unloaded."); + if (_cachedObject == null) + _cachedObject = RawFileObject.CreateFromBytes(_bytes); + return _cachedObject; } /// @@ -27,6 +39,12 @@ namespace YooAsset /// public void Unload() { + if (_cachedObject != null) + { + _cachedObject.Release(); + UnityEngine.Object.Destroy(_cachedObject); + _cachedObject = null; + } _bytes = null; } } diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundleHandle.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundleHandle.cs index 2aac4156..97287595 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundleHandle.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawBundleHandle.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 原生资源包句柄 /// - internal class RawBundleHandle : IBundleHandle + internal sealed class RawBundleHandle : IBundleHandle { private readonly string _bundleFilePath; private readonly PackageBundle _packageBundle; @@ -19,6 +19,12 @@ namespace YooAsset get { return _bundleFilePath; } } + /// + /// 创建原生资源包句柄实例 + /// + /// 资源包文件的本地路径 + /// 资源包描述 + /// 已加载的原生资源包数据对象 public RawBundleHandle(string bundleFilePath, PackageBundle packageBundle, RawBundle rawBundle) { _bundleFilePath = bundleFilePath; diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawFileObject.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawFileObject.cs index bfd16c77..dfb59266 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawFileObject.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/RawBundleHandle/RawFileObject.cs @@ -1,10 +1,11 @@ +using System; using System.Text; using UnityEngine; namespace YooAsset { /// - /// 用于访问原生文件字节数据及文本内容的对象 + /// 原生文件对象 /// public class RawFileObject : ScriptableObject { @@ -12,36 +13,69 @@ namespace YooAsset private string _fileText; /// - /// 原生文件的字节数据 + /// 获取原生文件的字节数据 /// - public byte[] Bytes => _fileBytes; - - /// - /// 以UTF-8编码解析得到的文本内容 - /// - public string Text + /// 原生文件字节数据的副本 + public byte[] GetBytes() { - get - { - if (_fileBytes == null || _fileBytes.Length == 0) - return null; - - if (string.IsNullOrEmpty(_fileText)) - _fileText = Encoding.UTF8.GetString(_fileBytes); - return _fileText; - } + if (_fileBytes == null) + return null; + var copy = new byte[_fileBytes.Length]; + System.Buffer.BlockCopy(_fileBytes, 0, copy, 0, _fileBytes.Length); + return copy; } /// - /// 根据字节数据创建原生文件对象实例 + /// 获取以 UTF-8 编码解析的文本内容 + /// + /// 解析后的文本字符串 + public string GetText() + { + if (_fileBytes == null || _fileBytes.Length == 0) + return null; + + if (string.IsNullOrEmpty(_fileText)) + _fileText = Encoding.UTF8.GetString(_fileBytes); + return _fileText; + } + +#if UNITY_2021_2_OR_NEWER + /// + /// 获取原生文件的只读字节数据 + /// + /// + /// 返回的数据直接引用内部数组,调用方不应在资源包卸载后继续使用。 + /// + /// 原生文件的只读字节数据 + public ReadOnlySpan GetBytesAsReadOnlySpan() + { + if (_fileBytes == null) + return ReadOnlySpan.Empty; + return new ReadOnlySpan(_fileBytes); + } +#endif + + /// + /// 释放内部持有的字节数据和文本缓存 + /// + internal void Release() + { + _fileBytes = null; + _fileText = null; + } + + /// + /// 创建基于指定字节数据的原生文件对象实例 /// /// 原生文件的字节数据 /// 创建得到的原生文件对象 - public static RawFileObject CreateFromBytes(byte[] bytes) + internal static RawFileObject CreateFromBytes(byte[] bytes) { + if (bytes == null) + throw new ArgumentNullException(nameof(bytes)); var obj = CreateInstance(); obj._fileBytes = bytes; return obj; } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAllAssetsOperation.cs index b20d40e5..e4d57572 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAllAssetsOperation.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 虚拟资源包的加载所有资源操作 + /// 通过 AssetDatabase 加载全部资源对象(仅编辑器模式) /// - internal class VBHLoadAllAssetsOperation : BHLoadAllAssetsOperation + internal sealed class VBHLoadAllAssetsOperation : BHLoadAllAssetsOperation { - protected enum ESteps + private enum ESteps { None, CheckBundle, @@ -20,6 +20,11 @@ namespace YooAsset private readonly AssetInfo _assetInfo; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 待加载资源信息 public VBHLoadAllAssetsOperation(PackageBundle packageBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -47,8 +52,8 @@ namespace YooAsset if (string.IsNullOrEmpty(guid)) { _steps = ESteps.Done; - SetError($"Asset not found: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Asset not found: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); return; } @@ -90,13 +95,13 @@ namespace YooAsset { string error; if (_assetInfo.AssetType == null) - error = $"Failed to load all assets: {_assetInfo.AssetPath} AssetType: null"; + error = $"Failed to load all assets: '{_assetInfo.AssetPath}' AssetType: null."; else - error = $"Failed to load all assets: {_assetInfo.AssetPath} AssetType: {_assetInfo.AssetType}"; + error = $"Failed to load all assets: '{_assetInfo.AssetPath}' AssetType: {_assetInfo.AssetType}."; _steps = ESteps.Done; SetError(error); - YooLogger.Error(error); + YooLogger.LogError(error); } else { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAssetOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAssetOperation.cs index 73700914..230ae9c5 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAssetOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadAssetOperation.cs @@ -2,11 +2,11 @@ namespace YooAsset { /// - /// 虚拟资源包的加载单个资源操作 + /// 通过 AssetDatabase 加载单个资源对象(仅编辑器模式) /// - internal class VBHLoadAssetOperation : BHLoadAssetOperation + internal sealed class VBHLoadAssetOperation : BHLoadAssetOperation { - protected enum ESteps + private enum ESteps { None, CheckBundle, @@ -19,6 +19,11 @@ namespace YooAsset private readonly AssetInfo _assetInfo; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 待加载资源信息 public VBHLoadAssetOperation(PackageBundle packageBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -46,8 +51,8 @@ namespace YooAsset if (string.IsNullOrEmpty(guid)) { _steps = ESteps.Done; - SetError($"Asset not found: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Asset not found: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); return; } @@ -69,13 +74,13 @@ namespace YooAsset { string error; if (_assetInfo.AssetType == null) - error = $"Failed to load asset object: {_assetInfo.AssetPath} AssetType: null"; + error = $"Failed to load asset: '{_assetInfo.AssetPath}' AssetType: null."; else - error = $"Failed to load asset object: {_assetInfo.AssetPath} AssetType: {_assetInfo.AssetType}"; + error = $"Failed to load asset: '{_assetInfo.AssetPath}' AssetType: {_assetInfo.AssetType}."; _steps = ESteps.Done; SetError(error); - YooLogger.Error(error); + YooLogger.LogError(error); } else { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSceneOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSceneOperation.cs index 9a720d0b..4f807cc9 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSceneOperation.cs @@ -4,11 +4,11 @@ using UnityEngine.SceneManagement; namespace YooAsset { /// - /// 虚拟资源包的场景加载操作 + /// 通过 EditorSceneManager 加载场景资源(仅编辑器模式) /// - internal class VBHLoadSceneOperation : BHLoadSceneOperation + internal sealed class VBHLoadSceneOperation : BHLoadSceneOperation { - protected enum ESteps + private enum ESteps { None, LoadScene, @@ -17,15 +17,21 @@ namespace YooAsset } private readonly AssetInfo _assetInfo; - private readonly LoadSceneParameters _loadParams; + private readonly LoadSceneParameters _loadSceneParams; private bool _allowSceneActivation; private AsyncOperation _asyncOperation; private ESteps _steps = ESteps.None; - public VBHLoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool allowSceneActivation) + /// + /// 创建实例 + /// + /// 待加载场景信息 + /// 控制场景加载的选项 + /// 是否允许场景在加载完成后立即激活 + public VBHLoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool allowSceneActivation) { _assetInfo = assetInfo; - _loadParams = loadParams; + _loadSceneParams = loadSceneParams; _allowSceneActivation = allowSceneActivation; } protected override void InternalStart() @@ -47,12 +53,12 @@ namespace YooAsset { if (IsWaitForCompletion) { - Result = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneInPlayMode(_assetInfo.AssetPath, _loadParams); + Result = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneInPlayMode(_assetInfo.AssetPath, _loadSceneParams); _steps = ESteps.CheckResult; } else { - _asyncOperation = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(_assetInfo.AssetPath, _loadParams); + _asyncOperation = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(_assetInfo.AssetPath, _loadSceneParams); if (_asyncOperation != null) { _asyncOperation.allowSceneActivation = _allowSceneActivation; @@ -63,9 +69,8 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"Failed to load scene: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); - return; + SetError($"Failed to load scene: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); } } } @@ -77,7 +82,7 @@ namespace YooAsset if (IsWaitForCompletion) { // 注意:场景加载无法强制异步转同步 - YooLogger.Error("The scene is already loading asynchronously."); + YooLogger.LogError("The scene is already loading asynchronously."); } else { @@ -102,8 +107,8 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"The loaded scene is invalid: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Loaded scene is invalid: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); } } #endif @@ -113,7 +118,7 @@ namespace YooAsset //注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法! ExecuteOnce(); } - public override void AllowSceneActivation() + protected override void InternalAllowSceneActivation() { _allowSceneActivation = true; } diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSubAssetsOperation.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSubAssetsOperation.cs index e60b3d21..2eadb12a 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSubAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/Operations/VBHLoadSubAssetsOperation.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 虚拟资源包的加载子资源操作 + /// 通过 AssetDatabase 加载指定资源的全部子资源对象(仅编辑器模式) /// - internal class VBHLoadSubAssetsOperation : BHLoadSubAssetsOperation + internal sealed class VBHLoadSubAssetsOperation : BHLoadSubAssetsOperation { - protected enum ESteps + private enum ESteps { None, CheckBundle, @@ -20,6 +20,11 @@ namespace YooAsset private readonly AssetInfo _assetInfo; private ESteps _steps = ESteps.None; + /// + /// 创建实例 + /// + /// 资源包描述 + /// 待加载资源信息 public VBHLoadSubAssetsOperation(PackageBundle packageBundle, AssetInfo assetInfo) { _packageBundle = packageBundle; @@ -47,8 +52,8 @@ namespace YooAsset if (string.IsNullOrEmpty(guid)) { _steps = ESteps.Done; - SetError($"Asset not found: {_assetInfo.AssetPath}"); - YooLogger.Error(Error); + SetError($"Asset not found: '{_assetInfo.AssetPath}'."); + YooLogger.LogError(Error); return; } @@ -81,13 +86,13 @@ namespace YooAsset { string error; if (_assetInfo.AssetType == null) - error = $"Failed to load sub-assets: {_assetInfo.AssetPath} AssetType: null"; + error = $"Failed to load sub-assets: '{_assetInfo.AssetPath}' AssetType: null."; else - error = $"Failed to load sub-assets: {_assetInfo.AssetPath} AssetType: {_assetInfo.AssetType}"; + error = $"Failed to load sub-assets: '{_assetInfo.AssetPath}' AssetType: {_assetInfo.AssetType}."; _steps = ESteps.Done; SetError(error); - YooLogger.Error(error); + YooLogger.LogError(error); } else { diff --git a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/VirtualBundleHandle.cs b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/VirtualBundleHandle.cs index bdc88d4c..19fcfc19 100644 --- a/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/VirtualBundleHandle.cs +++ b/Assets/YooAsset/Runtime/BundleHandle/Services/VirtualBundleHandle/VirtualBundleHandle.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 虚拟资源包句柄 /// - internal class VirtualBundleHandle : IBundleHandle + internal sealed class VirtualBundleHandle : IBundleHandle { private readonly string _bundleFilePath; private readonly PackageBundle _packageBundle; @@ -18,6 +18,11 @@ namespace YooAsset get { return _bundleFilePath; } } + /// + /// 创建虚拟资源包句柄实例 + /// + /// 资源包文件的本地路径 + /// 资源包描述 public VirtualBundleHandle(string bundleFilePath, PackageBundle packageBundle) { _bundleFilePath = bundleFilePath; @@ -25,7 +30,7 @@ namespace YooAsset } /// - /// 虚拟资源包无需执行实际卸载操作 + /// 释放虚拟资源包(无需执行实际卸载操作) /// public void UnloadBundle() { diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticBehaviour.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticBehaviour.cs index 9fc67047..a08122da 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticBehaviour.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticBehaviour.cs @@ -8,7 +8,7 @@ namespace YooAsset /// 诊断行为组件 /// /// - /// 负责接收 Editor 命令并发送诊断数据。 + /// 负责接收 Editor 命令并发送诊断数据 /// internal class DiagnosticBehaviour : MonoBehaviour { @@ -16,13 +16,13 @@ namespace YooAsset [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void OnRuntimeInitialize() { - _sampleOnce = false; - _autoSampling = false; + s_sampleOnce = false; + s_autoSampling = false; } #endif - private static bool _sampleOnce = false; - private static bool _autoSampling = false; + private static bool s_sampleOnce = false; + private static bool s_autoSampling = false; private void Awake() { @@ -48,9 +48,9 @@ namespace YooAsset } private void LateUpdate() { - if (_autoSampling || _sampleOnce) + if (s_autoSampling || s_sampleOnce) { - _sampleOnce = false; + s_sampleOnce = false; var debugReport = YooAssets.GetDiagnosticReport(); var data = DiagnosticReport.Serialize(debugReport); @@ -65,22 +65,22 @@ namespace YooAsset private static void HandleEditorMessage(MessageEventArgs args) { var command = DiagnosticCommand.Deserialize(args.data); - YooLogger.Log($"[{nameof(DiagnosticBehaviour)}] Handle command: Type={command.CommandType}, Param={command.Parameter}"); - if (command.CommandType == (int)EDiagnosticCommandType.SampleOnce) + YooLogger.Log($"[{nameof(DiagnosticBehaviour)}] Received command: Type={command.CommandType}, Param='{command.Parameter}'."); + if (command.CommandType == EDiagnosticCommandType.SampleOnce) { - _sampleOnce = true; + s_sampleOnce = true; } - else if (command.CommandType == (int)EDiagnosticCommandType.AutoSampling) + else if (command.CommandType == EDiagnosticCommandType.AutoSampling) { - if (command.Parameter == "open") - _autoSampling = true; + if (command.Parameter == DiagnosticSystemConsts.AutoSamplingOpen) + s_autoSampling = true; else - _autoSampling = false; + s_autoSampling = false; } else { - YooLogger.Warning($"Unknown diagnostic command type: {command.CommandType}."); + YooLogger.LogWarning($"Unknown diagnostic command type: {command.CommandType}."); } } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticCommand.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticCommand.cs index a7a68d8c..cd14844a 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticCommand.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticCommand.cs @@ -8,7 +8,7 @@ namespace YooAsset /// 诊断命令 /// /// - /// 用于 Editor 向 Player 发送诊断指令。 + /// 用于 Editor 向 Player 发送诊断指令 /// [Serializable] internal class DiagnosticCommand @@ -16,14 +16,13 @@ namespace YooAsset /// /// 命令类型 /// - public int CommandType; + public EDiagnosticCommandType CommandType; /// /// 命令附加参数 /// public string Parameter; - /// /// 序列化命令为字节数组 /// @@ -44,4 +43,4 @@ namespace YooAsset return JsonUtility.FromJson(Encoding.UTF8.GetString(data)); } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticBundleInfo.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticBundleInfo.cs index 8c66b18d..a7fd44cb 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticBundleInfo.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticBundleInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; namespace YooAsset @@ -8,7 +7,7 @@ namespace YooAsset /// 描述资源包的运行时诊断信息 /// [Serializable] - internal struct DiagnosticBundleInfo : IComparer, IComparable + internal class DiagnosticBundleInfo : IComparable { /// /// 资源包名称 @@ -30,13 +29,10 @@ namespace YooAsset /// public List Referencers; + /// public int CompareTo(DiagnosticBundleInfo other) { - return Compare(this, other); - } - public int Compare(DiagnosticBundleInfo a, DiagnosticBundleInfo b) - { - return string.CompareOrdinal(a.BundleName, b.BundleName); + return string.CompareOrdinal(BundleName, other.BundleName); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticOperationInfo.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticOperationInfo.cs index a830efb1..afca831e 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticOperationInfo.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticOperationInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; namespace YooAsset @@ -8,7 +7,7 @@ namespace YooAsset /// 描述异步操作的运行时诊断信息 /// [Serializable] - internal class DiagnosticOperationInfo : IComparer, IComparable + internal class DiagnosticOperationInfo : IComparable { /// /// 异步操作的名称 @@ -49,19 +48,14 @@ namespace YooAsset /// 子任务列表 /// /// - /// TODO:序列化深度限制为10层。 + /// TODO:序列化深度限制为10层 /// public List Children; /// public int CompareTo(DiagnosticOperationInfo other) { - return Compare(this, other); - } - /// - public int Compare(DiagnosticOperationInfo a, DiagnosticOperationInfo b) - { - return string.CompareOrdinal(a.OperationName, b.OperationName); + return string.CompareOrdinal(OperationName, other.OperationName); } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs index 444dbafe..27530d51 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; namespace YooAsset @@ -34,31 +33,26 @@ namespace YooAsset public List OperationInfos = new List(1000); /// - /// 获取资源包的诊断信息 + /// 尝试获取资源包的诊断信息 /// - public DiagnosticBundleInfo GetBundleInfo(string bundleName) + /// 资源包名称 + /// 找到时返回对应的诊断信息 + /// 是否成功找到 + public bool TryGetBundleInfo(string bundleName, out DiagnosticBundleInfo bundleInfo) { if (_isParsed == false) { _isParsed = true; - foreach (var bundleInfo in BundleInfos) + foreach (var info in BundleInfos) { - if (_bundleInfoDict.ContainsKey(bundleInfo.BundleName) == false) + if (_bundleInfoDict.ContainsKey(info.BundleName) == false) { - _bundleInfoDict.Add(bundleInfo.BundleName, bundleInfo); + _bundleInfoDict.Add(info.BundleName, info); } } } - if (_bundleInfoDict.TryGetValue(bundleName, out DiagnosticBundleInfo value)) - { - return value; - } - else - { - YooLogger.Error($"[{nameof(DiagnosticPackageData)}] Bundle info not found: '{bundleName}'."); - return default; - } + return _bundleInfoDict.TryGetValue(bundleName, out bundleInfo); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticProviderInfo.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticProviderInfo.cs index fbe99811..c2f3d3c2 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticProviderInfo.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticProviderInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; namespace YooAsset @@ -8,7 +7,7 @@ namespace YooAsset /// 描述资源加载的运行时诊断信息 /// [Serializable] - internal struct DiagnosticProviderInfo : IComparer, IComparable + internal class DiagnosticProviderInfo : IComparable { /// /// 资源对象路径 @@ -19,7 +18,7 @@ namespace YooAsset /// 资源加载时的活跃场景名称 /// public string SceneName; - + /// /// 资源加载开始时间 /// @@ -45,13 +44,10 @@ namespace YooAsset /// public List Dependencies; + /// public int CompareTo(DiagnosticProviderInfo other) { - return Compare(this, other); - } - public int Compare(DiagnosticProviderInfo a, DiagnosticProviderInfo b) - { - return string.CompareOrdinal(a.AssetPath, b.AssetPath); + return string.CompareOrdinal(AssetPath, other.AssetPath); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticReport.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticReport.cs index 17c0f343..48872283 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticReport.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticReport.cs @@ -1,7 +1,6 @@ -using System; -using System.Text; -using System.Collections; +using System; using System.Collections.Generic; +using System.Text; using UnityEngine; namespace YooAsset @@ -27,10 +26,10 @@ namespace YooAsset /// public List PackageDataList = new List(10); - /// /// 创建新的诊断报告 /// + /// 已初始化协议版本和帧号的诊断报告 public static DiagnosticReport Create() { var report = new DiagnosticReport(); @@ -59,4 +58,4 @@ namespace YooAsset return JsonUtility.FromJson(Encoding.UTF8.GetString(data)); } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticSystemConsts.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticSystemConsts.cs index 00831632..0a3f3566 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticSystemConsts.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticSystemConsts.cs @@ -1,11 +1,11 @@ -using System; +using System; namespace YooAsset { /// /// 诊断系统的常量定义 /// - internal class DiagnosticSystemConsts + internal static class DiagnosticSystemConsts { /// /// 通信协议版本号 @@ -21,5 +21,10 @@ namespace YooAsset /// Editor 向 Player 发送消息的标识符 /// public static readonly Guid EditorToPlayerMessageId = new Guid("4d1926c9df5b052469a1c63448b7609a"); + + /// + /// 自动采样开启参数值 + /// + public const string AutoSamplingOpen = "open"; } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/EDiagnosticCommandType.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/EDiagnosticCommandType.cs index d43a01bc..5d16da5f 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/EDiagnosticCommandType.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/EDiagnosticCommandType.cs @@ -1,4 +1,4 @@ - + namespace YooAsset { /// @@ -6,14 +6,19 @@ namespace YooAsset /// internal enum EDiagnosticCommandType { + /// + /// 未指定命令 + /// + None = 0, + /// /// 采样一次 /// - SampleOnce = 0, + SampleOnce = 1, /// /// 持续采样 /// - AutoSampling = 1, + AutoSampling = 2, } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/MockEditorConnection.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/MockEditorConnection.cs index 5eb6bdc1..7c785c55 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/MockEditorConnection.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/MockEditorConnection.cs @@ -12,17 +12,19 @@ namespace YooAsset /// /// 在 Editor 模式下模拟 EditorConnection 的行为,用于本地调试。 /// - internal class MockEditorConnection + internal sealed class MockEditorConnection { + private MockEditorConnection() { } + #if UNITY_EDITOR [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void OnRuntimeInitialize() { - _instance = null; + s_instance = null; } #endif - private static MockEditorConnection _instance; + private static MockEditorConnection s_instance; /// /// 单例实例 @@ -31,9 +33,9 @@ namespace YooAsset { get { - if (_instance == null) - _instance = new MockEditorConnection(); - return _instance; + if (s_instance == null) + s_instance = new MockEditorConnection(); + return s_instance; } } @@ -50,52 +52,59 @@ namespace YooAsset /// /// 注册消息处理回调 /// - /// 消息标识符 + /// 消息标识符 /// 收到消息时的回调函数 - public void Register(Guid messageID, UnityAction callback) + public void Register(Guid messageId, UnityAction callback) { - if (messageID == Guid.Empty) - throw new ArgumentException("Message ID cannot be empty.", nameof(messageID)); + if (messageId == Guid.Empty) + throw new ArgumentException("Message ID cannot be empty.", nameof(messageId)); + if (callback == null) + throw new ArgumentNullException(nameof(callback)); - if (_messageHandlers.ContainsKey(messageID) == false) - _messageHandlers.Add(messageID, callback); + if (_messageHandlers.ContainsKey(messageId)) + _messageHandlers[messageId] += callback; else - YooLogger.Warning($"Message handler already registered for ID: '{messageID}'."); + _messageHandlers[messageId] = callback; } /// /// 注销消息处理回调 /// - /// 消息标识符 + /// 消息标识符 /// 要注销的回调函数 - public void Unregister(Guid messageID, UnityAction callback) + public void Unregister(Guid messageId, UnityAction callback) { - if (_messageHandlers.ContainsKey(messageID)) - _messageHandlers.Remove(messageID); + if (_messageHandlers.ContainsKey(messageId)) + { + _messageHandlers[messageId] -= callback; + if (_messageHandlers[messageId] == null) + _messageHandlers.Remove(messageId); + } } /// /// 向 Player 端发送消息 /// - /// 消息标识符 + /// 消息标识符 /// 消息数据 - public void Send(Guid messageID, byte[] data) + public void Send(Guid messageId, byte[] data) { - if (messageID == Guid.Empty) - throw new ArgumentException("Message ID cannot be empty.", nameof(messageID)); + if (messageId == Guid.Empty) + throw new ArgumentException("Message ID cannot be empty.", nameof(messageId)); + if (data == null) + throw new ArgumentNullException(nameof(data)); - // 接收对方的消息 - MockPlayerConnection.Instance.HandleEditorMessage(messageID, data); + MockPlayerConnection.Instance.HandleEditorMessage(messageId, data); } /// /// 处理来自 Player 端的消息 /// - /// 消息标识符 + /// 消息标识符 /// 消息数据 - internal void HandlePlayerMessage(Guid messageID, byte[] data) + internal void HandlePlayerMessage(Guid messageId, byte[] data) { - if (_messageHandlers.TryGetValue(messageID, out UnityAction value)) + if (_messageHandlers.TryGetValue(messageId, out UnityAction value)) { var args = new MessageEventArgs(); args.playerId = 0; diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/MockPlayerConnection.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/MockPlayerConnection.cs index 5e4cf185..83365bf9 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/MockPlayerConnection.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/MockPlayerConnection.cs @@ -12,17 +12,19 @@ namespace YooAsset /// /// 在 Editor 模式下模拟 PlayerConnection 的行为,用于本地调试。 /// - internal class MockPlayerConnection + internal sealed class MockPlayerConnection { + private MockPlayerConnection() { } + #if UNITY_EDITOR [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void OnRuntimeInitialize() { - _instance = null; + s_instance = null; } #endif - private static MockPlayerConnection _instance; + private static MockPlayerConnection s_instance; /// /// 单例实例 @@ -31,9 +33,9 @@ namespace YooAsset { get { - if (_instance == null) - _instance = new MockPlayerConnection(); - return _instance; + if (s_instance == null) + s_instance = new MockPlayerConnection(); + return s_instance; } } @@ -50,52 +52,59 @@ namespace YooAsset /// /// 注册消息处理回调 /// - /// 消息标识符 + /// 消息标识符 /// 收到消息时的回调函数 - public void Register(Guid messageID, UnityAction callback) + public void Register(Guid messageId, UnityAction callback) { - if (messageID == Guid.Empty) - throw new ArgumentException("Message ID cannot be empty.", nameof(messageID)); + if (messageId == Guid.Empty) + throw new ArgumentException("Message ID cannot be empty.", nameof(messageId)); + if (callback == null) + throw new ArgumentNullException(nameof(callback)); - if (_messageHandlers.ContainsKey(messageID) == false) - _messageHandlers.Add(messageID, callback); + if (_messageHandlers.ContainsKey(messageId)) + _messageHandlers[messageId] += callback; else - YooLogger.Warning($"Message handler already registered for ID: '{messageID}'."); + _messageHandlers[messageId] = callback; } /// /// 注销消息处理回调 /// - /// 消息标识符 + /// 消息标识符 /// 要注销的回调函数 - public void Unregister(Guid messageID, UnityAction callback) + public void Unregister(Guid messageId, UnityAction callback) { - if (_messageHandlers.ContainsKey(messageID)) - _messageHandlers.Remove(messageID); + if (_messageHandlers.ContainsKey(messageId)) + { + _messageHandlers[messageId] -= callback; + if (_messageHandlers[messageId] == null) + _messageHandlers.Remove(messageId); + } } /// /// 向 Editor 端发送消息 /// - /// 消息标识符 + /// 消息标识符 /// 消息数据 - public void Send(Guid messageID, byte[] data) + public void Send(Guid messageId, byte[] data) { - if (messageID == Guid.Empty) - throw new ArgumentException("Message ID cannot be empty.", nameof(messageID)); + if (messageId == Guid.Empty) + throw new ArgumentException("Message ID cannot be empty.", nameof(messageId)); + if (data == null) + throw new ArgumentNullException(nameof(data)); - // 接收对方的消息 - MockEditorConnection.Instance.HandlePlayerMessage(messageID, data); + MockEditorConnection.Instance.HandlePlayerMessage(messageId, data); } /// /// 处理来自 Editor 端的消息 /// - /// 消息标识符 + /// 消息标识符 /// 消息数据 - internal void HandleEditorMessage(Guid messageID, byte[] data) + internal void HandleEditorMessage(Guid messageId, byte[] data) { - if (_messageHandlers.TryGetValue(messageID, out UnityAction value)) + if (_messageHandlers.TryGetValue(messageId, out UnityAction value)) { var args = new MessageEventArgs(); args.playerId = 0; diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloadReport.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadReport.cs index 6b7ad970..e2391d74 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/DownloadReport.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloadReport.cs @@ -54,20 +54,28 @@ namespace YooAsset /// 不含 HTTP 状态信息的进度报告 public static DownloadReport CreateProgress(long downloadedBytes, float downloadProgress) { - return new DownloadReport(0, null, downloadedBytes, downloadProgress); + return new DownloadReport( + httpCode: 0, + httpError: null, + downloadedBytes: downloadedBytes, + downloadProgress: downloadProgress); } /// /// 创建包含 HTTP 状态的最终报告(成功或失败) /// /// HTTP 响应状态码 - /// HTTP 错误信息,成功时为 null + /// HTTP 错误信息,成功时为 null。 /// 已下载的字节数 /// 下载进度,取值范围 0f ~ 1f /// 包含完整 HTTP 状态信息的最终报告 public static DownloadReport CreateFinished(long httpCode, string httpError, long downloadedBytes, float downloadProgress) { - return new DownloadReport(httpCode, httpError, downloadedBytes, downloadProgress); + return new DownloadReport( + httpCode: httpCode, + httpError: httpError, + downloadedBytes: downloadedBytes, + downloadProgress: downloadProgress); } } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloadRequestArgs.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadRequestArgs.cs index 564d9dde..c5210b22 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/DownloadRequestArgs.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloadRequestArgs.cs @@ -11,7 +11,7 @@ namespace YooAsset /// /// 请求地址 /// - public readonly string Url; + public string Url { get; } /// /// 响应的超时时间(单位:秒) @@ -19,28 +19,28 @@ namespace YooAsset /// /// 当 Timeout 设置为 0 时,不应用超时。 /// - public readonly int Timeout; + public int Timeout { get; } /// /// 看门狗超时时间(单位:秒) /// /// - /// 用于监控下载任务的数据接收情况。 - /// 当设置值为 0 时,表示禁用看门狗监控。 + /// 用于监控下载任务的数据接收情况 + /// 当设置值为 0 时,表示禁用看门狗监控。 /// - public readonly int WatchdogTimeout; + public int WatchdogTimeout { get; } /// /// 自定义请求头(可选) /// - public readonly IReadOnlyDictionary Headers; + public IReadOnlyDictionary Headers { get; } /// /// 构造下载请求公共参数 /// /// 请求地址 - /// 响应超时时间(秒),0 表示不应用超时 - /// 看门狗超时时间(秒),0 表示禁用 + /// 响应超时时间(秒),0 表示不应用超时。 + /// 看门狗超时时间(秒),0 表示禁用。 /// 自定义请求头(可选) public DownloadRequestArgs(string url, int timeout, int watchdogTimeout, IReadOnlyDictionary headers = null) @@ -63,12 +63,12 @@ namespace YooAsset /// /// 公共请求参数 /// - public readonly DownloadRequestArgs RequestArgs; + public DownloadRequestArgs RequestArgs { get; } /// /// 文件保存路径 /// - public readonly string SavePath; + public string SavePath { get; } /// /// 是否追加写入文件 @@ -76,12 +76,12 @@ namespace YooAsset /// /// 配合 ResumeOffset 使用,用于断点续传场景。 /// - public readonly bool AppendToFile; + public bool AppendToFile { get; } /// /// 中止请求时是否删除目标文件 /// - public readonly bool RemoveFileOnAbort; + public bool RemoveFileOnAbort { get; } /// /// 断点续传的起始字节(小于等于 0 表示不启用) @@ -89,14 +89,14 @@ namespace YooAsset /// /// 推荐由后端自动设置 Range 请求头:"bytes={ResumeOffset}-"。 /// - public readonly long ResumeOffset; + public long ResumeOffset { get; } /// /// 构造文件下载请求参数 /// /// 请求地址 - /// 响应超时时间(秒),0 表示不应用超时 - /// 看门狗超时时间(秒),0 表示禁用 + /// 响应超时时间(秒),0 表示不应用超时。 + /// 看门狗超时时间(秒),0 表示禁用。 /// 文件保存路径 /// 是否追加写入文件(用于断点续传) /// 中止时是否删除目标文件 @@ -110,9 +110,13 @@ namespace YooAsset bool appendToFile = false, bool removeFileOnAbort = true, long resumeOffset = 0, - Dictionary headers = null) + IReadOnlyDictionary headers = null) { - RequestArgs = new DownloadRequestArgs(url, timeout, watchdogTimeout, headers); + RequestArgs = new DownloadRequestArgs( + url: url, + timeout: timeout, + watchdogTimeout: watchdogTimeout, + headers: headers); SavePath = savePath; AppendToFile = appendToFile; RemoveFileOnAbort = removeFileOnAbort; @@ -131,18 +135,22 @@ namespace YooAsset /// /// 公共请求参数 /// - public readonly DownloadRequestArgs RequestArgs; + public DownloadRequestArgs RequestArgs { get; } /// /// 构造数据下载请求参数 /// /// 请求地址 - /// 响应超时时间(秒),0 表示不应用超时 - /// 看门狗超时时间(秒),0 表示禁用 + /// 响应超时时间(秒),0 表示不应用超时。 + /// 看门狗超时时间(秒),0 表示禁用。 /// 自定义请求头(可选) - public DownloadDataRequestArgs(string url, int timeout, int watchdogTimeout, Dictionary headers = null) + public DownloadDataRequestArgs(string url, int timeout, int watchdogTimeout, IReadOnlyDictionary headers = null) { - RequestArgs = new DownloadRequestArgs(url, timeout, watchdogTimeout, headers); + RequestArgs = new DownloadRequestArgs( + url: url, + timeout: timeout, + watchdogTimeout: watchdogTimeout, + headers: headers); } } @@ -157,32 +165,32 @@ namespace YooAsset /// /// 公共请求参数 /// - public readonly DownloadRequestArgs RequestArgs; + public DownloadRequestArgs RequestArgs { get; } /// /// 禁用 Unity 的网络缓存 /// - public readonly bool DisableUnityWebCache; + public bool DisableUnityWebCache { get; } /// /// AssetBundle 文件哈希(用于 UnityWebRequest 的缓存) /// /// - /// 仅当 DisableUnityWebCache 为 false 时需要。 + /// 仅当 DisableUnityWebCache 为 false 时需要 /// - public readonly string FileHash; + public string FileHash { get; } /// /// Unity CRC 校验值 /// - public readonly uint UnityCrc; + public uint UnityCrc { get; } /// /// 构造 AssetBundle 下载请求参数 /// /// 请求地址 - /// 响应超时时间(秒),0 表示不应用超时 - /// 看门狗超时时间(秒),0 表示禁用 + /// 响应超时时间(秒),0 表示不应用超时。 + /// 看门狗超时时间(秒),0 表示禁用。 /// 是否禁用 Unity 内置缓存 /// 文件哈希(启用缓存时必须提供) /// Unity CRC 校验值 @@ -194,9 +202,13 @@ namespace YooAsset bool disableUnityWebCache = true, string fileHash = null, uint unityCrc = 0, - Dictionary headers = null) + IReadOnlyDictionary headers = null) { - RequestArgs = new DownloadRequestArgs(url, timeout, watchdogTimeout, headers); + RequestArgs = new DownloadRequestArgs( + url: url, + timeout: timeout, + watchdogTimeout: watchdogTimeout, + headers: headers); DisableUnityWebCache = disableUnityWebCache; FileHash = fileHash; UnityCrc = unityCrc; @@ -207,24 +219,24 @@ namespace YooAsset /// 模拟下载请求参数 /// /// - /// 用于编辑器模式下模拟下载进度,不发起网络请求 + /// 用于编辑器模式下模拟下载进度,不发起网络请求。 /// internal readonly struct SimulatedDownloadRequestArgs { /// /// 请求地址(仅用于标识) /// - public readonly string Url; + public string Url { get; } /// /// 模拟的文件大小(字节) /// - public readonly long FileSize; + public long FileSize { get; } /// /// 模拟的下载速度(字节/秒) /// - public readonly long DownloadSpeed; + public long DownloadSpeed { get; } /// /// 构造模拟下载请求参数 @@ -239,4 +251,4 @@ namespace YooAsset DownloadSpeed = downloadSpeed > 0 ? downloadSpeed : 1024 * 1024; } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloadRetryController.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadRetryController.cs index 68918bb4..aacc3ae5 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/DownloadRetryController.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloadRetryController.cs @@ -5,7 +5,7 @@ namespace YooAsset /// 下载重试控制器 /// /// - /// 管理重试次数和重试前的等待计时,不执行实际下载 + /// 管理重试次数和重试前的等待计时,不执行实际下载。 /// internal sealed class DownloadRetryController { @@ -45,7 +45,7 @@ namespace YooAsset /// 请求地址 /// HTTP 状态码 /// HTTP 错误信息 - /// 允许重试返回 true,否则返回 false + /// 允许重试返回 true,否则返回 false。 public bool CanRetryRequest(string url, long httpCode, string httpError) { if (_retryCount >= _maxRetryCount) @@ -54,14 +54,14 @@ namespace YooAsset if (_retryPolicy.IsRetryableError(url, httpCode, httpError) == false) return false; - YooLogger.Warning($"Download request failed. URL: '{url}', HttpCode={httpCode}."); + YooLogger.LogWarning($"Download request failed. URL: '{url}', HttpCode={httpCode}."); return true; } /// /// 判断当前是否还有可用的重试次数 /// - /// 尚未达到最大重试次数返回 true,否则返回 false + /// 尚未达到最大重试次数返回 true,否则返回 false。 public bool HasRetriesRemaining() { if (_retryCount >= _maxRetryCount) @@ -78,13 +78,13 @@ namespace YooAsset _retryCount++; _retryStartTime = TimeUtility.RealtimeSinceStartup; _retryDelay = _retryPolicy.CalculateRetryDelay(_retryCount, _retryDelay); - YooLogger.Warning($"Retrying download in {RetryDelay:F1}s."); + YooLogger.LogWarning($"Retrying download in {RetryDelay:F1}s."); } /// /// 每帧推进重试等待计时 /// - /// 等待时间已到返回 true,否则返回 false + /// 等待时间已到返回 true,否则返回 false。 public bool TickRetryDelay() { return TimeUtility.RealtimeSinceStartup - _retryStartTime >= _retryDelay; diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs index fae5687a..90b07c93 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs @@ -45,7 +45,7 @@ namespace YooAsset /// 判断是否为本地文件 URL /// /// 要判断的 URL - /// 如果是本地文件 URL 返回 true,否则返回 false + /// 如果是本地文件 URL 返回 true,否则返回 false。 public static bool IsLocalFileUrl(string url) { if (string.IsNullOrEmpty(url)) diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadBackend.cs b/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadBackend.cs index b99a9e09..a5f44d7b 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadBackend.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadBackend.cs @@ -6,8 +6,8 @@ namespace YooAsset /// 下载后台接口 /// /// - /// 不同网络库(UnityWebRequest / BestHTTP / 自研)实现该接口,用于创建具体下载请求。 - /// 每个后台实例是独立的,不共享全局状态。 + /// 不同网络库(UnityWebRequest / BestHTTP / 自研)实现该接口,用于创建具体下载请求。 + /// 每个后台实例是独立的,不共享全局状态。 /// internal interface IDownloadBackend : IDisposable { @@ -20,7 +20,7 @@ namespace YooAsset /// 驱动更新 /// /// - /// 部分第三方网络库需要在 Unity 主线程中周期性调用 Update 进行驱动。 + /// 部分第三方网络库需要在 Unity 主线程中周期性调用 Update 进行驱动 /// void Update(); @@ -72,4 +72,4 @@ namespace YooAsset /// 模拟下载请求实例 IDownloadFileRequest CreateSimulateRequest(SimulatedDownloadRequestArgs args); } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadRequest.cs b/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadRequest.cs index 0f91c841..3256ab09 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadRequest.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Interfaces/IDownloadRequest.cs @@ -100,7 +100,7 @@ namespace YooAsset /// 获取响应头信息 /// /// 响应头名称(不区分大小写) - /// 响应头的值,如果不存在或请求未完成则返回 null + /// 响应头的值,如果不存在或请求未完成则返回 null。 string GetResponseHeader(string name); } diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadFileBaseOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadFileBaseOperation.cs index 5f65d9f8..8559798c 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadFileBaseOperation.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadFileBaseOperation.cs @@ -7,7 +7,7 @@ namespace YooAsset internal abstract class DownloadFileBaseOperation : AsyncOperationBase { /// - /// 资源包对象 + /// 资源包描述 /// public PackageBundle Bundle { get; } @@ -29,11 +29,11 @@ namespace YooAsset /// /// 构造文件下载操作 /// - /// 目标资源包 + /// 资源包描述 /// 下载地址 - public DownloadFileBaseOperation(PackageBundle bundle, string url) + public DownloadFileBaseOperation(PackageBundle packageBundle, string url) { - Bundle = bundle; + Bundle = packageBundle; Url = url; } protected override string InternalGetDescription() diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadSchedulerOperation.cs b/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadSchedulerOperation.cs index 1dc37b83..ad7d5488 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadSchedulerOperation.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Operations/DownloadSchedulerOperation.cs @@ -20,7 +20,7 @@ namespace YooAsset /// 调度器名称 /// /// - /// 主要用于调试信息和运行时描述输出。 + /// 主要用于调试信息和运行时描述输出 /// public string SchedulerName { get; } @@ -67,7 +67,7 @@ namespace YooAsset /// 是否暂停调度 /// /// - /// 暂停时不启动新任务,但已启动的任务继续执行 + /// 暂停时不启动新任务,但已启动的任务继续执行。 /// public bool Paused { get; private set; } = false; @@ -196,7 +196,7 @@ namespace YooAsset /// 尝试获取指定资源包对应的下载任务 /// /// 目标资源包 - /// 已存在的下载任务(自动增加引用),不存在返回 null + /// 已存在的下载任务(自动增加引用),不存在返回 null。 public DownloadFileBaseOperation TryGetDownloadOperation(PackageBundle bundle) { if (_operationMap.TryGetValue(bundle.BundleGuid, out var oldDownloader)) @@ -216,12 +216,12 @@ namespace YooAsset /// public void RegisterDownloadOperation(DownloadFileBaseOperation downloadFileOp) { - string bundleGUID = downloadFileOp.Bundle.BundleGuid; - if (_operationMap.ContainsKey(bundleGUID)) - throw new YooInternalException($"Download operation is already registered: '{bundleGUID}'."); + string bundleGuid = downloadFileOp.Bundle.BundleGuid; + if (_operationMap.ContainsKey(bundleGuid)) + throw new YooInternalException($"Download operation is already registered: '{bundleGuid}'."); AddChildOperation(downloadFileOp); - _operationMap.Add(bundleGUID, downloadFileOp); + _operationMap.Add(bundleGuid, downloadFileOp); _operationList.Add(downloadFileOp); downloadFileOp.Reference(); } diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadRetryPolicy.cs b/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadRetryPolicy.cs index 6c64c86e..f55c983b 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadRetryPolicy.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadRetryPolicy.cs @@ -16,7 +16,7 @@ namespace YooAsset /// 失败请求的 URL /// HTTP 响应状态码 /// HTTP 错误信息 - /// 如果该错误可以重试则返回 true,否则返回 false + /// 如果该错误可以重试则返回 true,否则返回 false。 public bool IsRetryableError(string url, long httpCode, string httpError) { // HTTP 状态码 @@ -52,7 +52,7 @@ namespace YooAsset /// 上一次的等待时长(秒) /// 本次重试前的等待时长(秒) /// - /// 线性退避:每次在上一次基础上 +1 秒,上限 10 秒 + /// 线性退避:每次在上一次基础上 +1 秒,上限 10 秒。 /// public float CalculateRetryDelay(int retryCount, float previousDelay) { diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadUrlPolicy.cs b/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadUrlPolicy.cs index 4e08c8bb..e97e4de7 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadUrlPolicy.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Policies/DefaultDownloadUrlPolicy.cs @@ -6,8 +6,8 @@ namespace YooAsset /// 默认的 URL 选择策略 /// /// - /// 失败时递增计数并轮转到下一个候选 URL,成功时保持粘滞在当前可用的 URL 上。 - /// 策略实例随 FileSystem 重建时自动重置。 + /// 失败时递增计数并轮转到下一个候选 URL,成功时保持粘滞在当前可用的 URL 上。 + /// 策略实例随 FileSystem 重建时自动重置 /// public class DefaultDownloadUrlPolicy : IDownloadUrlPolicy { @@ -28,7 +28,7 @@ namespace YooAsset } /// - /// 请求成功反馈,保持当前 URL 不变 + /// 请求成功反馈,保持当前 URL 不变。 /// /// 成功请求的 URL public void OnRequestSucceeded(string url) @@ -36,7 +36,7 @@ namespace YooAsset } /// - /// 请求失败反馈,递增失败计数以切换 URL + /// 请求失败反馈,递增失败计数以切换 URL。 /// /// 失败请求的 URL /// HTTP 响应状态码 @@ -46,4 +46,4 @@ namespace YooAsset _failureCount++; } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestBackend.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestBackend.cs index 177e207e..0a2e3fef 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestBackend.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestBackend.cs @@ -6,8 +6,8 @@ namespace YooAsset /// UnityWebRequest 下载后台 /// /// - /// 基于 Unity 内置 UnityWebRequest 实现的下载后台。 - /// 支持自定义 UnityWebRequest 创建方式,例如添加证书验证、代理设置等。 + /// 基于 Unity 内置 UnityWebRequest 实现的下载后台 + /// 支持自定义 UnityWebRequest 创建方式,例如添加证书验证、代理设置等。 /// internal sealed class UnityWebRequestBackend : IDownloadBackend { @@ -17,7 +17,7 @@ namespace YooAsset private readonly UnityWebRequestCreator _webRequestCreator; /// - /// 后端名称 + /// 后台名称 /// public string Name { @@ -35,7 +35,7 @@ namespace YooAsset /// 创建 UnityWebRequest 下载后端 /// /// - /// 自定义 UnityWebRequest 创建委托(可选)。 + /// 自定义 UnityWebRequest 创建委托(可选) /// 如果为 null,则使用默认的 UnityWebRequest 构造方式。 /// public UnityWebRequestBackend(UnityWebRequestCreator webRequestCreator) @@ -121,4 +121,4 @@ namespace YooAsset return new SimulatedFileRequest(args); } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestCreator.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestCreator.cs index dca8a8f9..59e6c8eb 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestCreator.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebBackend/UnityWebRequestCreator.cs @@ -6,11 +6,11 @@ namespace YooAsset /// 自定义 UnityWebRequest 创建委托 /// /// - /// 用于自定义 UnityWebRequest 的创建方式,例如添加证书验证、代理设置等。 - /// 通过 UnityWebRequestBackend 构造函数传入。 + /// 用于自定义 UnityWebRequest 的创建方式,例如添加证书验证、代理设置等。 + /// 通过 UnityWebRequestBackend 构造函数传入 /// /// 请求地址 /// HTTP 方法(如 GET、HEAD) /// 自定义配置的 UnityWebRequest 实例 public delegate UnityWebRequest UnityWebRequestCreator(string url, string method); -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/SimulatedFileRequest.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/SimulatedFileRequest.cs index 2d6bf811..8836bb30 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/SimulatedFileRequest.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/SimulatedFileRequest.cs @@ -6,8 +6,8 @@ namespace YooAsset /// 模拟下载器 /// /// - /// 用于编辑器模式下模拟下载进度,不进行实际网络请求。 - /// 根据配置的下载速度模拟进度变化。 + /// 用于编辑器模式下模拟下载进度,不进行实际网络请求。 + /// 根据配置的下载速度模拟进度变化 /// internal sealed class SimulatedFileRequest : IDownloadFileRequest { @@ -157,4 +157,4 @@ namespace YooAsset } } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestAssetBundle.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestAssetBundle.cs index ab7ed8b0..faa5604d 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestAssetBundle.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestAssetBundle.cs @@ -8,8 +8,8 @@ namespace YooAsset /// UnityWebRequest AssetBundle 下载器 /// /// - /// 下载并加载 Unity AssetBundle 资源包。 - /// 支持 Unity 内置缓存机制和 CRC 校验。 + /// 下载并加载 Unity AssetBundle 资源包 + /// 支持 Unity 内置缓存机制和 CRC 校验 /// internal sealed class UnityWebRequestAssetBundle : UnityWebRequestBase, IDownloadAssetBundleRequest { @@ -39,7 +39,6 @@ namespace YooAsset _args = args; } - /// protected override UnityWebRequest CreateWebRequest() { _downloadHandler = CreateAssetBundleDownloadHandler(); @@ -49,7 +48,6 @@ namespace YooAsset return request; } - /// protected override void OnRequestSucceeded(UnityWebRequest webRequest) { Result = _downloadHandler.assetBundle; @@ -59,8 +57,8 @@ namespace YooAsset /// 创建 AssetBundle 下载处理器 /// /// - /// 根据 DisableUnityWebCache 配置决定是否使用 Unity 内置缓存。 - /// 启用缓存时需要提供有效的 FileHash。 + /// 根据 DisableUnityWebCache 配置决定是否使用 Unity 内置缓存 + /// 启用缓存时需要提供有效的 FileHash /// private DownloadHandlerAssetBundle CreateAssetBundleDownloadHandler() { @@ -85,4 +83,4 @@ namespace YooAsset return handler; } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBase.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBase.cs index b5000280..1c540834 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBase.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBase.cs @@ -8,8 +8,8 @@ namespace YooAsset /// UnityWebRequest 下载器基类 /// /// - /// 封装 UnityWebRequest 的通用下载逻辑,包括状态管理、进度追踪等。 - /// 子类只需实现 CreateWebRequest 方法来创建特定类型的下载请求。 + /// 封装 UnityWebRequest 的通用下载逻辑,包括状态管理、进度追踪等。 + /// 子类只需实现 CreateWebRequest 方法来创建特定类型的下载请求 /// internal abstract class UnityWebRequestBase : IDownloadRequest { @@ -117,8 +117,8 @@ namespace YooAsset /// 发起请求 /// /// - /// 仅在 Status 为 None 时生效,重复调用无效。 - /// 调用后 Status 变为 Running。 + /// 仅在 Status 为 None 时生效,重复调用无效。 + /// 调用后 Status 变为 Running /// public void SendRequest() { @@ -192,7 +192,7 @@ namespace YooAsset /// /// 请求成功时的回调(子类可重写) /// - /// 已完成的 UnityWebRequest 实例,可用于读取响应数据 + /// 已完成的 UnityWebRequest 实例,可用于读取响应数据。 protected virtual void OnRequestSucceeded(UnityWebRequest webRequest) { } @@ -200,7 +200,7 @@ namespace YooAsset /// /// 请求失败时的回调(子类可重写) /// - /// 已完成的 UnityWebRequest 实例,可用于读取错误详情 + /// 已完成的 UnityWebRequest 实例,可用于读取错误详情。 protected virtual void OnRequestFailed(UnityWebRequest webRequest) { } @@ -298,7 +298,7 @@ namespace YooAsset if (deltaTime > _requestArgs.WatchdogTimeout) { AbortRequest(); - YooLogger.Warning($"Watchdog timeout after {deltaTime:F1}s for '{Url}'."); + YooLogger.LogWarning($"Watchdog timeout after {deltaTime:F1}s for '{Url}'."); } } } @@ -333,4 +333,4 @@ namespace YooAsset } } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBytes.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBytes.cs index eaa42ce3..0baa0fb5 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBytes.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestBytes.cs @@ -7,7 +7,7 @@ namespace YooAsset /// UnityWebRequest 字节下载器 /// /// - /// 将下载内容保存到内存中的字节数组。 + /// 将下载内容保存到内存中的字节数组 /// internal sealed class UnityWebRequestBytes : UnityWebRequestBase, IDownloadBytesRequest { @@ -26,7 +26,6 @@ namespace YooAsset { } - /// protected override UnityWebRequest CreateWebRequest() { var request = CreateGetWebRequest(Url); @@ -35,7 +34,6 @@ namespace YooAsset return request; } - /// protected override void OnRequestSucceeded(UnityWebRequest webRequest) { Result = webRequest.downloadHandler.data; diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestFile.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestFile.cs index ae426424..59678bd8 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestFile.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestFile.cs @@ -35,7 +35,6 @@ namespace YooAsset _args = args; } - /// protected override UnityWebRequest CreateWebRequest() { var handler = new DownloadHandlerFile(_args.SavePath, _args.AppendToFile); diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestHead.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestHead.cs index aa69be43..8f56d8dc 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestHead.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestHead.cs @@ -8,8 +8,8 @@ namespace YooAsset /// UnityWebRequest HEAD 请求下载器 /// /// - /// 仅获取响应头信息,不下载实际内容。 - /// 用于检查资源是否存在、获取资源大小、检查缓存有效性等场景。 + /// 仅获取响应头信息,不下载实际内容。 + /// 用于检查资源是否存在、获取资源大小、检查缓存有效性等场景 /// internal sealed class UnityWebRequestHead : UnityWebRequestBase, IDownloadHeadRequest { @@ -81,7 +81,7 @@ namespace YooAsset /// 获取响应头信息 /// /// 响应头名称(不区分大小写) - /// 响应头的值,如果不存在或请求未完成则返回 null + /// 响应头的值,如果不存在或请求未完成则返回 null。 public string GetResponseHeader(string name) { if (_cachedResponseHeaders == null) @@ -93,7 +93,6 @@ namespace YooAsset return null; } - /// protected override UnityWebRequest CreateWebRequest() { var request = CreateHeadWebRequest(Url); @@ -101,7 +100,6 @@ namespace YooAsset return request; } - /// protected override void OnRequestSucceeded(UnityWebRequest webRequest) { var headers = webRequest.GetResponseHeaders(); @@ -118,4 +116,4 @@ namespace YooAsset } } } -} +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestText.cs b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestText.cs index db587053..ff1d95a7 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestText.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/Services/UnityWebRequest/UnityWebRequestText.cs @@ -7,7 +7,7 @@ namespace YooAsset /// UnityWebRequest 文本下载器 /// /// - /// 将下载内容解析为 UTF-8 文本字符串。 + /// 将下载内容解析为 UTF-8 文本字符串 /// internal sealed class UnityWebRequestText : UnityWebRequestBase, IDownloadTextRequest { @@ -26,7 +26,6 @@ namespace YooAsset { } - /// protected override UnityWebRequest CreateWebRequest() { var request = CreateGetWebRequest(Url); @@ -35,7 +34,6 @@ namespace YooAsset return request; } - /// protected override void OnRequestSucceeded(UnityWebRequest webRequest) { Result = webRequest.downloadHandler.text; diff --git a/Assets/YooAsset/Runtime/FileSystem/FileSystemConsts.cs b/Assets/YooAsset/Runtime/FileSystem/FileSystemConsts.cs index 1ffcae24..aa55e023 100644 --- a/Assets/YooAsset/Runtime/FileSystem/FileSystemConsts.cs +++ b/Assets/YooAsset/Runtime/FileSystem/FileSystemConsts.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 文件系统参数常量定义 /// - public class FileSystemConsts + public static class FileSystemConsts { /// /// 初始化的时候缓存文件校验级别 diff --git a/Assets/YooAsset/Runtime/FileSystem/FileSystemHelper.cs b/Assets/YooAsset/Runtime/FileSystem/FileSystemHelper.cs new file mode 100644 index 00000000..badcbec4 --- /dev/null +++ b/Assets/YooAsset/Runtime/FileSystem/FileSystemHelper.cs @@ -0,0 +1,25 @@ +using System; + +namespace YooAsset +{ + internal static class FileSystemHelper + { + /// + /// 将参数值安全转换为目标类型 + /// + /// 目标类型 + /// 参数名称 + /// 待转换的参数值 + /// 转换后的值 + internal static T CastParameter(string paramName, object value) + { + if (value is T typedValue) + return typedValue; + if (value == null) + throw new ArgumentNullException(paramName); + throw new ArgumentException( + $"Failed to cast parameter, type '{value.GetType().Name}' does not match target type '{typeof(T).Name}'.", + paramName); + } + } +} diff --git a/Assets/YooAsset/Runtime/FileSystem/FileSystemHelper.cs.meta b/Assets/YooAsset/Runtime/FileSystem/FileSystemHelper.cs.meta new file mode 100644 index 00000000..0d1a11ef --- /dev/null +++ b/Assets/YooAsset/Runtime/FileSystem/FileSystemHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d4dd45f81473e164581e3b5a766e6fd8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs b/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs index d3e901d2..7b12e28c 100644 --- a/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs +++ b/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 文件系统参数 + /// 提供文件系统的创建参数与工厂方法 /// public class FileSystemParameters { @@ -23,7 +23,11 @@ namespace YooAsset /// public string PackageRoot { get; private set; } - + /// + /// 创建实例 + /// + /// 文件系统的完整类型名称 + /// 文件系统的根目录 public FileSystemParameters(string fileSystemTypeName, string packageRoot) { FileSystemTypeName = fileSystemTypeName; @@ -33,30 +37,33 @@ namespace YooAsset /// /// 添加自定义参数 /// + /// 参数名称 + /// 参数值 public void AddParameter(string paramName, object value) { _createParameters.Add(paramName, value); } /// - /// 创建文件系统 + /// 根据配置创建文件系统实例 /// + /// 包裹名称 + /// 创建的文件系统实例 internal IFileSystem CreateFileSystem(string packageName) { - YooLogger.Log($"The package {packageName} create file system: {FileSystemTypeName}"); + YooLogger.Log($"Package '{packageName}' created file system: '{FileSystemTypeName}'."); Type classType = Type.GetType(FileSystemTypeName); if (classType == null) { - YooLogger.Error($"Cannot find file system class type: {FileSystemTypeName}"); - return null; + throw new InvalidOperationException($"Could not find file system class type: '{FileSystemTypeName}'."); } - var instance = (IFileSystem)System.Activator.CreateInstance(classType, true); + var instance = Activator.CreateInstance(classType, true) as IFileSystem; if (instance == null) { - YooLogger.Error($"Failed to create file system instance: {FileSystemTypeName}"); - return null; + throw new InvalidOperationException( + $"Failed to create file system instance: '{FileSystemTypeName}'. Type must implement {nameof(IFileSystem)}."); } foreach (var param in _createParameters) @@ -72,6 +79,7 @@ namespace YooAsset /// 创建默认的编辑器文件系统参数 /// /// 文件系统的根目录 + /// 配置好的文件系统参数实例 public static FileSystemParameters CreateDefaultEditorFileSystemParameters(string packageRoot) { string fileSystemClass = typeof(EditorFileSystem).FullName; @@ -83,6 +91,7 @@ namespace YooAsset /// 创建默认的内置文件系统参数 /// /// 文件系统的根目录 + /// 配置好的文件系统参数实例 public static FileSystemParameters CreateDefaultBuiltinFileSystemParameters(string packageRoot = null) { string fileSystemClass = typeof(BuiltinFileSystem).FullName; @@ -95,6 +104,7 @@ namespace YooAsset /// /// 远端资源地址查询服务类 /// 文件系统的根目录 + /// 配置好的文件系统参数实例 public static FileSystemParameters CreateDefaultSandboxFileSystemParameters(IRemoteService remoteService, string packageRoot = null) { string fileSystemClass = typeof(SandboxFileSystem).FullName; @@ -107,6 +117,7 @@ namespace YooAsset /// 创建默认的WebServer文件系统参数 /// /// 禁用Unity的网络缓存 + /// 配置好的文件系统参数实例 public static FileSystemParameters CreateDefaultWebServerFileSystemParameters(bool disableUnityWebCache = false) { string fileSystemClass = typeof(WebServerFileSystem).FullName; @@ -120,6 +131,7 @@ namespace YooAsset /// /// 远端资源地址查询服务类 /// 禁用Unity的网络缓存 + /// 配置好的文件系统参数实例 public static FileSystemParameters CreateDefaultWebRemoteFileSystemParameters(IRemoteService remoteService, bool disableUnityWebCache = false) { string fileSystemClass = typeof(WebRemoteFileSystem).FullName; diff --git a/Assets/YooAsset/Runtime/FileSystem/Interfaces/IFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Interfaces/IFileSystem.cs index 549ae629..5ecd83c0 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Interfaces/IFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Interfaces/IFileSystem.cs @@ -14,68 +14,91 @@ namespace YooAsset /// /// 初始化文件系统 /// + /// 初始化操作句柄 FSInitializeOperation InitializeAsync(); /// /// 查询包裹版本 /// + /// 请求版本的选项参数 + /// 请求包裹版本操作句柄 FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options); /// /// 加载包裹清单 /// + /// 加载清单的选项参数 + /// 加载包裹清单操作句柄 FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options); /// /// 加载资源包 /// + /// 加载资源包的选项参数 + /// 加载资源包操作句柄 FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options); /// /// 下载资源包 /// + /// 下载资源包的选项参数 + /// 下载资源包操作句柄 FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options); /// /// 清理缓存文件 /// + /// 清理缓存的选项参数 + /// 清理缓存操作句柄 FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options); /// /// 设置自定义参数 /// + /// 参数名称 + /// 参数值 void SetParameter(string paramName, object value); /// - /// 文件系统创建时的回调 + /// 执行文件系统创建时的初始化回调 /// + /// 包裹名称 + /// 包裹根目录 void OnCreate(string packageName, string packageRoot); /// - /// 文件系统销毁时的回调 + /// 执行文件系统销毁时的清理回调 /// void OnDestroy(); /// - /// 查询文件系统是否可以接管指定的资源包 + /// 判断是否可以接管指定的资源包 /// + /// 资源包描述 + /// 如果可以接受该资源包则返回 true,否则返回 false。 bool CanAcceptBundle(PackageBundle bundle); /// - /// 是否需要下载 + /// 检查是否需要下载指定的资源包 /// + /// 资源包描述 + /// 如果需要下载该资源包则返回 true,否则返回 false。 bool IsDownloadRequired(PackageBundle bundle); /// - /// 是否需要解压 + /// 检查是否需要解压指定的资源包 /// + /// 资源包描述 + /// 如果需要解压该资源包则返回 true,否则返回 false。 bool IsUnpackRequired(PackageBundle bundle); /// - /// 是否需要导入 + /// 检查是否需要导入指定的资源包 /// + /// 资源包描述 + /// 如果需要导入该资源包则返回 true,否则返回 false。 bool IsImportRequired(PackageBundle bundle); } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOperation.cs index 0670a13d..0b4e76d2 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOperation.cs @@ -3,7 +3,7 @@ namespace YooAsset /// /// 加载Web远端包裹清单文件操作 /// - internal class LoadWebPackageManifestOperation : AsyncOperationBase + internal sealed class LoadWebPackageManifestOperation : AsyncOperationBase { private enum ESteps { @@ -44,7 +44,10 @@ namespace YooAsset { string fileName = YooAssetConfiguration.GetManifestBinaryFileName(_options.PackageName, _options.PackageVersion); string url = GetRequestUrl(fileName); - var args = new DownloadDataRequestArgs(url, _options.Timeout, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _options.Timeout, + watchdogTimeout: 0); _downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args); _downloadBytesRequest.SendRequest(); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOptions.cs index f11e2221..95052c23 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/LoadWebPackageManifestOptions.cs @@ -3,46 +3,60 @@ namespace YooAsset /// /// 加载Web远端包裹清单操作选项 /// - internal struct LoadWebPackageManifestOptions + internal readonly struct LoadWebPackageManifestOptions { /// /// 包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 包裹版本 /// - public string PackageVersion { get; set; } + public string PackageVersion { get; } /// /// 包裹哈希值 /// - public string PackageHash { get; set; } + public string PackageHash { get; } /// /// 超时时间(秒) /// - public int Timeout { get; set; } + public int Timeout { get; } /// /// 远端资源地址查询服务 /// - public IRemoteService RemoteService { get; set; } + public IRemoteService RemoteService { get; } /// /// 资源清单解密器 /// - public IManifestDecryptor ManifestDecryptor { get; set; } + public IManifestDecryptor ManifestDecryptor { get; } /// /// 下载后台接口 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } /// /// URL 选择策略 /// - public IDownloadUrlPolicy DownloadUrlPolicy { get; set; } + public IDownloadUrlPolicy DownloadUrlPolicy { get; } + + public LoadWebPackageManifestOptions(string packageName, string packageVersion, string packageHash, + int timeout, IRemoteService remoteService, IManifestDecryptor manifestDecryptor, + IDownloadBackend downloadBackend, IDownloadUrlPolicy downloadUrlPolicy) + { + PackageName = packageName; + PackageVersion = packageVersion; + PackageHash = packageHash; + Timeout = timeout; + RemoteService = remoteService; + ManifestDecryptor = manifestDecryptor; + DownloadBackend = downloadBackend; + DownloadUrlPolicy = downloadUrlPolicy; + } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOperation.cs index 9421d9c1..bd04b6a4 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOperation.cs @@ -3,7 +3,7 @@ namespace YooAsset /// /// 请求Web远端包裹哈希操作 /// - internal class RequestWebPackageHashOperation : AsyncOperationBase + internal sealed class RequestWebPackageHashOperation : AsyncOperationBase { private enum ESteps { @@ -41,7 +41,10 @@ namespace YooAsset { string fileName = YooAssetConfiguration.GetPackageHashFileName(_options.PackageName, _options.PackageVersion); string url = GetRequestUrl(fileName); - var args = new DownloadDataRequestArgs(url, _options.Timeout, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _options.Timeout, + watchdogTimeout: 0); _downloadTextRequest = _options.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -56,7 +59,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageHash, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Web package hash file validation failed: {validateError}"); + SetError($"Web package hash file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOptions.cs index 8165bc14..9a8bfcc5 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageHashOptions.cs @@ -3,36 +3,47 @@ namespace YooAsset /// /// 请求Web远端包裹哈希操作选项 /// - internal struct RequestWebPackageHashOptions + internal readonly struct RequestWebPackageHashOptions { /// /// 包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 包裹版本 /// - public string PackageVersion { get; set; } + public string PackageVersion { get; } /// /// 超时时间(秒) /// - public int Timeout { get; set; } + public int Timeout { get; } /// /// 远端资源地址查询服务 /// - public IRemoteService RemoteService { get; set; } + public IRemoteService RemoteService { get; } /// /// 下载后台接口 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } /// /// URL 选择策略 /// - public IDownloadUrlPolicy DownloadUrlPolicy { get; set; } + public IDownloadUrlPolicy DownloadUrlPolicy { get; } + + public RequestWebPackageHashOptions(string packageName, string packageVersion, int timeout, + IRemoteService remoteService, IDownloadBackend downloadBackend, IDownloadUrlPolicy downloadUrlPolicy) + { + PackageName = packageName; + PackageVersion = packageVersion; + Timeout = timeout; + RemoteService = remoteService; + DownloadBackend = downloadBackend; + DownloadUrlPolicy = downloadUrlPolicy; + } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOperation.cs index bb8795b4..d7f8f192 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOperation.cs @@ -3,7 +3,7 @@ namespace YooAsset /// /// 请求Web远端包裹版本操作 /// - internal class RequestWebPackageVersionOperation : AsyncOperationBase + internal sealed class RequestWebPackageVersionOperation : AsyncOperationBase { private enum ESteps { @@ -41,7 +41,10 @@ namespace YooAsset { string fileName = YooAssetConfiguration.GetPackageVersionFileName(_options.PackageName); string url = GetRequestUrl(fileName); - var args = new DownloadDataRequestArgs(url, _options.Timeout, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _options.Timeout, + watchdogTimeout: 0); _downloadTextRequest = _options.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -56,7 +59,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageVersion, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Web package version file validation failed: {validateError}"); + SetError($"Web package version file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOptions.cs index 4a308338..98a4af41 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/Common/RequestWebPackageVersionOptions.cs @@ -3,36 +3,47 @@ namespace YooAsset /// /// 请求Web远端包裹版本操作选项 /// - internal struct RequestWebPackageVersionOptions + internal readonly struct RequestWebPackageVersionOptions { /// /// 包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 在URL末尾添加时间戳 /// - public bool AppendTimeTicks { get; set; } + public bool AppendTimeTicks { get; } /// /// 超时时间(秒) /// - public int Timeout { get; set; } + public int Timeout { get; } /// /// 远端资源地址查询服务 /// - public IRemoteService RemoteService { get; set; } + public IRemoteService RemoteService { get; } /// /// 下载后台接口 /// - public IDownloadBackend DownloadBackend { get; set; } + public IDownloadBackend DownloadBackend { get; } /// /// URL 选择策略 /// - public IDownloadUrlPolicy DownloadUrlPolicy { get; set; } + public IDownloadUrlPolicy DownloadUrlPolicy { get; } + + public RequestWebPackageVersionOptions(string packageName, bool appendTimeTicks, int timeout, + IRemoteService remoteService, IDownloadBackend downloadBackend, IDownloadUrlPolicy downloadUrlPolicy) + { + PackageName = packageName; + AppendTimeTicks = appendTimeTicks; + Timeout = timeout; + RemoteService = remoteService; + DownloadBackend = downloadBackend; + DownloadUrlPolicy = downloadUrlPolicy; + } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSClearCacheOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSClearCacheOptions.cs index 1225353f..7b275c92 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSClearCacheOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSClearCacheOptions.cs @@ -4,33 +4,39 @@ namespace YooAsset /// /// 清理缓存操作选项 /// - internal struct FSClearCacheOptions + internal readonly struct FSClearCacheOptions { /// /// 清理方式 /// - public string ClearMethod { get; set; } + public string ClearMethod { get; } /// /// 附加参数 /// - public object ClearParameter { get; set; } + public object ClearParameter { get; } /// /// 资源清单 /// - public PackageManifest Manifest { get; set; } + public PackageManifest Manifest { get; } + + public FSClearCacheOptions(string clearMethod, object clearParameter, PackageManifest manifest) + { + ClearMethod = clearMethod; + ClearParameter = clearParameter; + Manifest = manifest; + } /// /// 转换为 BundleCache 的清理选项 /// public BCClearCacheOptions ConvertTo() { - var options = new BCClearCacheOptions(); - options.ClearMethod = ClearMethod; - options.ClearParameter = ClearParameter; - options.Manifest = Manifest; - return options; + return new BCClearCacheOptions( + clearMethod: ClearMethod, + clearParameter: ClearParameter, + manifest: Manifest); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOperation.cs index 57908bdc..d4e21df7 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOperation.cs @@ -7,7 +7,7 @@ namespace YooAsset internal abstract class FSDownloadBundleOperation : AsyncOperationBase { /// - /// 关联的资源包信息 + /// 资源包描述 /// public PackageBundle Bundle { get; private set; } @@ -16,7 +16,7 @@ namespace YooAsset /// public DownloadReport Report { get; protected set; } - public FSDownloadBundleOperation(PackageBundle bundle) + internal FSDownloadBundleOperation(PackageBundle bundle) { Bundle = bundle; } diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOptions.cs index 7f1591ba..7ae4ea4c 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSDownloadBundleOptions.cs @@ -7,19 +7,19 @@ namespace YooAsset internal readonly struct FSDownloadBundleOptions { /// - /// 资源包对象 + /// 资源包描述 /// - public readonly PackageBundle Bundle; + public PackageBundle Bundle { get; } /// /// 失败后重试次数 /// - public readonly int RetryCount; + public int RetryCount { get; } /// /// 待导入的本地文件路径 /// - public readonly string ImportFilePath; + public string ImportFilePath { get; } public FSDownloadBundleOptions(PackageBundle bundle, int retryCount) { diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageBundleOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageBundleOptions.cs index 1ec52f44..71d6d706 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageBundleOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageBundleOptions.cs @@ -7,9 +7,9 @@ namespace YooAsset internal readonly struct FSLoadPackageBundleOptions { /// - /// 资源包 + /// 资源包描述 /// - public readonly PackageBundle Bundle; + public PackageBundle Bundle { get; } public FSLoadPackageBundleOptions(PackageBundle bundle) { diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOperation.cs index 66cb2732..a16685e6 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOperation.cs @@ -9,6 +9,6 @@ namespace YooAsset /// /// 包裹清单 /// - internal PackageManifest Manifest { set; get; } + internal PackageManifest Manifest { get; set; } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOptions.cs index 1bac69ee..2953b5e3 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSLoadPackageManifestOptions.cs @@ -9,12 +9,12 @@ namespace YooAsset /// /// 包裹版本 /// - public readonly string PackageVersion; + public string PackageVersion { get; } /// /// 超时时间 /// - public readonly int Timeout; + public int Timeout { get; } public FSLoadPackageManifestOptions(string packageVersion, int timeout) { diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOperation.cs index 3c70f39c..aeafd142 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOperation.cs @@ -9,6 +9,6 @@ namespace YooAsset /// /// 包裹版本 /// - internal string PackageVersion { set; get; } + internal string PackageVersion { get; set; } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOptions.cs b/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOptions.cs index 6aabfbf1..0e0e5382 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOptions.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Operations/FSRequestPackageVersionOptions.cs @@ -9,12 +9,12 @@ namespace YooAsset /// /// 在URL末尾添加时间戳 /// - public readonly bool AppendTimeTicks; + public bool AppendTimeTicks { get; } /// /// 超时时间 /// - public readonly int Timeout; + public int Timeout { get; } public FSRequestPackageVersionOptions(bool appendTimeTicks, int timeout) { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystem.cs index 54997908..5afbb4fe 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystem.cs @@ -6,31 +6,54 @@ using UnityEngine; namespace YooAsset { /// - /// 内置文件系统 + /// 内置文件系统,管理内置(StreamingAssets)目录下的资源文件访问。 /// internal class BuiltinFileSystem : IFileSystem { + /// + /// 内置资源文件路径映射表 + /// protected readonly Dictionary _builtinFilePathMapping = new Dictionary(10000); + + /// + /// 临时文件路径映射表 + /// protected readonly Dictionary _tempFilePathMapping = new Dictionary(10000); + + /// + /// 包裹根目录路径 + /// protected string _packageRoot; + + /// + /// 临时文件根目录路径 + /// protected string _tempFilesRoot; + + /// + /// 解压清单文件根目录路径 + /// protected string _unpackManifestFilesRoot; + + /// + /// 解压资源包文件根目录路径 + /// protected string _unpackBundleFilesRoot; /// - /// 内置Bundle缓存系统 + /// 内置 Bundle 缓存系统 /// public IBundleCache BuiltinBundleCache { get; private set; } /// - /// 解压Bundle缓存系统 + /// 解压 Bundle 缓存系统 /// public IBundleCache UnpackBundleCache { get; private set; } /// /// 解压调度器 /// - public DownloadSchedulerOperation UnpackScheduler { get; set; } + public DownloadSchedulerOperation UnpackScheduler { get; internal set; } /// /// 下载后台接口 @@ -60,9 +83,10 @@ namespace YooAsset /// /// 自定义参数:初始化的时候缓存文件校验最大并发数 - /// 默认值:8(推荐值为处理器数两倍) - /// 说明:过大的值可能导致线程池任务过多,影响系统稳定性 /// + /// + /// 默认值:8(推荐值为处理器数两倍)。过大的值可能导致线程池任务过多,影响系统稳定性。 + /// public int FileVerifyMaxConcurrency { get; private set; } = 8; /// @@ -72,8 +96,10 @@ namespace YooAsset /// /// 自定义参数:拷贝内置清单的目标目录 - /// 注意:该参数为空的时候,会获取默认的沙盒目录! /// + /// + /// 注意:该参数为空的时候,会获取默认的沙盒目录。 + /// public string CopyBuiltinPackageManifestDestRoot { get; private set; } /// @@ -83,31 +109,34 @@ namespace YooAsset /// /// 自定义参数:最大并发连接数 - /// 默认值:8(推荐范围 1-32) /// + /// + /// 默认值:8(推荐范围 1-32) + /// public int UnpackMaxConcurrency { get; private set; } = 8; /// /// 自定义参数:每帧发起的最大请求数 - /// 默认值:8(推荐范围 1-32) - /// 说明:避免单帧发起过多请求导致卡顿 /// + /// + /// 默认值:8(推荐范围 1-32)。避免单帧发起过多请求导致卡顿。 + /// public int UnpackMaxRequestsPerFrame { get; private set; } = 8; /// /// 自定义参数:AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; private set; } /// /// 自定义参数:RawBundle 解密器 /// - public IBundleDecryptor RawBundleDecryptor { get; set; } + public IBundleDecryptor RawBundleDecryptor { get; private set; } /// /// 自定义参数:AssetBundle 备用解密器 /// - public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; } + public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; private set; } /// /// 自定义参数:资源清单解密器 @@ -115,42 +144,44 @@ namespace YooAsset public IManifestDecryptor ManifestDecryptor { get; private set; } #endregion - + /// + /// 创建实例 + /// public BuiltinFileSystem() { } /// - public virtual FSInitializeOperation InitializeAsync() + public FSInitializeOperation InitializeAsync() { var operation = new BFSInitializeOperation(this); return operation; } /// - public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) + public FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) { var operation = new BFSRequestPackageVersionOperation(this); return operation; } /// - public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) + public FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) { var operation = new BFSLoadPackageManifestOperation(this, options.PackageVersion); return operation; } /// - public virtual FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) + public FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) { var operation = new BFSLoadPackageBundleOperation(this, options); return operation; } /// - public virtual FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) + public FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) { var operation = new BFSDownloadBundleOperation(this, options); return operation; } /// - public virtual FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) + public FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) { if (options.ClearMethod == ClearCacheMethods.ClearAllManifestFiles) { @@ -170,30 +201,30 @@ namespace YooAsset } /// - public virtual void SetParameter(string paramName, object value) + public void SetParameter(string paramName, object value) { if (paramName == FileSystemConsts.DOWNLOAD_BACKEND) { - DownloadBackend = (IDownloadBackend)value; + DownloadBackend = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.UNITY_WEB_REQUEST_CREATOR) { - WebRequestCreator = (UnityWebRequestCreator)value; + WebRequestCreator = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.INSTALL_CLEANUP_MODE) { - InstallCleanupMode = (EInstallCleanupMode)value; + InstallCleanupMode = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.FILE_VERIFY_LEVEL) { - FileVerifyLevel = (EFileVerifyLevel)value; + FileVerifyLevel = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.FILE_VERIFY_MAX_CONCURRENCY) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"FILE_VERIFY_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"FILE_VERIFY_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -201,22 +232,22 @@ namespace YooAsset } else if (paramName == FileSystemConsts.COPY_BUILTIN_PACKAGE_MANIFEST) { - CopyBuiltinPackageManifest = Convert.ToBoolean(value); + CopyBuiltinPackageManifest = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.COPY_BUILTIN_PACKAGE_MANIFEST_DEST_ROOT) { - CopyBuiltinPackageManifestDestRoot = (string)value; + CopyBuiltinPackageManifestDestRoot = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.UNPACK_FILE_SYSTEM_ROOT) { - UnpackFileSystemRoot = (string)value; + UnpackFileSystemRoot = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_MAX_CONCURRENCY) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -224,10 +255,10 @@ namespace YooAsset } else if (paramName == FileSystemConsts.DOWNLOAD_MAX_REQUEST_PER_FRAME) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -235,27 +266,27 @@ namespace YooAsset } else if (paramName == FileSystemConsts.ASSETBUNDLE_DECRYPTOR) { - AssetBundleDecryptor = (IBundleDecryptor)value; + AssetBundleDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.RAWBUNDLE_DECRYPTOR) { - RawBundleDecryptor = (IBundleDecryptor)value; + RawBundleDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.ASSETBUNDLE_FALLBACK_DECRYPTOR) { - AssetBundleFallbackDecryptor = (IBundleMemoryDecryptor)value; + AssetBundleFallbackDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.MANIFEST_DECRYPTOR) { - ManifestDecryptor = (IManifestDecryptor)value; + ManifestDecryptor = FileSystemHelper.CastParameter(paramName, value); } else { - YooLogger.Warning($"Invalid parameter: {paramName}"); + throw new ArgumentException($"Unrecognized parameter name: '{paramName}'.", nameof(paramName)); } } /// - public virtual void OnCreate(string packageName, string packageRoot) + public void OnCreate(string packageName, string packageRoot) { PackageName = packageName; @@ -280,26 +311,26 @@ namespace YooAsset // 创建内置文件缓存系统 { - var cacheConfig = new BuiltinBundleCache.Configuration(); - cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor; - cacheConfig.RawBundleDecryptor = RawBundleDecryptor; - cacheConfig.DownloadBackend = DownloadBackend; + var cacheConfig = new BuiltinBundleCache.Configuration( + assetBundleDecryptor: AssetBundleDecryptor, + rawBundleDecryptor: RawBundleDecryptor, + downloadBackend: DownloadBackend); BuiltinBundleCache = new BuiltinBundleCache(packageName, _packageRoot, cacheConfig); } // 创建沙盒文件缓存系统 { - var cacheConfig = new SandboxBundleCache.Configuration(); - cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency; - cacheConfig.FileVerifyLevel = FileVerifyLevel; - cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor; - cacheConfig.RawBundleDecryptor = RawBundleDecryptor; - cacheConfig.AssetBundleFallbackDecryptor = AssetBundleFallbackDecryptor; + var cacheConfig = new SandboxBundleCache.Configuration( + fileVerifyMaxConcurrency: FileVerifyMaxConcurrency, + fileVerifyLevel: FileVerifyLevel, + assetBundleDecryptor: AssetBundleDecryptor, + rawBundleDecryptor: RawBundleDecryptor, + assetBundleFallbackDecryptor: AssetBundleFallbackDecryptor); UnpackBundleCache = new SandboxBundleCache(packageName, _unpackBundleFilesRoot, cacheConfig); } } /// - public virtual void OnDestroy() + public void OnDestroy() { if (BuiltinBundleCache != null) { @@ -327,17 +358,17 @@ namespace YooAsset } /// - public virtual bool CanAcceptBundle(PackageBundle bundle) + public bool CanAcceptBundle(PackageBundle bundle) { return BuiltinBundleCache.IsCached(bundle.BundleGuid); } /// - public virtual bool IsDownloadRequired(PackageBundle bundle) + public bool IsDownloadRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsUnpackRequired(PackageBundle bundle) + public bool IsUnpackRequired(PackageBundle bundle) { if (IsUnpackBundleFile(bundle)) { @@ -349,7 +380,7 @@ namespace YooAsset } } /// - public virtual bool IsImportRequired(PackageBundle bundle) + public bool IsImportRequired(PackageBundle bundle) { return false; } @@ -357,7 +388,7 @@ namespace YooAsset /// /// 是否属于解压资源包文件 /// - public virtual bool IsUnpackBundleFile(PackageBundle bundle) + public bool IsUnpackBundleFile(PackageBundle bundle) { if (CanAcceptBundle(bundle) == false) return false; @@ -366,7 +397,7 @@ namespace YooAsset if (bundle.IsEncrypted) return true; - if (bundle.BundleType == (int)EBundleType.RawBundle) + if (bundle.GetBundleType() == (int)EBundleType.RawBundle) return true; return false; @@ -392,7 +423,7 @@ namespace YooAsset { if (_builtinFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) { - filePath = PathUtility.Combine(_packageRoot, bundle.FileName); + filePath = PathUtility.Combine(_packageRoot, bundle.GetFileName()); _builtinFilePathMapping.Add(bundle.BundleGuid, filePath); } return filePath; diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystemConsts.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystemConsts.cs index d4cfead5..2264d093 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystemConsts.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/BuiltinFileSystemConsts.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统常量定义 /// - internal class BuiltinFileSystemConsts + internal static class BuiltinFileSystemConsts { /// /// 解压清单文件的文件夹名称 diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSClearCacheOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSClearCacheOperation.cs index 79c8fbf6..eb477d99 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSClearCacheOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统的清理缓存操作 /// - internal class BFSClearCacheOperation : FSClearCacheOperation + internal sealed class BFSClearCacheOperation : FSClearCacheOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSDownloadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSDownloadBundleOperation.cs index 16346a4b..01474c22 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSDownloadBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统的解压文件操作 /// - internal class BFSDownloadBundleOperation : FSDownloadBundleOperation + internal sealed class BFSDownloadBundleOperation : FSDownloadBundleOperation { private enum ESteps { @@ -68,7 +68,9 @@ namespace YooAsset if (IsWaitForCompletion) _downloadFileOp.WaitForCompletion(); - _downloadFileOp.UpdateOperation(); + // 注意:不主动调用 _downloadFileOp.UpdateOperation() + // 说明:解压任务由 UnpackScheduler 统一驱动,此处仅读取状态。 + // 说明:同步等待由 WaitForCompletion() 内部的 ExecuteBatch() 保证。 Progress = _downloadFileOp.Progress; Report = _downloadFileOp.LatestReport; if (_downloadFileOp.IsDone == false) @@ -83,7 +85,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError(_downloadFileOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSInitializeOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSInitializeOperation.cs index 1ec1bca2..013c9b05 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统的初始化操作 /// - internal class BFSInitializeOperation : FSInitializeOperation + internal sealed class BFSInitializeOperation : FSInitializeOperation { private enum ESteps { @@ -58,28 +58,28 @@ namespace YooAsset { if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.None) { - YooLogger.Warning("No action required on overwrite installation."); + YooLogger.LogWarning("No action required on overwrite installation."); } else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllCacheFiles) { _fileSystem.DeleteAllBundleFiles(); _fileSystem.DeleteAllManifestFiles(); _fileSystem.DeleteAllTempFiles(); - YooLogger.Warning("Deleted all cache files on overwrite installation."); + YooLogger.LogWarning("Deleted all cache files on overwrite installation."); } else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllBundleFiles) { _fileSystem.DeleteAllBundleFiles(); - YooLogger.Warning("Deleted all bundle files on overwrite installation."); + YooLogger.LogWarning("Deleted all bundle files on overwrite installation."); } else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllManifestFiles) { _fileSystem.DeleteAllManifestFiles(); - YooLogger.Warning("Deleted all manifest files on overwrite installation."); + YooLogger.LogWarning("Deleted all manifest files on overwrite installation."); } else { - throw new System.NotImplementedException(_fileSystem.InstallCleanupMode.ToString()); + throw new YooInternalException($"Unhandled {nameof(EInstallCleanupMode)} value: {_fileSystem.InstallCleanupMode}."); } appFootprint.Overwrite(_fileSystem.PackageName); @@ -176,10 +176,10 @@ namespace YooAsset if (_fileSystem.UnpackScheduler == null) { var schedulerConfig = new DownloadSchedulerOperation.Configuration( - _fileSystem.GetType().Name, - _fileSystem.DownloadBackend, - _fileSystem.UnpackMaxConcurrency, - _fileSystem.UnpackMaxRequestsPerFrame); + schedulerName: _fileSystem.GetType().Name, + downloadBackend: _fileSystem.DownloadBackend, + maxConcurrency: _fileSystem.UnpackMaxConcurrency, + maxRequestsPerFrame: _fileSystem.UnpackMaxRequestsPerFrame); _fileSystem.UnpackScheduler = new DownloadSchedulerOperation(schedulerConfig); AsyncOperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.UnpackScheduler); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageBundleOperation.cs index 3386df79..80859ecb 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统的加载资源包操作 /// - internal class BFSLoadPackageBundleOperation : FSLoadPackageBundleOperation + internal sealed class BFSLoadPackageBundleOperation : FSLoadPackageBundleOperation { private enum ESteps { @@ -139,8 +139,8 @@ namespace YooAsset if (_loadBundleOp.BundleHandle == null) { _steps = ESteps.Done; - SetError("Loaded bundle handle is null."); - YooLogger.Error(Error); + SetError("Fatal error: loaded bundle handle is null."); + YooLogger.LogError(Error); } else { @@ -153,7 +153,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError(_loadBundleOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageManifestOperation.cs index ddfa490c..cd7177c2 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSLoadPackageManifestOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统的加载包裹清单操作 /// - internal class BFSLoadPackageManifestOperation : FSLoadPackageManifestOperation + internal sealed class BFSLoadPackageManifestOperation : FSLoadPackageManifestOperation { private enum ESteps { @@ -21,7 +21,7 @@ namespace YooAsset private ESteps _steps = ESteps.None; - public BFSLoadPackageManifestOperation(BuiltinFileSystem fileSystem, string packageVersion) + internal BFSLoadPackageManifestOperation(BuiltinFileSystem fileSystem, string packageVersion) { _fileSystem = fileSystem; _packageVersion = packageVersion; diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSRequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSRequestPackageVersionOperation.cs index 3d7e9a6b..e840823b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSRequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/BFSRequestPackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 内置文件系统的查询包裹版本操作 /// - internal class BFSRequestPackageVersionOperation : FSRequestPackageVersionOperation + internal sealed class BFSRequestPackageVersionOperation : FSRequestPackageVersionOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/Internal/CopyBuiltinPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/Internal/CopyBuiltinPackageManifestOperation.cs index 85d621d0..c27a85c1 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/Internal/CopyBuiltinPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/Internal/CopyBuiltinPackageManifestOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 拷贝内置包裹清单到沙盒操作 /// - internal class CopyBuiltinPackageManifestOperation : AsyncOperationBase + internal sealed class CopyBuiltinPackageManifestOperation : AsyncOperationBase { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/CopyBuiltinFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/CopyBuiltinFileOperation.cs index 45e21ee7..9b56beb0 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/CopyBuiltinFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/CopyBuiltinFileOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 拷贝内置文件操作 /// - internal class CopyBuiltinFileOperation : AsyncOperationBase + internal sealed class CopyBuiltinFileOperation : AsyncOperationBase { private enum ESteps { @@ -23,7 +23,7 @@ namespace YooAsset private IDownloadFileRequest _downloadFileRequest; private ESteps _steps = ESteps.None; - public CopyBuiltinFileOperation(BuiltinFileSystem fileSystem, string sourceFilePath, string destFilePath) + internal CopyBuiltinFileOperation(BuiltinFileSystem fileSystem, string sourceFilePath, string destFilePath) { _fileSystem = fileSystem; _sourceFilePath = sourceFilePath; @@ -40,6 +40,8 @@ namespace YooAsset if (_steps == ESteps.CheckFileExist) { + // 注意:只检查目标文件是否存在,不校验完整性。 + // 说明:文件校验由后续的缓存写入流程负责。 if (File.Exists(_destFilePath)) { _steps = ESteps.Done; @@ -57,16 +59,14 @@ namespace YooAsset { try { - var directory = Path.GetDirectoryName(_destFilePath); - if (Directory.Exists(directory) == false) - Directory.CreateDirectory(directory); + FileUtility.EnsureParentDirectoryExists(_destFilePath); File.Copy(_sourceFilePath, _destFilePath, true); _steps = ESteps.Done; SetResult(); } catch (Exception ex) { - YooLogger.Warning($"Failed to copy builtin file: {ex.Message}"); + YooLogger.LogWarning($"Failed to copy builtin file: {ex.Message}."); _steps = ESteps.UnpackFile; } } @@ -80,9 +80,13 @@ namespace YooAsset { if (_downloadFileRequest == null) { - //TODO 团结引擎,在某些安卓机型(红米),通过UnityWebRequest拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。 + // TODO: 团结引擎,在某些安卓机型(红米),通过UnityWebRequest拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。 string url = DownloadUrlHelper.ToLocalFileUrl(_sourceFilePath); - var args = new DownloadFileRequestArgs(url, 60, 0, _destFilePath); + var args = new DownloadFileRequestArgs( + url: url, + timeout: 60, + watchdogTimeout: 0, + savePath: _destFilePath); _downloadFileRequest = _fileSystem.DownloadBackend.CreateFileRequest(args); _downloadFileRequest.SendRequest(); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/LoadBuiltinPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/LoadBuiltinPackageManifestOperation.cs index e009305a..5576c1c7 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/LoadBuiltinPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/LoadBuiltinPackageManifestOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 加载内置包裹清单文件操作 /// - internal class LoadBuiltinPackageManifestOperation : AsyncOperationBase + internal sealed class LoadBuiltinPackageManifestOperation : AsyncOperationBase { private enum ESteps { @@ -51,8 +51,16 @@ namespace YooAsset string filePath = _fileSystem.GetBuiltinPackageManifestFilePath(_packageVersion); if (File.Exists(filePath)) { - _fileData = File.ReadAllBytes(filePath); - _steps = ESteps.VerifyFileData; + try + { + _fileData = File.ReadAllBytes(filePath); + _steps = ESteps.VerifyFileData; + } + catch (System.Exception ex) + { + _steps = ESteps.Done; + SetError($"Failed to read builtin package manifest file: {ex.Message}."); + } } else { @@ -66,7 +74,10 @@ namespace YooAsset { string filePath = _fileSystem.GetBuiltinPackageManifestFilePath(_packageVersion); string url = DownloadUrlHelper.ToLocalFileUrl(filePath); - var args = new DownloadDataRequestArgs(url, 60, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: 60, + watchdogTimeout: 0); _downloadBytesRequest = _fileSystem.DownloadBackend.CreateBytesRequest(args); _downloadBytesRequest.SendRequest(); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageHashOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageHashOperation.cs index 4c906e69..61100b39 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageHashOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageHashOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 请求内置包裹哈希操作 /// - internal class RequestBuiltinPackageHashOperation : AsyncOperationBase + internal sealed class RequestBuiltinPackageHashOperation : AsyncOperationBase { private enum ESteps { @@ -46,8 +46,16 @@ namespace YooAsset string filePath = _fileSystem.GetBuiltinPackageHashFilePath(_packageVersion); if (File.Exists(filePath)) { - PackageHash = File.ReadAllText(filePath); - _steps = ESteps.CheckResult; + try + { + PackageHash = File.ReadAllText(filePath); + _steps = ESteps.CheckResult; + } + catch (System.Exception ex) + { + _steps = ESteps.Done; + SetError($"Failed to read builtin package hash file: {ex.Message}."); + } } else { @@ -61,7 +69,10 @@ namespace YooAsset { string filePath = _fileSystem.GetBuiltinPackageHashFilePath(_packageVersion); string url = DownloadUrlHelper.ToLocalFileUrl(filePath); - var args = new DownloadDataRequestArgs(url, 60, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: 60, + watchdogTimeout: 0); _downloadTextRequest = _fileSystem.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -86,7 +97,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageHash, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Builtin package hash file validation failed: {validateError}"); + SetError($"Builtin package hash file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageVersionOperation.cs index 96e92ce5..8beb78a3 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/RequestBuiltinPackageVersionOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 请求内置包裹版本操作 /// - internal class RequestBuiltinPackageVersionOperation : AsyncOperationBase + internal sealed class RequestBuiltinPackageVersionOperation : AsyncOperationBase { private enum ESteps { @@ -44,8 +44,16 @@ namespace YooAsset string filePath = _fileSystem.GetBuiltinPackageVersionFilePath(); if (File.Exists(filePath)) { - PackageVersion = File.ReadAllText(filePath); - _steps = ESteps.CheckResult; + try + { + PackageVersion = File.ReadAllText(filePath); + _steps = ESteps.CheckResult; + } + catch (System.Exception ex) + { + _steps = ESteps.Done; + SetError($"Failed to read builtin package version file: {ex.Message}."); + } } else { @@ -59,7 +67,10 @@ namespace YooAsset { string filePath = _fileSystem.GetBuiltinPackageVersionFilePath(); string url = DownloadUrlHelper.ToLocalFileUrl(filePath); - var args = new DownloadDataRequestArgs(url, 60, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: 60, + watchdogTimeout: 0); _downloadTextRequest = _fileSystem.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -84,7 +95,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageVersion, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Builtin package version file validation failed: {validateError}"); + SetError($"Builtin package version file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/UnpackAndCacheFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/UnpackAndCacheFileOperation.cs index ad564a68..94d556bc 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/UnpackAndCacheFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/BuiltinFileSystem/Operations/internal/UnpackAndCacheFileOperation.cs @@ -89,9 +89,7 @@ namespace YooAsset { if (_writeCacheOp == null) { - var options = new BCWriteCacheOptions(); - options.Bundle = Bundle; - options.FilePath = _tempFilePath; + var options = new BCWriteCacheOptions(Bundle, _tempFilePath); _writeCacheOp = _fileSystem.UnpackBundleCache.WriteCacheAsync(options); _writeCacheOp.StartOperation(); AddChildOperation(_writeCacheOp); diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/EditorFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/EditorFileSystem.cs index 6a8045fe..9825034b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/EditorFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/EditorFileSystem.cs @@ -4,10 +4,13 @@ using UnityEngine; namespace YooAsset { /// - /// 模拟文件系统 + /// 模拟文件系统,管理编辑器模式下的模拟文件系统。 /// internal class EditorFileSystem : IFileSystem { + /// + /// 包裹根目录路径 + /// protected string _packageRoot; /// @@ -18,7 +21,7 @@ namespace YooAsset /// /// 下载调度器 /// - public DownloadSchedulerOperation DownloadScheduler { get; set; } + public DownloadSchedulerOperation DownloadScheduler { get; internal set; } /// /// 下载后台接口 @@ -48,72 +51,83 @@ namespace YooAsset /// /// 自定义参数:模拟虚拟下载的网速(单位:字节) - /// 默认值:1024 /// + /// + /// 默认值:1024 + /// public int VirtualDownloadSpeed { get; private set; } = 1024; /// /// 自定义参数:最大并发连接数 - /// 默认值:8(推荐范围 1-32) - /// 说明:过大的并发数可能被服务器限流,也会增加本地资源消耗 /// + /// + /// 默认值:8(推荐范围 1-32)。过大的并发数可能被服务器限流,也会增加本地资源消耗。 + /// public int DownloadMaxConcurrency { get; private set; } = 8; /// /// 自定义参数:每帧发起的最大请求数 - /// 默认值:8(推荐范围 1-32) - /// 说明:避免单帧发起过多请求导致卡顿 /// + /// + /// 默认值:8(推荐范围 1-32)。避免单帧发起过多请求导致卡顿。 + /// public int DownloadMaxRequestsPerFrame { get; private set; } = 8; /// /// 自定义参数:异步模拟加载最小帧数 - /// 默认值:1 /// + /// + /// 默认值:1 + /// public int AsyncSimulateMinFrame { get; private set; } = 1; /// /// 自定义参数:异步模拟加载最大帧数 - /// 默认值:1 /// + /// + /// 默认值:1 + /// public int AsyncSimulateMaxFrame { get; private set; } = 1; #endregion + /// + /// 创建实例 + /// public EditorFileSystem() { } /// - public virtual FSInitializeOperation InitializeAsync() + public FSInitializeOperation InitializeAsync() { var operation = new EFSInitializeOperation(this); return operation; } /// - public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) + public FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) { var operation = new EFSRequestPackageVersionOperation(this); return operation; } /// - public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) + public FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) { var operation = new EFSLoadPackageManifestOperation(this, options.PackageVersion); return operation; } /// - public virtual FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) + public FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) { var operation = new EFSLoadPackageBundleOperation(this, options); return operation; } /// - public virtual FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) + public FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) { var downloader = new EFSDownloadBundleOperation(this, options); return downloader; } /// - public virtual FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) + public FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) { if (options.ClearMethod == ClearCacheMethods.ClearAllManifestFiles) { @@ -133,35 +147,35 @@ namespace YooAsset } /// - public virtual void SetParameter(string paramName, object value) + public void SetParameter(string paramName, object value) { if (paramName == FileSystemConsts.DOWNLOAD_BACKEND) { - DownloadBackend = (IDownloadBackend)value; + DownloadBackend = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.UNITY_WEB_REQUEST_CREATOR) { - WebRequestCreator = (UnityWebRequestCreator)value; + WebRequestCreator = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.VIRTUAL_WEBGL_MODE) { - VirtualWebGLMode = Convert.ToBoolean(value); + VirtualWebGLMode = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.VIRTUAL_DOWNLOAD_MODE) { - VirtualDownloadMode = Convert.ToBoolean(value); + VirtualDownloadMode = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.VIRTUAL_DOWNLOAD_SPEED) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); VirtualDownloadSpeed = Mathf.Clamp(convertValue, 1, int.MaxValue); } else if (paramName == FileSystemConsts.DOWNLOAD_MAX_CONCURRENCY) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -169,10 +183,10 @@ namespace YooAsset } else if (paramName == FileSystemConsts.DOWNLOAD_MAX_REQUEST_PER_FRAME) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -180,19 +194,19 @@ namespace YooAsset } else if (paramName == FileSystemConsts.ASYNC_SIMULATE_MIN_FRAME) { - AsyncSimulateMinFrame = Convert.ToInt32(value); + AsyncSimulateMinFrame = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.ASYNC_SIMULATE_MAX_FRAME) { - AsyncSimulateMaxFrame = Convert.ToInt32(value); + AsyncSimulateMaxFrame = FileSystemHelper.CastParameter(paramName, value); } else { - YooLogger.Warning($"Invalid parameter: {paramName}"); + throw new ArgumentException($"Unrecognized parameter name: '{paramName}'.", nameof(paramName)); } } /// - public virtual void OnCreate(string packageName, string packageRoot) + public void OnCreate(string packageName, string packageRoot) { PackageName = packageName; @@ -208,15 +222,15 @@ namespace YooAsset // 创建编辑器文件缓存系统 if (AsyncSimulateMinFrame > AsyncSimulateMaxFrame) AsyncSimulateMinFrame = AsyncSimulateMaxFrame; - var cacheConfig = new EditorBundleCache.Configuration(); - cacheConfig.VirtualDownloadMode = VirtualDownloadMode; - cacheConfig.VirtualWebGLMode = VirtualWebGLMode; - cacheConfig.AsyncSimulateMinFrame = AsyncSimulateMinFrame; - cacheConfig.AsyncSimulateMaxFrame = AsyncSimulateMaxFrame; + var cacheConfig = new EditorBundleCache.Configuration( + virtualDownloadMode: VirtualDownloadMode, + virtualWebGLMode: VirtualWebGLMode, + asyncSimulateMinFrame: AsyncSimulateMinFrame, + asyncSimulateMaxFrame: AsyncSimulateMaxFrame); BundleCache = new EditorBundleCache(packageName, _packageRoot, cacheConfig); } /// - public virtual void OnDestroy() + public void OnDestroy() { if (BundleCache != null) { @@ -238,22 +252,22 @@ namespace YooAsset } /// - public virtual bool CanAcceptBundle(PackageBundle bundle) + public bool CanAcceptBundle(PackageBundle bundle) { return true; } /// - public virtual bool IsDownloadRequired(PackageBundle bundle) + public bool IsDownloadRequired(PackageBundle bundle) { return BundleCache.IsCached(bundle.BundleGuid) == false; } /// - public virtual bool IsUnpackRequired(PackageBundle bundle) + public bool IsUnpackRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsImportRequired(PackageBundle bundle) + public bool IsImportRequired(PackageBundle bundle) { return false; } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSClearCacheOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSClearCacheOperation.cs index 602c1a32..34a53e1b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSClearCacheOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件系统的清理缓存操作 /// - internal class EFSClearCacheOperation : FSClearCacheOperation + internal sealed class EFSClearCacheOperation : FSClearCacheOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSDownloadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSDownloadBundleOperation.cs index 7b5a81e7..9b3bd68d 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSDownloadBundleOperation.cs @@ -4,9 +4,9 @@ namespace YooAsset /// /// 编辑器文件系统的下载文件操作 /// - internal class EFSDownloadBundleOperation : FSDownloadBundleOperation + internal sealed class EFSDownloadBundleOperation : FSDownloadBundleOperation { - protected enum ESteps + private enum ESteps { None, CheckExists, @@ -58,7 +58,7 @@ namespace YooAsset if (string.IsNullOrEmpty(editorFilePath)) { _steps = ESteps.Done; - SetError($"Editor file path is empty. Bundle: {Bundle.BundleName}"); + SetError($"Editor file path is empty for bundle '{Bundle.BundleName}'."); return; } @@ -75,7 +75,9 @@ namespace YooAsset if (IsWaitForCompletion) _downloadFileOp.WaitForCompletion(); - _downloadFileOp.UpdateOperation(); + // 注意:不主动调用 _downloadFileOp.UpdateOperation() + // 说明:下载任务由 DownloadSchedulerOperation 统一驱动,此处仅读取状态。 + // 说明:同步等待由 WaitForCompletion() 内部的 ExecuteBatch() 保证。 Progress = _downloadFileOp.Progress; Report = _downloadFileOp.LatestReport; if (_downloadFileOp.IsDone == false) @@ -90,7 +92,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError(_downloadFileOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSInitializeOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSInitializeOperation.cs index 8c76f126..e257c8aa 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件系统的初始化操作 /// - internal class EFSInitializeOperation : FSInitializeOperation + internal sealed class EFSInitializeOperation : FSInitializeOperation { private enum ESteps { @@ -74,10 +74,10 @@ namespace YooAsset if (_fileSystem.DownloadScheduler == null) { var schedulerConfig = new DownloadSchedulerOperation.Configuration( - _fileSystem.GetType().Name, - _fileSystem.DownloadBackend, - _fileSystem.DownloadMaxConcurrency, - _fileSystem.DownloadMaxRequestsPerFrame); + schedulerName: _fileSystem.GetType().Name, + downloadBackend: _fileSystem.DownloadBackend, + maxConcurrency: _fileSystem.DownloadMaxConcurrency, + maxRequestsPerFrame: _fileSystem.DownloadMaxRequestsPerFrame); _fileSystem.DownloadScheduler = new DownloadSchedulerOperation(schedulerConfig); AsyncOperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadScheduler); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageBundleOperation.cs index 9f516e5a..a568f686 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件系统的加载资源包操作 /// - internal class EFSLoadPackageBundleOperation : FSLoadPackageBundleOperation + internal sealed class EFSLoadPackageBundleOperation : FSLoadPackageBundleOperation { private enum ESteps { @@ -123,8 +123,8 @@ namespace YooAsset if (_loadBundleOp.BundleHandle == null) { _steps = ESteps.Done; - SetError("Loaded bundle handle is null."); - YooLogger.Error(Error); + SetError("Fatal error: loaded bundle handle is null."); + YooLogger.LogError(Error); } else { @@ -137,7 +137,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError(_loadBundleOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageManifestOperation.cs index cc8f5b05..4005d5e9 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSLoadPackageManifestOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件系统的加载包裹清单操作 /// - internal class EFSLoadPackageManifestOperation : FSLoadPackageManifestOperation + internal sealed class EFSLoadPackageManifestOperation : FSLoadPackageManifestOperation { private enum ESteps { @@ -16,7 +16,7 @@ namespace YooAsset private readonly EditorFileSystem _fileSystem; private readonly string _packageVersion; - private LoadEditorPackageHashOperation _loadEditorPackageHashOpe; + private LoadEditorPackageHashOperation _loadEditorPackageHashOp; private LoadEditorPackageManifestOperation _loadEditorPackageManifestOp; private ESteps _steps = ESteps.None; @@ -37,25 +37,25 @@ namespace YooAsset if (_steps == ESteps.LoadPackageHash) { - if (_loadEditorPackageHashOpe == null) + if (_loadEditorPackageHashOp == null) { - _loadEditorPackageHashOpe = new LoadEditorPackageHashOperation(_fileSystem, _packageVersion); - _loadEditorPackageHashOpe.StartOperation(); - AddChildOperation(_loadEditorPackageHashOpe); + _loadEditorPackageHashOp = new LoadEditorPackageHashOperation(_fileSystem, _packageVersion); + _loadEditorPackageHashOp.StartOperation(); + AddChildOperation(_loadEditorPackageHashOp); } - _loadEditorPackageHashOpe.UpdateOperation(); - if (_loadEditorPackageHashOpe.IsDone == false) + _loadEditorPackageHashOp.UpdateOperation(); + if (_loadEditorPackageHashOp.IsDone == false) return; - if (_loadEditorPackageHashOpe.Status == EOperationStatus.Succeeded) + if (_loadEditorPackageHashOp.Status == EOperationStatus.Succeeded) { _steps = ESteps.LoadPackageManifest; } else { _steps = ESteps.Done; - SetError(_loadEditorPackageHashOpe.Error); + SetError(_loadEditorPackageHashOp.Error); } } @@ -63,7 +63,7 @@ namespace YooAsset { if (_loadEditorPackageManifestOp == null) { - string packageHash = _loadEditorPackageHashOpe.PackageHash; + string packageHash = _loadEditorPackageHashOp.PackageHash; _loadEditorPackageManifestOp = new LoadEditorPackageManifestOperation(_fileSystem, _packageVersion, packageHash); _loadEditorPackageManifestOp.StartOperation(); AddChildOperation(_loadEditorPackageManifestOp); diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSRequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSRequestPackageVersionOperation.cs index 7cfea095..d108d8a4 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSRequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/EFSRequestPackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 编辑器文件系统的查询包裹版本操作 /// - internal class EFSRequestPackageVersionOperation : FSRequestPackageVersionOperation + internal sealed class EFSRequestPackageVersionOperation : FSRequestPackageVersionOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageHashOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageHashOperation.cs index 697ab60c..b2c15397 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageHashOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageHashOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 加载编辑器包裹哈希文件操作 /// - internal class LoadEditorPackageHashOperation : AsyncOperationBase + internal sealed class LoadEditorPackageHashOperation : AsyncOperationBase { private enum ESteps { @@ -47,7 +47,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageHash, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Simulation package hash file validation failed: {validateError}"); + SetError($"Simulation package hash file validation failed: {validateError}."); } else { @@ -58,7 +58,7 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"Cannot find simulation package hash file: {hashFilePath}"); + SetError($"Could not find simulation package hash file: '{hashFilePath}'."); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageManifestOperation.cs index 5a177a77..0688490e 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageManifestOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 加载编辑器包裹清单文件操作 /// - internal class LoadEditorPackageManifestOperation : AsyncOperationBase + internal sealed class LoadEditorPackageManifestOperation : AsyncOperationBase { private enum ESteps { @@ -49,13 +49,21 @@ namespace YooAsset string manifestFilePath = _fileSystem.GetEditorPackageManifestFilePath(_packageVersion); if (File.Exists(manifestFilePath)) { - _steps = ESteps.VerifyFileData; - _fileData = FileUtility.ReadAllBytes(manifestFilePath); + try + { + _fileData = FileUtility.ReadAllBytes(manifestFilePath); + _steps = ESteps.VerifyFileData; + } + catch (System.Exception ex) + { + _steps = ESteps.Done; + SetError($"Failed to read editor package manifest file: {ex.Message}."); + } } else { _steps = ESteps.Done; - SetError($"Cannot find simulation package manifest file: {manifestFilePath}"); + SetError($"Could not find simulation package manifest file: '{manifestFilePath}'."); } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageVersionOperation.cs index 98c86294..75bf2b90 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/LoadEditorPackageVersionOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 加载编辑器包裹版本文件操作 /// - internal class LoadEditorPackageVersionOperation : AsyncOperationBase + internal sealed class LoadEditorPackageVersionOperation : AsyncOperationBase { private enum ESteps { @@ -45,7 +45,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageVersion, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Simulation package version file validation failed: {validateError}"); + SetError($"Simulation package version file validation failed: {validateError}."); } else { @@ -56,7 +56,7 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"Cannot find simulation package version file: {versionFilePath}"); + SetError($"Could not find simulation package version file: '{versionFilePath}'."); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/SimulateAndCacheFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/SimulateAndCacheFileOperation.cs index e57a2873..0aa8cd3b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/SimulateAndCacheFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/EditorFileSystem/Operations/internal/SimulateAndCacheFileOperation.cs @@ -4,9 +4,9 @@ namespace YooAsset /// /// 模拟下载并缓存文件操作 /// - internal class SimulateAndCacheFileOperation : DownloadFileBaseOperation + internal sealed class SimulateAndCacheFileOperation : DownloadFileBaseOperation { - protected enum ESteps + private enum ESteps { None, CreateRequest, @@ -15,8 +15,8 @@ namespace YooAsset Done, } - protected readonly EditorFileSystem _fileSystem; - protected IDownloadRequest _downloadRequest; + private readonly EditorFileSystem _fileSystem; + private IDownloadRequest _downloadRequest; private BCWriteCacheOperation _writeCacheOp; private ESteps _steps = ESteps.None; @@ -37,7 +37,10 @@ namespace YooAsset if (_steps == ESteps.CreateRequest) { int speed = _fileSystem.VirtualDownloadSpeed; - var args = new SimulatedDownloadRequestArgs(Url, Bundle.FileSize, speed); + var args = new SimulatedDownloadRequestArgs( + url: Url, + fileSize: Bundle.FileSize, + downloadSpeed: speed); _downloadRequest = _fileSystem.DownloadBackend.CreateSimulateRequest(args); _downloadRequest.SendRequest(); _steps = ESteps.CheckRequest; @@ -72,9 +75,7 @@ namespace YooAsset { if (_writeCacheOp == null) { - var options = new BCWriteCacheOptions(); - options.Bundle = Bundle; - options.FilePath = Url; + var options = new BCWriteCacheOptions(Bundle, Url); _writeCacheOp = _fileSystem.BundleCache.WriteCacheAsync(options); _writeCacheOp.StartOperation(); AddChildOperation(_writeCacheOp); @@ -110,7 +111,7 @@ namespace YooAsset { // 注意:不中断下载任务,保持下载后台继续下载 // 注意:上层异步操作会被动失败 - YooLogger.Error($"Attempting to load bundle {Bundle.BundleName} from remote: {Url}"); + YooLogger.LogError($"Attempting to load bundle '{Bundle.BundleName}' from remote: '{Url}'."); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/ApplicationFootprint.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/ApplicationFootprint.cs index 34d99bfb..3966e4ed 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/ApplicationFootprint.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/ApplicationFootprint.cs @@ -11,6 +11,10 @@ namespace YooAsset private readonly string _filePath; private string _footprint; + /// + /// 创建实例 + /// + /// 足迹文件路径 public ApplicationFootprint(string filePath) { _filePath = filePath; @@ -23,7 +27,15 @@ namespace YooAsset { if (File.Exists(_filePath)) { - _footprint = FileUtility.ReadAllText(_filePath); + try + { + _footprint = FileUtility.ReadAllText(_filePath); + } + catch (System.Exception ex) + { + _footprint = string.Empty; + YooLogger.LogError($"Failed to read application footprint file: {ex.Message}."); + } } else { @@ -36,11 +48,7 @@ namespace YooAsset /// public bool IsDirty() { -#if UNITY_EDITOR - return _footprint != Application.version; -#else - return _footprint != Application.buildGUID; -#endif + return _footprint != GetApplicationIdentifier(); } /// @@ -48,13 +56,25 @@ namespace YooAsset /// public void Overwrite(string packageName) { + _footprint = GetApplicationIdentifier(); + try + { + FileUtility.WriteAllText(_filePath, _footprint); + YooLogger.Log($"Saved application footprint: '{_footprint}'."); + } + catch (System.Exception ex) + { + YooLogger.LogWarning($"Failed to save application footprint file: {ex.Message}."); + } + } + + private static string GetApplicationIdentifier() + { #if UNITY_EDITOR - _footprint = Application.version; + return Application.version; #else - _footprint = Application.buildGUID; + return Application.buildGUID; #endif - FileUtility.WriteAllText(_filePath, _footprint); - YooLogger.Log($"Save application footprint: {_footprint}"); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadAndCacheFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadAndCacheFileOperation.cs index 8ec9d74c..742a5c44 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadAndCacheFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadAndCacheFileOperation.cs @@ -111,9 +111,7 @@ namespace YooAsset { if (_writeCacheOp == null) { - var options = new BCWriteCacheOptions(); - options.Bundle = Bundle; - options.FilePath = _tempFilePath; + var options = new BCWriteCacheOptions(Bundle, _tempFilePath); _writeCacheOp = _fileSystem.BundleCache.WriteCacheAsync(options); _writeCacheOp.StartOperation(); AddChildOperation(_writeCacheOp); @@ -152,7 +150,7 @@ namespace YooAsset { // 注意:不中断下载任务,保持下载后台继续下载 // 注意:上层异步操作会被动失败 - YooLogger.Error($"Attempting to load bundle {Bundle.BundleName} from remote: {Url}"); + YooLogger.LogError($"Attempting to load bundle '{Bundle.BundleName}' from remote: '{Url}'."); } } @@ -177,7 +175,14 @@ namespace YooAsset bool appendToFile = true; bool removeFileOnAbort = false; long resumeOffset = _fileOriginLength; - var args = new DownloadFileRequestArgs(Url, timeout, watchdogTime, _tempFilePath, appendToFile, removeFileOnAbort, resumeOffset); + var args = new DownloadFileRequestArgs( + url: Url, + timeout: timeout, + watchdogTimeout: watchdogTime, + savePath: _tempFilePath, + appendToFile: appendToFile, + removeFileOnAbort: removeFileOnAbort, + resumeOffset: resumeOffset); return _fileSystem.DownloadBackend.CreateFileRequest(args); } private IDownloadFileRequest CreateNormalRequest() @@ -186,7 +191,11 @@ namespace YooAsset int watchdogTime = _fileSystem.DownloadWatchdogTimeout; int timeout = 0; //注意:文件下载不做超时检测 - var args = new DownloadFileRequestArgs(Url, timeout, watchdogTime, _tempFilePath); + var args = new DownloadFileRequestArgs( + url: Url, + timeout: timeout, + watchdogTimeout: watchdogTime, + savePath: _tempFilePath); return _fileSystem.DownloadBackend.CreateFileRequest(args); } private void DeleteTempFile() diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageHashOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageHashOperation.cs index 3c38c4a6..f2afc709 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageHashOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageHashOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 下载包裹哈希文件操作 /// - internal class DownloadPackageHashOperation : AsyncOperationBase + internal sealed class DownloadPackageHashOperation : AsyncOperationBase { private enum ESteps { @@ -59,6 +59,8 @@ namespace YooAsset { if (_downloadFileRequest == null) { + FileUtility.EnsureParentDirectoryExists(_tempPath); + // 删除历史临时文件 if (File.Exists(_tempPath)) File.Delete(_tempPath); @@ -66,7 +68,11 @@ namespace YooAsset string fileName = YooAssetConfiguration.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion); string webURL = GetWebRequestUrl(fileName); int watchdogTime = _fileSystem.DownloadWatchdogTimeout; - var args = new DownloadFileRequestArgs(webURL, _timeout, watchdogTime, _tempPath); + var args = new DownloadFileRequestArgs( + url: webURL, + timeout: _timeout, + watchdogTimeout: watchdogTime, + savePath: _tempPath); _downloadFileRequest = _fileSystem.DownloadBackend.CreateFileRequest(args); _downloadFileRequest.SendRequest(); } @@ -104,7 +110,7 @@ namespace YooAsset if (TextUtility.ValidateContent(content, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Downloaded package hash file validation failed: {validateError}"); + SetError($"Downloaded package hash file validation failed: {validateError}."); DeleteTempFile(); return; } @@ -121,7 +127,7 @@ namespace YooAsset catch (System.Exception ex) { _steps = ESteps.Done; - SetError($"Failed to move hash temp file to cache path: {ex.Message}"); + SetError($"Failed to move hash temp file to cache path: {ex.Message}."); DeleteTempFile(); } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageManifestOperation.cs index dc1a05a7..26f54cd0 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/DownloadPackageManifestOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 下载包裹清单文件操作 /// - internal class DownloadPackageManifestOperation : AsyncOperationBase + internal sealed class DownloadPackageManifestOperation : AsyncOperationBase { private enum ESteps { @@ -59,6 +59,8 @@ namespace YooAsset { if (_downloadFileRequest == null) { + FileUtility.EnsureParentDirectoryExists(_tempPath); + // 删除历史临时文件 if (File.Exists(_tempPath)) File.Delete(_tempPath); @@ -66,7 +68,11 @@ namespace YooAsset string fileName = YooAssetConfiguration.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion); string webURL = GetDownloadRequestUrl(fileName); int watchdogTime = _fileSystem.DownloadWatchdogTimeout; - var args = new DownloadFileRequestArgs(webURL, _timeout, watchdogTime, _tempPath); + var args = new DownloadFileRequestArgs( + url: webURL, + timeout: _timeout, + watchdogTimeout: watchdogTime, + savePath: _tempPath); _downloadFileRequest = _fileSystem.DownloadBackend.CreateFileRequest(args); _downloadFileRequest.SendRequest(); } @@ -91,10 +97,17 @@ namespace YooAsset { // 验证临时文件存在且大小有效 FileInfo fileInfo = new FileInfo(_tempPath); - if (fileInfo.Exists == false || fileInfo.Length == 0) + if (fileInfo.Exists == false) { _steps = ESteps.Done; - SetError("Downloaded package manifest temp file is invalid."); + SetError("Downloaded package manifest temp file does not exist."); + return; + } + + if (fileInfo.Length < PackageManifestConsts.MinFileSize) + { + _steps = ESteps.Done; + SetError($"Downloaded manifest file is too small ({fileInfo.Length} bytes), possibly corrupted."); DeleteTempFile(); return; } @@ -111,7 +124,7 @@ namespace YooAsset catch (System.Exception ex) { _steps = ESteps.Done; - SetError($"Failed to move manifest temp file to cache path: {ex.Message}"); + SetError($"Failed to move manifest temp file to cache path: {ex.Message}."); DeleteTempFile(); } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/ImportAndCacheFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/ImportAndCacheFileOperation.cs index 8a792063..111e20ec 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/ImportAndCacheFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/ImportAndCacheFileOperation.cs @@ -62,11 +62,11 @@ namespace YooAsset catch (System.Exception ex) { _steps = ESteps.Done; - SetError($"Failed to copy local file: {ex.Message}"); + LatestReport = DownloadReport.CreateFinished(-1, ex.Message, 0, 0f); + SetError($"Failed to copy local file: {ex.Message}."); // 注意:拷贝失败后直接删除临时文件 - if (File.Exists(_tempFilePath)) - File.Delete(_tempFilePath); + DeleteTempFile(); } } @@ -75,9 +75,7 @@ namespace YooAsset { if (_bundleCacheOp == null) { - var options = new BCWriteCacheOptions(); - options.Bundle = Bundle; - options.FilePath = _tempFilePath; + var options = new BCWriteCacheOptions(Bundle, _tempFilePath); _bundleCacheOp = _fileSystem.BundleCache.WriteCacheAsync(options); _bundleCacheOp.StartOperation(); AddChildOperation(_bundleCacheOp); @@ -102,13 +100,25 @@ namespace YooAsset } // 注意:缓存完成后直接删除临时文件 - if (File.Exists(_tempFilePath)) - File.Delete(_tempFilePath); + DeleteTempFile(); } } protected override void InternalWaitForCompletion() { ExecuteBatch(); } + + private void DeleteTempFile() + { + try + { + if (File.Exists(_tempFilePath)) + File.Delete(_tempFilePath); + } + catch (System.Exception ex) + { + YooLogger.LogWarning($"Failed to delete temp file '{_tempFilePath}': {ex.Message}."); + } + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageHashOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageHashOperation.cs index 13d4c90f..58ee3979 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageHashOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageHashOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 加载缓存包裹哈希文件操作 /// - internal class LoadCachePackageHashOperation : AsyncOperationBase + internal sealed class LoadCachePackageHashOperation : AsyncOperationBase { private enum ESteps { @@ -44,7 +44,7 @@ namespace YooAsset if (File.Exists(filePath) == false) { _steps = ESteps.Done; - SetError($"Cannot find cache package hash file: {filePath}"); + SetError($"Could not find cache package hash file: '{filePath}'."); return; } @@ -52,7 +52,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageHash, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Cache package hash file validate failed: {validateError}"); + SetError($"Cache package hash file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageManifestOperation.cs index e008cb08..c7a17ce1 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/LoadCachePackageManifestOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 加载缓存包裹清单文件操作 /// - internal class LoadCachePackageManifestOperation : AsyncOperationBase + internal sealed class LoadCachePackageManifestOperation : AsyncOperationBase { private enum ESteps { @@ -49,13 +49,21 @@ namespace YooAsset string manifestFilePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion); if (File.Exists(manifestFilePath)) { - _steps = ESteps.VerifyFileData; - _fileData = File.ReadAllBytes(manifestFilePath); + try + { + _fileData = File.ReadAllBytes(manifestFilePath); + _steps = ESteps.VerifyFileData; + } + catch (System.Exception ex) + { + _steps = ESteps.Done; + SetError($"Failed to read cache package manifest file: {ex.Message}."); + } } else { _steps = ESteps.Done; - SetError($"Cannot find cache manifest file: {manifestFilePath}"); + SetError($"Could not find cache manifest file: '{manifestFilePath}'."); } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/RequestRemotePackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/RequestRemotePackageVersionOperation.cs index 69c47fe9..1be49bd2 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/RequestRemotePackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/Internal/RequestRemotePackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 请求远端包裹版本操作 /// - internal class RequestRemotePackageVersionOperation : AsyncOperationBase + internal sealed class RequestRemotePackageVersionOperation : AsyncOperationBase { private enum ESteps { @@ -22,7 +22,7 @@ namespace YooAsset /// /// 包裹版本 /// - internal string PackageVersion { set; get; } + internal string PackageVersion { get; set; } internal RequestRemotePackageVersionOperation(SandboxFileSystem fileSystem, bool appendTimeTicks, int timeout) @@ -47,7 +47,10 @@ namespace YooAsset string fileName = YooAssetConfiguration.GetPackageVersionFileName(_fileSystem.PackageName); string url = GetWebRequestUrl(fileName); int watchDogTime = _fileSystem.DownloadWatchdogTimeout; - var args = new DownloadDataRequestArgs(url, _timeout, watchDogTime); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _timeout, + watchdogTimeout: watchDogTime); _downloadTextRequest = _fileSystem.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -62,7 +65,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageVersion, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Remote package version file validation failed: {validateError}"); + SetError($"Remote package version file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSClearCacheOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSClearCacheOperation.cs index 0ef1146a..d61dc309 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSClearCacheOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 沙盒文件系统的清理缓存操作 /// - internal class SFSClearCacheOperation : FSClearCacheOperation + internal sealed class SFSClearCacheOperation : FSClearCacheOperation { private enum ESteps { @@ -77,7 +77,7 @@ namespace YooAsset /// /// 沙盒文件系统的清理所有缓存清单操作 /// - internal class SFSClearAllCacheManifestOperation : FSClearCacheOperation + internal sealed class SFSClearAllCacheManifestOperation : FSClearCacheOperation { private enum ESteps { @@ -106,7 +106,7 @@ namespace YooAsset { try { - //TODO 如果正在下载资源清单,会有几率触发异常! + // TODO: 如果正在下载资源清单,会有几率触发异常! string directoryRoot = _fileSystem.GetCacheManifestFilesRoot(); DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot); if (directoryInfo.Exists) @@ -136,7 +136,7 @@ namespace YooAsset /// /// 沙盒文件系统的清理未使用缓存清单操作 /// - internal class SFSClearUnusedCacheManifestOperation : FSClearCacheOperation + internal sealed class SFSClearUnusedCacheManifestOperation : FSClearCacheOperation { private enum ESteps { @@ -169,7 +169,7 @@ namespace YooAsset if (_manifest == null) { _steps = ESteps.Done; - SetError("Cannot find active package manifest."); + SetError("Could not find active package manifest."); } else { @@ -184,7 +184,7 @@ namespace YooAsset string activeManifestFileName = YooAssetConfiguration.GetManifestBinaryFileName(_manifest.PackageName, _manifest.PackageVersion); string activeHashFileName = YooAssetConfiguration.GetPackageHashFileName(_manifest.PackageName, _manifest.PackageVersion); - //TODO 如果正在下载资源清单,会有几率触发异常! + // TODO: 如果正在下载资源清单,会有几率触发异常! string directoryRoot = _fileSystem.GetCacheManifestFilesRoot(); DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot); if (directoryInfo.Exists) diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSDownloadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSDownloadBundleOperation.cs index 97aad365..30fcff97 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSDownloadBundleOperation.cs @@ -5,9 +5,9 @@ namespace YooAsset /// /// 沙盒文件系统的下载文件操作 /// - internal class SFSDownloadBundleOperation : FSDownloadBundleOperation + internal sealed class SFSDownloadBundleOperation : FSDownloadBundleOperation { - protected enum ESteps + private enum ESteps { None, CheckExists, @@ -61,7 +61,7 @@ namespace YooAsset if (string.IsNullOrEmpty(_options.ImportFilePath)) { // 下载远端文件 - string url = GetRequestUrl(Bundle.FileName); + string url = GetRequestUrl(Bundle.GetFileName()); _downloadFileOp = new DownloadAndCacheFileOperation(_fileSystem, Bundle, url); _fileSystem.DownloadScheduler.RegisterDownloadOperation(_downloadFileOp); } @@ -82,7 +82,9 @@ namespace YooAsset if (IsWaitForCompletion) _downloadFileOp.WaitForCompletion(); - _downloadFileOp.UpdateOperation(); + // 注意:不主动调用 _downloadFileOp.UpdateOperation() + // 说明:下载任务由 DownloadSchedulerOperation 统一驱动,此处仅读取状态。 + // 说明:同步等待由 WaitForCompletion() 内部的 ExecuteBatch() 保证。 Progress = _downloadFileOp.Progress; Report = _downloadFileOp.LatestReport; if (_downloadFileOp.IsDone == false) @@ -96,20 +98,30 @@ namespace YooAsset } else { - string url = _downloadFileOp.Url; - long httpCode = _downloadFileOp.LatestReport.HttpCode; - string httpError = _downloadFileOp.LatestReport.HttpError; - _fileSystem.DownloadUrlPolicy.OnRequestFailed(url, httpCode, httpError); - if (IsWaitForCompletion == false && _downloadRetryController.CanRetryRequest(url, httpCode, httpError)) - { - _downloadRetryController.StartRetryDelay(); - _steps = ESteps.TryAgain; - } - else + // 注意:本地导入失败时跳过重试策略 + if (string.IsNullOrEmpty(_options.ImportFilePath) == false) { _steps = ESteps.Done; SetError(_downloadFileOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); + } + else + { + string url = _downloadFileOp.Url; + long httpCode = _downloadFileOp.LatestReport.HttpCode; + string httpError = _downloadFileOp.LatestReport.HttpError; + _fileSystem.DownloadUrlPolicy.OnRequestFailed(url, httpCode, httpError); + if (IsWaitForCompletion == false && _downloadRetryController.CanRetryRequest(url, httpCode, httpError)) + { + _downloadRetryController.StartRetryDelay(); + _steps = ESteps.TryAgain; + } + else + { + _steps = ESteps.Done; + SetError(_downloadFileOp.Error); + YooLogger.LogError(Error); + } } } } @@ -119,6 +131,12 @@ namespace YooAsset { if (_downloadRetryController.TickRetryDelay()) { + if (_downloadFileOp != null) + { + _downloadFileOp.Release(); + _downloadFileOp = null; + } + Progress = 0f; Report = DownloadReport.Empty; _steps = ESteps.CreateDownload; diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSInitializeOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSInitializeOperation.cs index 2ce8c165..06002f2e 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件系统的初始化操作 /// - internal class SFSInitializeOperation : FSInitializeOperation + internal sealed class SFSInitializeOperation : FSInitializeOperation { private enum ESteps { @@ -68,28 +68,28 @@ namespace YooAsset { if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.None) { - YooLogger.Warning("No action required on overwrite installation."); + YooLogger.LogWarning("No action required on overwrite installation."); } else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllCacheFiles) { _fileSystem.DeleteAllBundleFiles(); _fileSystem.DeleteAllManifestFiles(); _fileSystem.DeleteAllTempFiles(); - YooLogger.Warning("Deleted all cache files on overwrite installation."); + YooLogger.LogWarning("Deleted all cache files on overwrite installation."); } else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllBundleFiles) { _fileSystem.DeleteAllBundleFiles(); - YooLogger.Warning("Deleted all bundle files on overwrite installation."); + YooLogger.LogWarning("Deleted all bundle files on overwrite installation."); } else if (_fileSystem.InstallCleanupMode == EInstallCleanupMode.ClearAllManifestFiles) { _fileSystem.DeleteAllManifestFiles(); - YooLogger.Warning("Deleted all manifest files on overwrite installation."); + YooLogger.LogWarning("Deleted all manifest files on overwrite installation."); } else { - throw new System.NotImplementedException(_fileSystem.InstallCleanupMode.ToString()); + throw new YooInternalException($"Unhandled {nameof(EInstallCleanupMode)} value: {_fileSystem.InstallCleanupMode}."); } appFootprint.Overwrite(_fileSystem.PackageName); @@ -130,10 +130,10 @@ namespace YooAsset if (_fileSystem.DownloadScheduler == null) { var schedulerConfig = new DownloadSchedulerOperation.Configuration( - _fileSystem.GetType().Name, - _fileSystem.DownloadBackend, - _fileSystem.DownloadMaxConcurrency, - _fileSystem.DownloadMaxRequestsPerFrame); + schedulerName: _fileSystem.GetType().Name, + downloadBackend: _fileSystem.DownloadBackend, + maxConcurrency: _fileSystem.DownloadMaxConcurrency, + maxRequestsPerFrame: _fileSystem.DownloadMaxRequestsPerFrame); _fileSystem.DownloadScheduler = new DownloadSchedulerOperation(schedulerConfig); AsyncOperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadScheduler); } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageBundleOperation.cs index 7b567bd3..128b2443 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件系统的加载资源包操作 /// - internal class SFSLoadPackageBundleOperation : FSLoadPackageBundleOperation + internal sealed class SFSLoadPackageBundleOperation : FSLoadPackageBundleOperation { private enum ESteps { @@ -48,8 +48,8 @@ namespace YooAsset if (_fileSystem.DisableOnDemandDownload) { _steps = ESteps.Done; - SetError($"The bundle is not cached: {_options.Bundle.BundleName}"); - YooLogger.Warning(Error); + SetError($"Bundle is not cached: '{_options.Bundle.BundleName}'."); + YooLogger.LogWarning(Error); } else { @@ -136,7 +136,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError("Fatal error: loaded bundle handle is null."); - YooLogger.Error(Error); + YooLogger.LogError(Error); } else { @@ -149,7 +149,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError(_loadBundleOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageManifestOperation.cs index c0423c88..12918269 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSLoadPackageManifestOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 沙盒文件系统的加载包裹清单操作 /// - internal class SFSLoadPackageManifestOperation : FSLoadPackageManifestOperation + internal sealed class SFSLoadPackageManifestOperation : FSLoadPackageManifestOperation { private enum ESteps { @@ -151,14 +151,14 @@ namespace YooAsset string manifestFilePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion); if (File.Exists(manifestFilePath)) { - YooLogger.Warning($"Invalid package manifest file has been removed: {manifestFilePath}"); + YooLogger.LogWarning($"Invalid package manifest file has been removed: '{manifestFilePath}'."); File.Delete(manifestFilePath); } string hashFilePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion); if (File.Exists(hashFilePath)) { - YooLogger.Warning($"Invalid package hash file has been removed: {hashFilePath}"); + YooLogger.LogWarning($"Invalid package hash file has been removed: '{hashFilePath}'."); File.Delete(hashFilePath); } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSRequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSRequestPackageVersionOperation.cs index 4d388fb4..adb84e19 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSRequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/Operations/SFSRequestPackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件系统的查询包裹版本操作 /// - internal class SFSRequestPackageVersionOperation : FSRequestPackageVersionOperation + internal sealed class SFSRequestPackageVersionOperation : FSRequestPackageVersionOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystem.cs index b780997c..f7f99c7c 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystem.cs @@ -1,31 +1,49 @@ using System; using System.IO; using System.Collections.Generic; -using System.Linq; using UnityEngine; namespace YooAsset { /// - /// 沙盒文件系统 + /// 沙盒文件系统,管理沙盒目录下的资源文件存储与访问。 /// internal class SandboxFileSystem : IFileSystem { + /// + /// 临时文件路径映射表 + /// protected readonly Dictionary _tempFilePathMapping = new Dictionary(10000); + + /// + /// 包裹根目录路径 + /// protected string _packageRoot; + + /// + /// 临时文件根目录路径 + /// protected string _tempFilesRoot; + + /// + /// 缓存清单文件根目录路径 + /// protected string _cacheManifestFilesRoot; + + /// + /// 缓存资源包文件根目录路径 + /// protected string _cacheBundleFilesRoot; /// - /// 沙盒Bundle缓存系统 + /// 沙盒 Bundle 缓存系统 /// public IBundleCache BundleCache { get; private set; } /// /// 下载调度器 /// - public DownloadSchedulerOperation DownloadScheduler { get; set; } + public DownloadSchedulerOperation DownloadScheduler { get; internal set; } /// /// 下载后台接口 @@ -59,10 +77,11 @@ namespace YooAsset public EFileVerifyLevel FileVerifyLevel { get; private set; } = EFileVerifyLevel.Low; /// - /// 自定义参数:初始化的时候缓存文件校验最大并发数 - /// 默认值:8(推荐值为处理器数两倍) - /// 说明:过大的值可能导致线程池任务过多,影响系统稳定性 + /// 自定义参数:初始化时缓存文件校验的最大并发数 /// + /// + /// 默认值:8(推荐值为处理器数两倍)。过大的值可能导致线程池任务过多,影响系统稳定性。 + /// public int FileVerifyMaxConcurrency { get; private set; } = 8; /// @@ -72,16 +91,18 @@ namespace YooAsset /// /// 自定义参数:最大并发连接数 - /// 默认值:8(推荐范围 1-32) - /// 说明:过大的并发数可能被服务器限流,也会增加本地资源消耗 /// + /// + /// 默认值:8(推荐范围 1-32)。过大的并发数可能被服务器限流,也会增加本地资源消耗。 + /// public int DownloadMaxConcurrency { get; private set; } = 8; /// /// 自定义参数:每帧发起的最大请求数 - /// 默认值:8(推荐范围 1-32) - /// 说明:避免单帧发起过多请求导致卡顿 /// + /// + /// 默认值:8(推荐范围 1-32)。避免单帧发起过多请求导致卡顿。 + /// public int DownloadMaxRequestsPerFrame { get; private set; } = 8; /// @@ -97,17 +118,17 @@ namespace YooAsset /// /// 自定义参数:AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; private set; } /// /// 自定义参数:RawBundle 解密器 /// - public IBundleDecryptor RawBundleDecryptor { get; set; } + public IBundleDecryptor RawBundleDecryptor { get; private set; } /// /// 自定义参数:AssetBundle 备用解密器 /// - public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; } + public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; private set; } /// /// 自定义参数:资源清单解密器 @@ -125,41 +146,44 @@ namespace YooAsset public IDownloadUrlPolicy DownloadUrlPolicy { get; private set; } #endregion + /// + /// 创建实例 + /// public SandboxFileSystem() { } /// - public virtual FSInitializeOperation InitializeAsync() + public FSInitializeOperation InitializeAsync() { var operation = new SFSInitializeOperation(this); return operation; } /// - public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) + public FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) { var operation = new SFSRequestPackageVersionOperation(this, options.AppendTimeTicks, options.Timeout); return operation; } /// - public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) + public FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) { var operation = new SFSLoadPackageManifestOperation(this, options.PackageVersion, options.Timeout); return operation; } /// - public virtual FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) + public FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) { var operation = new SFSLoadPackageBundleOperation(this, options); return operation; } /// - public virtual FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) + public FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) { var downloader = new SFSDownloadBundleOperation(this, options); return downloader; } /// - public virtual FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) + public FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) { if (options.ClearMethod == ClearCacheMethods.ClearAllManifestFiles) { @@ -179,34 +203,34 @@ namespace YooAsset } /// - public virtual void SetParameter(string paramName, object value) + public void SetParameter(string paramName, object value) { if (paramName == FileSystemConsts.DOWNLOAD_BACKEND) { - DownloadBackend = (IDownloadBackend)value; + DownloadBackend = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.UNITY_WEB_REQUEST_CREATOR) { - WebRequestCreator = (UnityWebRequestCreator)value; + WebRequestCreator = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.REMOTE_SERVICE) { - RemoteService = (IRemoteService)value; + RemoteService = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.INSTALL_CLEANUP_MODE) { - InstallCleanupMode = (EInstallCleanupMode)value; + InstallCleanupMode = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.FILE_VERIFY_LEVEL) { - FileVerifyLevel = (EFileVerifyLevel)value; + FileVerifyLevel = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.FILE_VERIFY_MAX_CONCURRENCY) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"FILE_VERIFY_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"FILE_VERIFY_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -214,14 +238,14 @@ namespace YooAsset } else if (paramName == FileSystemConsts.DOWNLOAD_DISABLE_ONDEMAND) { - DisableOnDemandDownload = Convert.ToBoolean(value); + DisableOnDemandDownload = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_MAX_CONCURRENCY) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -229,10 +253,10 @@ namespace YooAsset } else if (paramName == FileSystemConsts.DOWNLOAD_MAX_REQUEST_PER_FRAME) { - int convertValue = Convert.ToInt32(value); + int convertValue = FileSystemHelper.CastParameter(paramName, value); if (convertValue > 32) { - YooLogger.Warning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); + YooLogger.LogWarning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32."); } // 限制在合理范围内:1-32 @@ -240,44 +264,50 @@ namespace YooAsset } else if (paramName == FileSystemConsts.DOWNLOAD_WATCHDOG_TIMEOUT) { - int convertValue = Convert.ToInt32(value); - DownloadWatchdogTimeout = Mathf.Clamp(convertValue, 0, int.MaxValue); + int convertValue = FileSystemHelper.CastParameter(paramName, value); + if (convertValue < 1) + { + YooLogger.LogWarning($"DOWNLOAD_WATCHDOG_TIMEOUT value '{convertValue}' is too small, clamped to 1."); + } + + // 限制在合理范围内:1-max + DownloadWatchdogTimeout = Mathf.Clamp(convertValue, 1, int.MaxValue); } else if (paramName == FileSystemConsts.DOWNLOAD_RESUME_MINIMUM_SIZE) { - ResumeDownloadMinimumSize = Convert.ToInt64(value); + ResumeDownloadMinimumSize = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.ASSETBUNDLE_DECRYPTOR) { - AssetBundleDecryptor = (IBundleDecryptor)value; + AssetBundleDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.RAWBUNDLE_DECRYPTOR) { - RawBundleDecryptor = (IBundleDecryptor)value; + RawBundleDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.ASSETBUNDLE_FALLBACK_DECRYPTOR) { - AssetBundleFallbackDecryptor = (IBundleMemoryDecryptor)value; + AssetBundleFallbackDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.MANIFEST_DECRYPTOR) { - ManifestDecryptor = (IManifestDecryptor)value; + ManifestDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_RETRY_POLICY) { - DownloadRetryPolicy = (IDownloadRetryPolicy)value; + DownloadRetryPolicy = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_URL_POLICY) { - DownloadUrlPolicy = (IDownloadUrlPolicy)value; + DownloadUrlPolicy = FileSystemHelper.CastParameter(paramName, value); } else { - YooLogger.Warning($"Invalid parameter: {paramName}"); + throw new ArgumentException($"Unrecognized parameter name: '{paramName}'.", nameof(paramName)); } } /// - public virtual void OnCreate(string packageName, string packageRoot) + public void OnCreate(string packageName, string packageRoot) { PackageName = packageName; @@ -304,17 +334,17 @@ namespace YooAsset // 创建文件缓存系统 { - var cacheConfig = new SandboxBundleCache.Configuration(); - cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency; - cacheConfig.FileVerifyLevel = FileVerifyLevel; - cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor; - cacheConfig.RawBundleDecryptor = RawBundleDecryptor; - cacheConfig.AssetBundleFallbackDecryptor = AssetBundleFallbackDecryptor; + var cacheConfig = new SandboxBundleCache.Configuration( + fileVerifyMaxConcurrency: FileVerifyMaxConcurrency, + fileVerifyLevel: FileVerifyLevel, + assetBundleDecryptor: AssetBundleDecryptor, + rawBundleDecryptor: RawBundleDecryptor, + assetBundleFallbackDecryptor: AssetBundleFallbackDecryptor); BundleCache = new SandboxBundleCache(PackageName, _cacheBundleFilesRoot, cacheConfig); } } /// - public virtual void OnDestroy() + public void OnDestroy() { if (BundleCache != null) { @@ -336,23 +366,23 @@ namespace YooAsset } /// - public virtual bool CanAcceptBundle(PackageBundle bundle) + public bool CanAcceptBundle(PackageBundle bundle) { // 注意:保底加载! return true; } /// - public virtual bool IsDownloadRequired(PackageBundle bundle) + public bool IsDownloadRequired(PackageBundle bundle) { return BundleCache.IsCached(bundle.BundleGuid) == false; } /// - public virtual bool IsUnpackRequired(PackageBundle bundle) + public bool IsUnpackRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsImportRequired(PackageBundle bundle) + public bool IsImportRequired(PackageBundle bundle) { return BundleCache.IsCached(bundle.BundleGuid) == false; } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystemConsts.cs b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystemConsts.cs index 5d17bd5a..0bb5f62a 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystemConsts.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/SandboxFileSystem/SandboxFileSystemConsts.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 沙盒文件系统常量定义 /// - internal class SandboxFileSystemConsts + internal static class SandboxFileSystemConsts { /// /// 记录应用程序版本的文件名称 diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSInitializeOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSInitializeOperation.cs index 7c66d21d..8fc625a0 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web远端文件系统的初始化操作 /// - internal class WRFSInitializeOperation : FSInitializeOperation + internal sealed class WRFSInitializeOperation : FSInitializeOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageBundleOperation.cs index d164cba5..fff6d10b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web远端文件系统的加载资源包操作 /// - internal class WRFSLoadPackageBundleOperation : FSLoadPackageBundleOperation + internal sealed class WRFSLoadPackageBundleOperation : FSLoadPackageBundleOperation { private enum ESteps { @@ -51,7 +51,7 @@ namespace YooAsset if (_loadBundleOp.BundleHandle == null) { _steps = ESteps.Done; - SetError($"Loaded bundle handle is null."); + SetError("Fatal error: loaded bundle handle is null."); } else { @@ -73,7 +73,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError("WebGL platform does not support synchronous loading."); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageManifestOperation.cs index 020bb1b1..b43ef3e0 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSLoadPackageManifestOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web远端文件系统的加载包裹清单操作 /// - internal class WRFSLoadPackageManifestOperation : FSLoadPackageManifestOperation + internal sealed class WRFSLoadPackageManifestOperation : FSLoadPackageManifestOperation { private enum ESteps { @@ -41,13 +41,13 @@ namespace YooAsset { if (_requestWebPackageHashOp == null) { - var options = new RequestWebPackageHashOptions(); - options.PackageName = _fileSystem.PackageName; - options.PackageVersion = _packageVersion; - options.Timeout = _timeout; - options.RemoteService = _fileSystem.RemoteService; - options.DownloadBackend = _fileSystem.DownloadBackend; - options.DownloadUrlPolicy = _fileSystem.DownloadUrlPolicy; + var options = new RequestWebPackageHashOptions( + packageName: _fileSystem.PackageName, + packageVersion: _packageVersion, + timeout: _timeout, + remoteService: _fileSystem.RemoteService, + downloadBackend: _fileSystem.DownloadBackend, + downloadUrlPolicy: _fileSystem.DownloadUrlPolicy); _requestWebPackageHashOp = new RequestWebPackageHashOperation(options); _requestWebPackageHashOp.StartOperation(); AddChildOperation(_requestWebPackageHashOp); @@ -72,15 +72,15 @@ namespace YooAsset { if (_loadWebPackageManifestOp == null) { - var options = new LoadWebPackageManifestOptions(); - options.PackageName = _fileSystem.PackageName; - options.PackageVersion = _packageVersion; - options.PackageHash = _requestWebPackageHashOp.PackageHash; - options.Timeout = _timeout; - options.RemoteService = _fileSystem.RemoteService; - options.ManifestDecryptor = _fileSystem.ManifestDecryptor; - options.DownloadBackend = _fileSystem.DownloadBackend; - options.DownloadUrlPolicy = _fileSystem.DownloadUrlPolicy; + var options = new LoadWebPackageManifestOptions( + packageName: _fileSystem.PackageName, + packageVersion: _packageVersion, + packageHash: _requestWebPackageHashOp.PackageHash, + timeout: _timeout, + remoteService: _fileSystem.RemoteService, + manifestDecryptor: _fileSystem.ManifestDecryptor, + downloadBackend: _fileSystem.DownloadBackend, + downloadUrlPolicy: _fileSystem.DownloadUrlPolicy); _loadWebPackageManifestOp = new LoadWebPackageManifestOperation(options); _loadWebPackageManifestOp.StartOperation(); AddChildOperation(_loadWebPackageManifestOp); diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSRequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSRequestPackageVersionOperation.cs index 830158d7..aa9997d7 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSRequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/Operations/WRFSRequestPackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web远端文件系统的查询包裹版本操作 /// - internal class WRFSRequestPackageVersionOperation : FSRequestPackageVersionOperation + internal sealed class WRFSRequestPackageVersionOperation : FSRequestPackageVersionOperation { private enum ESteps { @@ -39,13 +39,13 @@ namespace YooAsset { if (_requestWebPackageVersionOp == null) { - var options = new RequestWebPackageVersionOptions(); - options.PackageName = _fileSystem.PackageName; - options.AppendTimeTicks = _appendTimeTicks; - options.Timeout = _timeout; - options.RemoteService = _fileSystem.RemoteService; - options.DownloadBackend = _fileSystem.DownloadBackend; - options.DownloadUrlPolicy = _fileSystem.DownloadUrlPolicy; + var options = new RequestWebPackageVersionOptions( + packageName: _fileSystem.PackageName, + appendTimeTicks: _appendTimeTicks, + timeout: _timeout, + remoteService: _fileSystem.RemoteService, + downloadBackend: _fileSystem.DownloadBackend, + downloadUrlPolicy: _fileSystem.DownloadUrlPolicy); _requestWebPackageVersionOp = new RequestWebPackageVersionOperation(options); _requestWebPackageVersionOp.StartOperation(); AddChildOperation(_requestWebPackageVersionOp); diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/WebRemoteFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/WebRemoteFileSystem.cs index 6f171ffd..decff5bc 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/WebRemoteFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebRemoteFileSystem/WebRemoteFileSystem.cs @@ -5,12 +5,12 @@ using UnityEngine; namespace YooAsset { /// - /// Web远端文件系统 + /// Web远端文件系统,管理 WebRemote 平台的远程文件系统访问。 /// internal class WebRemoteFileSystem : IFileSystem { /// - /// Web文件缓存系统 + /// Web 文件缓存系统 /// public IBundleCache BundleCache { get; private set; } @@ -46,14 +46,14 @@ namespace YooAsset public EFileVerifyLevel DownloadVerifyLevel { get; private set; } = EFileVerifyLevel.Middle; /// - /// 自定义参数:远程服务接口的实例类(支持跨域下载) + /// 支持跨域下载的远程服务接口实例 /// public IRemoteService RemoteService { get; private set; } /// /// 自定义参数:AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; private set; } /// /// 自定义参数:资源清单解密器 @@ -71,98 +71,106 @@ namespace YooAsset public IDownloadUrlPolicy DownloadUrlPolicy { get; private set; } #endregion - + /// + /// 创建实例 + /// public WebRemoteFileSystem() { } /// - public virtual FSInitializeOperation InitializeAsync() + public FSInitializeOperation InitializeAsync() { var operation = new WRFSInitializeOperation(this); return operation; } /// - public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) + public FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) { var operation = new WRFSRequestPackageVersionOperation(this, options.AppendTimeTicks, options.Timeout); return operation; } /// - public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) + public FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) { var operation = new WRFSLoadPackageManifestOperation(this, options.PackageVersion, options.Timeout); return operation; } /// - public virtual FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) + public FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) { var operation = new WRFSLoadPackageBundleOperation(this, options); return operation; } /// - public virtual FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) + public FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) { var operation = new FSDownloadBundleCompleteOperation($"{nameof(WebRemoteFileSystem)} does not support download operation."); return operation; } /// - public virtual FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) + public FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) { var operation = new FSClearCacheCompleteOperation(); return operation; } /// - public virtual void SetParameter(string paramName, object value) + public void SetParameter(string paramName, object value) { if (paramName == FileSystemConsts.DOWNLOAD_BACKEND) { - DownloadBackend = (IDownloadBackend)value; + DownloadBackend = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.UNITY_WEB_REQUEST_CREATOR) { - WebRequestCreator = (UnityWebRequestCreator)value; + WebRequestCreator = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DISABLE_UNITY_WEB_CACHE) { - DisableUnityWebCache = Convert.ToBoolean(value); + DisableUnityWebCache = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_WATCHDOG_TIMEOUT) { - int convertValue = Convert.ToInt32(value); - DownloadWatchdogTimeout = Mathf.Clamp(convertValue, 0, int.MaxValue); + int convertValue = FileSystemHelper.CastParameter(paramName, value); + if (convertValue < 1) + { + YooLogger.LogWarning($"DOWNLOAD_WATCHDOG_TIMEOUT value '{convertValue}' is too small, clamped to 1."); + } + + // 限制在合理范围内:1-max + DownloadWatchdogTimeout = Mathf.Clamp(convertValue, 1, int.MaxValue); } else if (paramName == FileSystemConsts.FILE_VERIFY_LEVEL) { - DownloadVerifyLevel = (EFileVerifyLevel)value; + DownloadVerifyLevel = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.REMOTE_SERVICE) { - RemoteService = (IRemoteService)value; + RemoteService = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.ASSETBUNDLE_DECRYPTOR) { - AssetBundleDecryptor = (IBundleDecryptor)value; + AssetBundleDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.MANIFEST_DECRYPTOR) { - ManifestDecryptor = (IManifestDecryptor)value; + ManifestDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_RETRY_POLICY) { - DownloadRetryPolicy = (IDownloadRetryPolicy)value; + DownloadRetryPolicy = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_URL_POLICY) { - DownloadUrlPolicy = (IDownloadUrlPolicy)value; + DownloadUrlPolicy = FileSystemHelper.CastParameter(paramName, value); } else { - YooLogger.Warning($"Invalid parameter: {paramName}"); + throw new ArgumentException($"Unrecognized parameter name: '{paramName}'.", nameof(paramName)); } } /// - public virtual void OnCreate(string packageName, string packageRoot) + public void OnCreate(string packageName, string packageRoot) { PackageName = packageName; @@ -179,19 +187,19 @@ namespace YooAsset DownloadUrlPolicy = new DefaultDownloadUrlPolicy(); // 创建Web文件缓存系统 - var cacheConfig = new WebRemoteBundleCache.Configuration(); - cacheConfig.WatchdogTimeout = DownloadWatchdogTimeout; - cacheConfig.DisableUnityWebCache = DisableUnityWebCache; - cacheConfig.DownloadVerifyLevel = DownloadVerifyLevel; - cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor; - cacheConfig.RemoteService = RemoteService; - cacheConfig.DownloadBackend = DownloadBackend; - cacheConfig.DownloadRetryPolicy = DownloadRetryPolicy; - cacheConfig.DownloadUrlPolicy = DownloadUrlPolicy; + var cacheConfig = new WebRemoteBundleCache.Configuration( + watchdogTimeout: DownloadWatchdogTimeout, + disableUnityWebCache: DisableUnityWebCache, + downloadVerifyLevel: DownloadVerifyLevel, + assetBundleDecryptor: AssetBundleDecryptor, + remoteService: RemoteService, + downloadBackend: DownloadBackend, + downloadRetryPolicy: DownloadRetryPolicy, + downloadUrlPolicy: DownloadUrlPolicy); BundleCache = new WebRemoteBundleCache(packageName, packageRoot, cacheConfig); } /// - public virtual void OnDestroy() + public void OnDestroy() { if (BundleCache != null) { @@ -207,23 +215,23 @@ namespace YooAsset } /// - public virtual bool CanAcceptBundle(PackageBundle bundle) + public bool CanAcceptBundle(PackageBundle bundle) { // 注意:保底加载! return true; } /// - public virtual bool IsDownloadRequired(PackageBundle bundle) + public bool IsDownloadRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsUnpackRequired(PackageBundle bundle) + public bool IsUnpackRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsImportRequired(PackageBundle bundle) + public bool IsImportRequired(PackageBundle bundle) { return false; } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSInitializeOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSInitializeOperation.cs index d038b0db..5573eb81 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSInitializeOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSInitializeOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web服务端文件系统的初始化操作 /// - internal class WSFSInitializeOperation : FSInitializeOperation + internal sealed class WSFSInitializeOperation : FSInitializeOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageBundleOperation.cs index 33e42085..2afb3cb4 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageBundleOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web服务端文件系统的加载资源包操作 /// - internal class WSFSLoadPackageBundleOperation : FSLoadPackageBundleOperation + internal sealed class WSFSLoadPackageBundleOperation : FSLoadPackageBundleOperation { private enum ESteps { @@ -51,7 +51,7 @@ namespace YooAsset if (_loadBundleOp.BundleHandle == null) { _steps = ESteps.Done; - SetError($"Loaded bundle handle is null."); + SetError("Fatal error: loaded bundle handle is null."); } else { @@ -73,7 +73,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError("WebGL platform does not support synchronous loading."); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageManifestOperation.cs index 8b31a38b..2a9d877b 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSLoadPackageManifestOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web服务端文件系统的加载包裹清单操作 /// - internal class WSFSLoadPackageManifestOperation : FSLoadPackageManifestOperation + internal sealed class WSFSLoadPackageManifestOperation : FSLoadPackageManifestOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSRequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSRequestPackageVersionOperation.cs index 49e4331d..819a418d 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSRequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/WSFSRequestPackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// Web服务端文件系统的查询包裹版本操作 /// - internal class WSFSRequestPackageVersionOperation : FSRequestPackageVersionOperation + internal sealed class WSFSRequestPackageVersionOperation : FSRequestPackageVersionOperation { private enum ESteps { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/LoadWebServerPackageManifestOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/LoadWebServerPackageManifestOperation.cs index e09f3102..fab4b055 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/LoadWebServerPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/LoadWebServerPackageManifestOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 加载Web服务端包裹清单文件操作 /// - internal class LoadWebServerPackageManifestOperation : AsyncOperationBase + internal sealed class LoadWebServerPackageManifestOperation : AsyncOperationBase { private enum ESteps { @@ -51,11 +51,15 @@ namespace YooAsset { string filePath = _fileSystem.GetWebPackageManifestFilePath(_packageVersion); string url = DownloadUrlHelper.ToLocalFileUrl(filePath); - var args = new DownloadDataRequestArgs(url, _timeout, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _timeout, + watchdogTimeout: 0); _downloadBytesRequest = _fileSystem.DownloadBackend.CreateBytesRequest(args); _downloadBytesRequest.SendRequest(); } + Progress = _downloadBytesRequest.DownloadProgress; if (_downloadBytesRequest.IsDone == false) return; diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageHashOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageHashOperation.cs index f29bb7a1..490eecc9 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageHashOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageHashOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 请求Web服务端包裹哈希操作 /// - internal class RequestWebServerPackageHashOperation : AsyncOperationBase + internal sealed class RequestWebServerPackageHashOperation : AsyncOperationBase { private enum ESteps { @@ -46,7 +46,10 @@ namespace YooAsset { string filePath = _fileSystem.GetWebPackageHashFilePath(_packageVersion); string url = DownloadUrlHelper.ToLocalFileUrl(filePath); - var args = new DownloadDataRequestArgs(url, _timeout, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _timeout, + watchdogTimeout: 0); _downloadTextRequest = _fileSystem.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -61,7 +64,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageHash, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Web server package hash file validation failed: {validateError}"); + SetError($"Web server package hash file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageVersionOperation.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageVersionOperation.cs index accd1681..38f3ddd1 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/Operations/internal/RequestWebServerPackageVersionOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 请求Web服务端包裹版本操作 /// - internal class RequestWebServerPackageVersionOperation : AsyncOperationBase + internal sealed class RequestWebServerPackageVersionOperation : AsyncOperationBase { private enum ESteps { @@ -44,7 +44,10 @@ namespace YooAsset { string filePath = _fileSystem.GetWebPackageVersionFilePath(); string url = DownloadUrlHelper.ToLocalFileUrl(filePath); - var args = new DownloadDataRequestArgs(url, _timeout, 0); + var args = new DownloadDataRequestArgs( + url: url, + timeout: _timeout, + watchdogTimeout: 0); _downloadTextRequest = _fileSystem.DownloadBackend.CreateTextRequest(args); _downloadTextRequest.SendRequest(); } @@ -59,7 +62,7 @@ namespace YooAsset if (TextUtility.ValidateContent(PackageVersion, out string validateError) == false) { _steps = ESteps.Done; - SetError($"Web server package version file validation failed: {validateError}"); + SetError($"Web server package version file validation failed: {validateError}."); } else { diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/WebServerFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/WebServerFileSystem.cs index e542377f..27c1b044 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/WebServerFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebServerFileSystem/WebServerFileSystem.cs @@ -6,15 +6,22 @@ using UnityEngine; namespace YooAsset { /// - /// Web服务端文件系统 + /// Web服务端文件系统,管理 WebServer 平台的文件系统访问。 /// internal class WebServerFileSystem : IFileSystem { + /// + /// Web 文件路径映射表 + /// protected readonly Dictionary _webFilePathMapping = new Dictionary(10000); + + /// + /// 包裹根目录路径 + /// protected string _packageRoot = string.Empty; /// - /// WebBundle缓存系统 + /// Web Bundle 缓存系统 /// public IBundleCache BundleCache { get; private set; } @@ -52,7 +59,7 @@ namespace YooAsset /// /// 自定义参数:AssetBundle 解密器 /// - public IBundleDecryptor AssetBundleDecryptor { get; set; } + public IBundleDecryptor AssetBundleDecryptor { get; private set; } /// /// 自定义参数:资源清单解密器 @@ -70,94 +77,102 @@ namespace YooAsset public IDownloadUrlPolicy DownloadUrlPolicy { get; private set; } #endregion - + /// + /// 创建实例 + /// public WebServerFileSystem() { } /// - public virtual FSInitializeOperation InitializeAsync() + public FSInitializeOperation InitializeAsync() { var operation = new WSFSInitializeOperation(this); return operation; } /// - public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) + public FSRequestPackageVersionOperation RequestPackageVersionAsync(FSRequestPackageVersionOptions options) { var operation = new WSFSRequestPackageVersionOperation(this, options.Timeout); return operation; } /// - public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) + public FSLoadPackageManifestOperation LoadPackageManifestAsync(FSLoadPackageManifestOptions options) { var operation = new WSFSLoadPackageManifestOperation(this, options.PackageVersion, options.Timeout); return operation; } /// - public virtual FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) + public FSLoadPackageBundleOperation LoadPackageBundleAsync(FSLoadPackageBundleOptions options) { var operation = new WSFSLoadPackageBundleOperation(this, options); return operation; } /// - public virtual FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) + public FSDownloadBundleOperation DownloadBundleAsync(FSDownloadBundleOptions options) { var operation = new FSDownloadBundleCompleteOperation($"{nameof(WebServerFileSystem)} does not support download operation."); return operation; } /// - public virtual FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) + public FSClearCacheOperation ClearCacheAsync(FSClearCacheOptions options) { var operation = new FSClearCacheCompleteOperation(); return operation; } /// - public virtual void SetParameter(string paramName, object value) + public void SetParameter(string paramName, object value) { if (paramName == FileSystemConsts.DOWNLOAD_BACKEND) { - DownloadBackend = (IDownloadBackend)value; + DownloadBackend = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.UNITY_WEB_REQUEST_CREATOR) { - WebRequestCreator = (UnityWebRequestCreator)value; + WebRequestCreator = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DISABLE_UNITY_WEB_CACHE) { - DisableUnityWebCache = Convert.ToBoolean(value); + DisableUnityWebCache = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_WATCHDOG_TIMEOUT) { - int convertValue = Convert.ToInt32(value); - DownloadWatchdogTimeout = Mathf.Clamp(convertValue, 0, int.MaxValue); + int convertValue = FileSystemHelper.CastParameter(paramName, value); + if (convertValue < 1) + { + YooLogger.LogWarning($"DOWNLOAD_WATCHDOG_TIMEOUT value '{convertValue}' is too small, clamped to 1."); + } + + // 限制在合理范围内:1-max + DownloadWatchdogTimeout = Mathf.Clamp(convertValue, 1, int.MaxValue); } else if (paramName == FileSystemConsts.FILE_VERIFY_LEVEL) { - DownloadVerifyLevel = (EFileVerifyLevel)value; + DownloadVerifyLevel = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.ASSETBUNDLE_DECRYPTOR) { - AssetBundleDecryptor = (IBundleDecryptor)value; + AssetBundleDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.MANIFEST_DECRYPTOR) { - ManifestDecryptor = (IManifestDecryptor)value; + ManifestDecryptor = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_RETRY_POLICY) { - DownloadRetryPolicy = (IDownloadRetryPolicy)value; + DownloadRetryPolicy = FileSystemHelper.CastParameter(paramName, value); } else if (paramName == FileSystemConsts.DOWNLOAD_URL_POLICY) { - DownloadUrlPolicy = (IDownloadUrlPolicy)value; + DownloadUrlPolicy = FileSystemHelper.CastParameter(paramName, value); } else { - YooLogger.Warning($"Invalid parameter: {paramName}"); + throw new ArgumentException($"Unrecognized parameter name: '{paramName}'.", nameof(paramName)); } } /// - public virtual void OnCreate(string packageName, string packageRoot) + public void OnCreate(string packageName, string packageRoot) { PackageName = packageName; @@ -179,18 +194,18 @@ namespace YooAsset DownloadUrlPolicy = new DefaultDownloadUrlPolicy(); // 创建Web文件缓存系统 - var cacheConfig = new WebServerBundleCache.Configuration(); - cacheConfig.WatchdogTimeout = DownloadWatchdogTimeout; - cacheConfig.DisableUnityWebCache = DisableUnityWebCache; - cacheConfig.DownloadVerifyLevel = DownloadVerifyLevel; - cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor; - cacheConfig.DownloadBackend = DownloadBackend; - cacheConfig.DownloadRetryPolicy = DownloadRetryPolicy; - cacheConfig.DownloadUrlPolicy = DownloadUrlPolicy; + var cacheConfig = new WebServerBundleCache.Configuration( + watchdogTimeout: DownloadWatchdogTimeout, + disableUnityWebCache: DisableUnityWebCache, + downloadVerifyLevel: DownloadVerifyLevel, + assetBundleDecryptor: AssetBundleDecryptor, + downloadBackend: DownloadBackend, + downloadRetryPolicy: DownloadRetryPolicy, + downloadUrlPolicy: DownloadUrlPolicy); BundleCache = new WebServerBundleCache(packageName, _packageRoot, cacheConfig); } /// - public virtual void OnDestroy() + public void OnDestroy() { if (BundleCache != null) { @@ -206,22 +221,22 @@ namespace YooAsset } /// - public virtual bool CanAcceptBundle(PackageBundle bundle) + public bool CanAcceptBundle(PackageBundle bundle) { return BundleCache.IsCached(bundle.BundleGuid); } /// - public virtual bool IsDownloadRequired(PackageBundle bundle) + public bool IsDownloadRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsUnpackRequired(PackageBundle bundle) + public bool IsUnpackRequired(PackageBundle bundle) { return false; } /// - public virtual bool IsImportRequired(PackageBundle bundle) + public bool IsImportRequired(PackageBundle bundle) { return false; } diff --git a/Assets/YooAsset/Runtime/Interfaces/IBundleDecryptor.cs b/Assets/YooAsset/Runtime/Interfaces/IBundleDecryptor.cs index b2066535..ba74b6d6 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IBundleDecryptor.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IBundleDecryptor.cs @@ -6,34 +6,49 @@ namespace YooAsset /// /// 资源包解密操作的输入参数 /// - public struct BundleDecryptArgs + public readonly struct BundleDecryptArgs { /// - /// 资源包对象 + /// 资源包描述 /// - internal PackageBundle Bundle { get; set; } + internal PackageBundle Bundle { get; } /// /// 资源包的二进制数据 /// /// - /// 仅在内存解密模式下有效。 + /// 仅在内存解密模式下有效 /// - public byte[] FileData { get; set; } + public byte[] FileData { get; } /// /// 资源包的文件路径 /// - public string FilePath { get; set; } + public string FilePath { get; } + + /// + /// 创建 实例 + /// + /// 资源包描述 + /// 资源包的二进制数据 + /// 资源包的文件路径 + internal BundleDecryptArgs(PackageBundle bundle, byte[] fileData, string filePath) + { + Bundle = bundle; + FileData = fileData; + FilePath = filePath; + } } /// /// 资源包解密器的基接口,本身不包含成员。 + /// + /// /// 请实现以下派生接口之一: /// 、 /// 、 /// 。 - /// + /// public interface IBundleDecryptor { } @@ -45,10 +60,10 @@ namespace YooAsset public interface IBundleOffsetDecryptor : IBundleDecryptor { /// - /// 获取解密数据的起始偏移量(字节)。 + /// 获取解密数据的起始偏移量(字节) /// - /// 解密操作的输入参数。 - /// AssetBundle 有效数据在文件中的起始偏移量。 + /// 解密操作的输入参数 + /// AssetBundle 有效数据在文件中的起始偏移量 long GetFileOffset(BundleDecryptArgs args); } @@ -59,10 +74,10 @@ namespace YooAsset public interface IBundleMemoryDecryptor : IBundleDecryptor { /// - /// 将资源包数据解密并返回解密后的字节数组。 + /// 将资源包数据解密并返回解密后的字节数组 /// - /// 解密操作的输入参数。 - /// 解密后的资源包数据。 + /// 解密操作的输入参数 + /// 解密后的资源包数据 byte[] GetDecryptedData(BundleDecryptArgs args); } @@ -73,17 +88,20 @@ namespace YooAsset public interface IBundleStreamDecryptor : IBundleDecryptor { /// - /// 获取流式读取时使用的缓冲区大小(字节)。 + /// 获取流式读取时使用的缓冲区大小(字节) /// - /// 解密操作的输入参数。 - /// 建议的缓冲区字节数。 + /// 解密操作的输入参数 + /// 建议的缓冲区字节数 int GetBufferSize(BundleDecryptArgs args); /// - /// 创建用于解密读取的流实例。 + /// 创建用于解密读取的流实例 /// - /// 解密操作的输入参数。 - /// 可供 AssetBundle 加载使用的解密流。 + /// + /// 调用方拥有返回流的所有权,负责在使用完毕后释放资源。 + /// + /// 解密操作的输入参数 + /// 可供 AssetBundle 加载使用的解密流 Stream CreateDecryptionStream(BundleDecryptArgs args); } } diff --git a/Assets/YooAsset/Runtime/Interfaces/IBundleEncryptor.cs b/Assets/YooAsset/Runtime/Interfaces/IBundleEncryptor.cs index a4670205..87d4b120 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IBundleEncryptor.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IBundleEncryptor.cs @@ -4,33 +4,55 @@ namespace YooAsset /// /// 资源包加密操作的输入参数 /// - public struct BundleEncryptArgs + public readonly struct BundleEncryptArgs { /// /// 资源包名称 /// - internal string BundleName { get; set; } + internal string BundleName { get; } /// - /// 待加密的源文件路径。 + /// 待加密的源文件路径 /// - public string FilePath { get; set; } + public string FilePath { get; } + + /// + /// 创建 实例 + /// + /// 资源包名称 + /// 待加密的源文件路径 + internal BundleEncryptArgs(string bundleName, string filePath) + { + BundleName = bundleName; + FilePath = filePath; + } } /// /// 资源包加密操作的返回结果 /// - public struct BundleEncryptResult + public readonly struct BundleEncryptResult { /// - /// 文件是否加密 + /// 文件是否已加密 /// - public bool Encrypted { get; set; } + public bool IsEncrypted { get; } /// /// 加密后的文件数据 /// - public byte[] EncryptedFileData { get; set; } + public byte[] EncryptedFileData { get; } + + /// + /// 创建 实例 + /// + /// 文件是否已加密 + /// 加密后的文件数据,未加密时为 null。 + public BundleEncryptResult(bool isEncrypted, byte[] encryptedFileData) + { + IsEncrypted = isEncrypted; + EncryptedFileData = encryptedFileData; + } } /// @@ -42,7 +64,7 @@ namespace YooAsset /// 对指定的资源包文件执行加密 /// /// 加密操作的输入参数 - /// 包含加密状态和加密后数据的结果。 + /// 包含加密状态和加密后数据的结果 BundleEncryptResult Encrypt(BundleEncryptArgs args); } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/Interfaces/IDownloadRetryPolicy.cs b/Assets/YooAsset/Runtime/Interfaces/IDownloadRetryPolicy.cs index 0b78e3e0..d87ac478 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IDownloadRetryPolicy.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IDownloadRetryPolicy.cs @@ -2,7 +2,7 @@ namespace YooAsset { /// - /// 下载重试策略接口 + /// 下载重试策略 /// public interface IDownloadRetryPolicy { @@ -11,8 +11,8 @@ namespace YooAsset /// /// 请求地址 /// HTTP 状态码(0 表示网络中断或非 HTTP 错误) - /// HTTP 错误信息 - /// true 允许重试;false 应立即失败 + /// 服务器返回的错误描述文本 + /// true 允许重试;false 应立即失败。 bool IsRetryableError(string url, long httpCode, string httpError); /// diff --git a/Assets/YooAsset/Runtime/Interfaces/IDownloadURLPolicy.cs b/Assets/YooAsset/Runtime/Interfaces/IDownloadURLPolicy.cs index c720fbe8..ef1815c5 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IDownloadURLPolicy.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IDownloadURLPolicy.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; namespace YooAsset { /// - /// URL 选择策略接口 + /// URL 选择策略 /// public interface IDownloadUrlPolicy { /// - /// 基于内部状态从候选列表中选择本次请求应使用的 URL。 + /// 选择本次请求应使用的 URL /// /// 候选 URL 列表(至少包含一个) /// 选中的 URL @@ -25,7 +25,7 @@ namespace YooAsset /// /// 实际使用的 URL /// HTTP 状态码(0 表示网络中断或非 HTTP 错误) - /// HTTP 错误信息 + /// 服务器返回的错误描述文本 void OnRequestFailed(string url, long httpCode, string httpError); } } diff --git a/Assets/YooAsset/Runtime/Interfaces/IManifestDecryptor.cs b/Assets/YooAsset/Runtime/Interfaces/IManifestDecryptor.cs index 3173222e..c5cf083f 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IManifestDecryptor.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IManifestDecryptor.cs @@ -7,10 +7,10 @@ namespace YooAsset public interface IManifestDecryptor { /// - /// 对加密的资源清单数据执行解密。 + /// 对加密的资源清单数据执行解密 /// - /// 已加密的清单数据。 - /// 解密后的字节数组。 + /// 已加密的清单数据 + /// 解密后的字节数组 byte[] Decrypt(byte[] fileData); } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/Interfaces/IManifestEncryptor.cs b/Assets/YooAsset/Runtime/Interfaces/IManifestEncryptor.cs index 32d90c24..19ff5e44 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IManifestEncryptor.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IManifestEncryptor.cs @@ -7,10 +7,10 @@ namespace YooAsset public interface IManifestEncryptor { /// - /// 对资源清单的原始数据执行加密。 + /// 对资源清单的原始数据执行加密 /// - /// 待加密的清单数据。 - /// 加密后的字节数组。 + /// 待加密的清单数据 + /// 加密后的字节数组 byte[] Encrypt(byte[] fileData); } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/Interfaces/IRemoteService.cs b/Assets/YooAsset/Runtime/Interfaces/IRemoteService.cs index 11d4e27a..3443b613 100644 --- a/Assets/YooAsset/Runtime/Interfaces/IRemoteService.cs +++ b/Assets/YooAsset/Runtime/Interfaces/IRemoteService.cs @@ -3,15 +3,15 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 远端资源服务接口。 + /// 远端资源服务 /// public interface IRemoteService { /// /// 获取指定文件的所有远端候选地址,按优先级排序。 - /// 列表至少包含一个 URL。 /// /// 请求的文件名称 + /// 按优先级排序的远端候选地址列表,至少包含一个 URL。 IReadOnlyList GetRemoteUrls(string fileName); } } diff --git a/Assets/YooAsset/Runtime/PackageBuilder/EditorSimulateBuildInvoker.cs b/Assets/YooAsset/Runtime/PackageBuilder/EditorSimulateBuildInvoker.cs index 1cea06a2..a7172d71 100644 --- a/Assets/YooAsset/Runtime/PackageBuilder/EditorSimulateBuildInvoker.cs +++ b/Assets/YooAsset/Runtime/PackageBuilder/EditorSimulateBuildInvoker.cs @@ -1,19 +1,25 @@ +using System; namespace YooAsset { /// - /// 编辑器模拟构建的调用入口。 + /// 编辑器模拟构建的调用入口 /// - public class EditorSimulateBuildInvoker + public static class EditorSimulateBuildInvoker { /// - /// 执行编辑器模拟构建。 + /// 执行编辑器模拟构建 /// - /// 包裹名称。 - /// 构建结果。 - /// 在非编辑器平台调用时抛出。 + /// 包裹名称 + /// 构建结果 + /// + /// 此方法通过反射调用 YooAsset.Editor 程序集中的构建器,存在隐式耦合。 + /// public static PackageBuildResult Build(string packageName) { + if (packageName == null) + throw new ArgumentNullException(nameof(packageName)); + #if UNITY_EDITOR var buildParam = new PackageBuildParameters(packageName); buildParam.BuildPipelineName = "EditorSimulateBuildPipeline"; @@ -22,7 +28,7 @@ namespace YooAsset buildParam.MethodName = "SimulateBuild"; return PackageBuildInvoker.InvokeBuild(buildParam); #else - throw new System.PlatformNotSupportedException("This feature is only supported in Unity Editor platform."); + throw new PlatformNotSupportedException("This feature is only supported on the Unity Editor platform."); #endif } } diff --git a/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildInvoker.cs b/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildInvoker.cs index 82604c60..e835a2f2 100644 --- a/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildInvoker.cs +++ b/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildInvoker.cs @@ -1,35 +1,54 @@ #if UNITY_EDITOR +using System; using System.Reflection; namespace YooAsset { /// - /// 通过反射调用编辑器构建方法的静态工具类。 + /// 通过反射调用编辑器构建方法的静态工具类 /// public static class PackageBuildInvoker { /// - /// 通过反射调用指定的编辑器构建方法,执行资源包构建任务。 + /// 调用指定的编辑器构建方法,执行资源包裹构建任务。 /// - /// 构建参数。 - /// 构建结果。 + /// 构建任务的配置参数 + /// 构建结果 public static PackageBuildResult InvokeBuild(PackageBuildParameters parameters) { + if (parameters == null) + throw new ArgumentNullException(nameof(parameters)); + var assemblyName = parameters.AssemblyName; var className = parameters.TypeFullName; var methodName = parameters.MethodName; - var classType = Assembly.Load(assemblyName).GetType(className); - return (PackageBuildResult)InvokeStaticPublicMethod(classType, methodName, parameters); + + if (string.IsNullOrEmpty(assemblyName)) + throw new ArgumentException("AssemblyName must not be null or empty.", nameof(parameters)); + if (string.IsNullOrEmpty(className)) + throw new ArgumentException("TypeFullName must not be null or empty.", nameof(parameters)); + if (string.IsNullOrEmpty(methodName)) + throw new ArgumentException("MethodName must not be null or empty.", nameof(parameters)); + + var assembly = Assembly.Load(assemblyName); + var classType = assembly.GetType(className); + if (classType == null) + throw new InvalidOperationException($"Could not find type '{className}' in assembly '{assemblyName}'."); + + var result = InvokeStaticPublicMethod(classType, methodName, parameters); + if (result == null) + throw new InvalidOperationException("Build method returned null."); + if (result is not PackageBuildResult buildResult) + throw new InvalidOperationException($"Return type '{result.GetType().FullName}' does not match expected type {nameof(PackageBuildResult)}."); + return buildResult; } - private static object InvokeStaticPublicMethod(System.Type type, string method, params object[] parameters) + private static object InvokeStaticPublicMethod(Type targetType, string methodName, params object[] parameters) { - var methodInfo = type.GetMethod(method, BindingFlags.Public | BindingFlags.Static); + var methodInfo = targetType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static); if (methodInfo == null) - { - UnityEngine.Debug.LogError($"Method '{method}' not found on type '{type.FullName}'."); - return null; - } + throw new MissingMethodException($"Could not find method '{methodName}' on type '{targetType.FullName}'."); + return methodInfo.Invoke(null, parameters); } } diff --git a/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildParameters.cs b/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildParameters.cs index 3cabf5a0..d3dfb0e6 100644 --- a/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildParameters.cs +++ b/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildParameters.cs @@ -1,49 +1,60 @@ +using System; namespace YooAsset { /// - /// 资源包构建的调用参数。 + /// 资源包裹构建的调用参数 /// public class PackageBuildParameters { /// - /// 包裹名称。 + /// 包裹名称 /// - public readonly string PackageName; + public string PackageName { get; } /// - /// 构建管线名称。 + /// 构建管线名称 /// public string BuildPipelineName { get; set; } /// - /// 用户自定义数据。 - /// - public object UserData; - - /// - /// 构建类所属的程序集名称。 - /// - public string AssemblyName; - - /// - /// 构建执行的类型全称。 + /// 用户自定义数据 /// /// - /// 类型名称必须包含命名空间。 + /// 此属性为通用扩展点,调用方应自行确保存取时的类型一致性。 /// - public string TypeFullName; + public object UserData { get; set; } /// - /// 构建执行的方法名称。 + /// 构建类所属的程序集名称 + /// + public string AssemblyName { get; set; } + + /// + /// 构建执行的类型全称 /// /// - /// 目标方法必须为公开静态方法(BindingFlags.Public | BindingFlags.Static)。 + /// 类型名称必须包含命名空间 /// - public string MethodName; + public string TypeFullName { get; set; } + /// + /// 构建执行的方法名称 + /// + /// + /// 目标方法必须为公开静态方法(BindingFlags.Public | BindingFlags.Static) + /// + public string MethodName { get; set; } + + /// + /// 创建资源包裹构建参数实例 + /// + /// 包裹名称 public PackageBuildParameters(string packageName) { + if (packageName == null) + throw new ArgumentNullException(nameof(packageName)); + PackageName = packageName; } } diff --git a/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildResult.cs b/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildResult.cs index 7f78e2d9..f6400622 100644 --- a/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildResult.cs +++ b/Assets/YooAsset/Runtime/PackageBuilder/PackageBuildResult.cs @@ -2,13 +2,13 @@ namespace YooAsset { /// - /// 资源包构建的返回结果。 + /// 资源包裹构建的返回结果 /// public class PackageBuildResult { /// - /// 构建输出的资源包根目录路径。 + /// 构建输出的资源包裹根目录路径 /// - public string PackageRootDirectory { get; set; } + public string PackageRootDirectory { get; internal set; } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs index 2b24a520..b18817dc 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs @@ -1,9 +1,10 @@ +using System; using System.Collections.Generic; namespace YooAsset { /// - /// 全资源句柄,用于加载资源包内所有资源对象 + /// 全资源句柄,用于加载资源包内所有资源对象。 /// public sealed class AllAssetsHandle : HandleBase { @@ -18,13 +19,13 @@ namespace YooAsset } /// - /// 完成委托 + /// 当加载完成时触发 /// public event System.Action Completed { add { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(AllAssetsHandle)} is invalid. It may have been released or the provider was destroyed."); if (Provider.IsDone) value.Invoke(this); @@ -33,7 +34,7 @@ namespace YooAsset } remove { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(AllAssetsHandle)} is invalid. It may have been released or the provider was destroyed."); _callback -= value; } @@ -44,7 +45,7 @@ namespace YooAsset /// public void WaitForAsyncComplete() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return; Provider.WaitForCompletion(); } @@ -56,8 +57,8 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) - return null; + if (CheckValidWithWarning() == false) + return Array.Empty(); return Provider.AllAssetObjects; } } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs index dd03f744..faca862a 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs @@ -3,7 +3,7 @@ using UnityEngine; namespace YooAsset { /// - /// 资源句柄,用于管理单个资源对象的加载和访问 + /// 资源句柄,用于管理单个资源对象的加载和访问。 /// public sealed class AssetHandle : HandleBase { @@ -18,13 +18,13 @@ namespace YooAsset } /// - /// 完成委托 + /// 当加载完成时触发 /// public event System.Action Completed { add { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(AssetHandle)} is invalid. It may have been released or the provider was destroyed."); if (Provider.IsDone) value.Invoke(this); @@ -33,7 +33,7 @@ namespace YooAsset } remove { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(AssetHandle)} is invalid. It may have been released or the provider was destroyed."); _callback -= value; } @@ -44,7 +44,7 @@ namespace YooAsset /// public void WaitForAsyncComplete() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return; Provider.WaitForCompletion(); } @@ -57,7 +57,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return null; return Provider.AssetObject; } @@ -67,9 +67,10 @@ namespace YooAsset /// 获取资源对象 /// /// 资源类型 + /// 资源对象,如果句柄无效则返回 null。 public TAsset GetAssetObject() where TAsset : UnityEngine.Object { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return null; return Provider.AssetObject as TAsset; } @@ -77,6 +78,7 @@ namespace YooAsset /// /// 同步实例化游戏对象 /// + /// 实例化的游戏对象 public GameObject InstantiateSync() { var options = new InstantiateOptions(true); @@ -86,14 +88,17 @@ namespace YooAsset /// /// 同步实例化游戏对象 /// + /// 实例化选项 + /// 实例化的游戏对象 public GameObject InstantiateSync(InstantiateOptions options) { return InstantiateSyncInternal(options); } /// - /// 异步实例化游戏对象 + /// 实例化游戏对象 /// + /// 实例化操作 public InstantiateOperation InstantiateAsync() { var options = new InstantiateOptions(true); @@ -101,8 +106,10 @@ namespace YooAsset } /// - /// 异步实例化游戏对象 + /// 实例化游戏对象 /// + /// 实例化选项 + /// 实例化操作 public InstantiateOperation InstantiateAsync(InstantiateOptions options) { return InstantiateAsyncInternal(options); @@ -110,7 +117,7 @@ namespace YooAsset private GameObject InstantiateSyncInternal(InstantiateOptions options) { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return null; if (Provider.AssetObject == null) return null; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs index 340a4e28..ddf33581 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs @@ -4,7 +4,7 @@ using System.Collections; namespace YooAsset { /// - /// 资源句柄基类,提供资源加载状态查询和释放功能 + /// 资源句柄基类,提供资源加载状态查询和释放功能。 /// public abstract class HandleBase : IEnumerator, IDisposable { @@ -27,7 +27,7 @@ namespace YooAsset /// public void Release() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return; Provider.ReleaseHandle(this); @@ -47,6 +47,7 @@ namespace YooAsset /// /// 获取资源信息 /// + /// 资源信息 public AssetInfo GetAssetInfo() { return _assetInfo; @@ -59,7 +60,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return EOperationStatus.None; return Provider.Status; } @@ -72,7 +73,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return string.Empty; return Provider.Error; } @@ -85,7 +86,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return 0; return Provider.Progress; } @@ -98,7 +99,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return true; return Provider.IsDone; } @@ -119,24 +120,21 @@ namespace YooAsset } /// - /// 句柄是否有效 + /// 检查句柄是否有效,无效时输出警告日志。 /// - internal bool IsValidWithWarning + internal bool CheckValidWithWarning() { - get + if (Provider != null && Provider.IsDestroyed == false) { - if (Provider != null && Provider.IsDestroyed == false) - { - return true; - } - else - { - if (Provider == null) - YooLogger.Warning($"The handle has already been released. Asset: {_assetInfo.AssetPath}"); - else if (Provider.IsDestroyed) - YooLogger.Warning($"The provider has already been destroyed. Asset: {_assetInfo.AssetPath}"); - return false; - } + return true; + } + else + { + if (Provider == null) + YooLogger.LogWarning($"Handle has already been released. Asset: '{_assetInfo.AssetPath}'."); + else if (Provider.IsDestroyed) + YooLogger.LogWarning($"Provider has already been destroyed. Asset: '{_assetInfo.AssetPath}'."); + return false; } } @@ -144,21 +142,24 @@ namespace YooAsset /// /// 获取用于 async/await 的 Awaiter /// + /// 用于 async/await 的 Awaiter 对象 public OperationAwaiter GetAwaiter() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new InvalidOperationException("Handle is not valid."); return Provider.GetAwaiter(); } - // 协程相关 + /// bool IEnumerator.MoveNext() { return !IsDone; } + /// void IEnumerator.Reset() { } + /// object IEnumerator.Current { get { return Provider; } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleFactory.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleFactory.cs index 62afd04d..e7fe73ac 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleFactory.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleFactory.cs @@ -4,11 +4,11 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 资源句柄工厂,根据类型创建对应的句柄实例 + /// 资源句柄工厂,根据类型创建对应的句柄实例。 /// internal static class HandleFactory { - private static readonly Dictionary> _handleFactory = new Dictionary>() + private static readonly Dictionary> s_handleFactory = new Dictionary>() { { typeof(AssetHandle), op => new AssetHandle(op) }, { typeof(SceneHandle), op => new SceneHandle(op) }, @@ -21,10 +21,10 @@ namespace YooAsset /// 根据类型创建资源句柄 /// /// 资源提供者 - /// 句柄类型 + /// 要创建的句柄类型,必须是 HandleBase 的派生类型。 public static HandleBase CreateHandle(ProviderBase provider, Type type) { - if (_handleFactory.TryGetValue(type, out var factory) == false) + if (s_handleFactory.TryGetValue(type, out var factory) == false) { throw new NotImplementedException($"Handle type {type.FullName} is not supported."); } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs index e1e454ef..b172ea80 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs @@ -2,9 +2,9 @@ namespace YooAsset { /// - /// 原生文件句柄,用于访问未经 Unity 处理的原始文件 + /// 原生文件句柄,用于访问未经 Unity 处理的原始文件。 /// - public class RawFileHandle : HandleBase + public sealed class RawFileHandle : HandleBase { private System.Action _callback; @@ -17,13 +17,13 @@ namespace YooAsset } /// - /// 完成委托 + /// 当加载完成时触发 /// public event System.Action Completed { add { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(RawFileHandle)} is invalid. It may have been released or the provider was destroyed."); if (Provider.IsDone) value.Invoke(this); @@ -32,7 +32,7 @@ namespace YooAsset } remove { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(RawFileHandle)} is invalid. It may have been released or the provider was destroyed."); _callback -= value; } @@ -43,7 +43,7 @@ namespace YooAsset /// public void WaitForAsyncComplete() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return; Provider.WaitForCompletion(); } @@ -51,9 +51,10 @@ namespace YooAsset /// /// 获取原生文件的路径 /// + /// 原生文件的磁盘路径 public string GetRawFilePath() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return string.Empty; return Provider.LoadedBundleHandle.BundleFilePath; } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs index ed409c23..be6046d0 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs @@ -3,14 +3,14 @@ using UnityEngine.SceneManagement; namespace YooAsset { /// - /// 场景句柄,用于管理场景的加载、激活和卸载 + /// 场景句柄,用于管理场景的加载、激活和卸载。 /// - public class SceneHandle : HandleBase + public sealed class SceneHandle : HandleBase { private System.Action _callback; /// - /// 所属资源包名称 + /// 所属包裹名称 /// internal string PackageName { set; get; } @@ -23,13 +23,13 @@ namespace YooAsset } /// - /// 完成委托 + /// 当加载完成时触发 /// public event System.Action Completed { add { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(SceneHandle)} is invalid. It may have been released or the provider was destroyed."); if (Provider.IsDone) value.Invoke(this); @@ -38,7 +38,7 @@ namespace YooAsset } remove { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(SceneHandle)} is invalid. It may have been released or the provider was destroyed."); _callback -= value; } @@ -46,10 +46,11 @@ namespace YooAsset /// /// 等待异步执行完毕 + /// 注意:场景加载不支持异步转同步,因此此方法有意设为 internal,防止外部误用。 /// internal void WaitForAsyncComplete() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return; Provider.WaitForCompletion(); } @@ -61,7 +62,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return string.Empty; return Provider.LoadedSceneName; } @@ -74,7 +75,7 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return new Scene(); return Provider.SceneObject; } @@ -83,9 +84,10 @@ namespace YooAsset /// /// 激活场景(当同时存在多个场景时用于切换激活场景) /// + /// 是否成功激活场景 public bool ActivateScene() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return false; if (SceneObject.IsValid() && SceneObject.isLoaded) @@ -94,7 +96,7 @@ namespace YooAsset } else { - YooLogger.Warning($"Scene is invalid or not loaded: {SceneObject.name}"); + YooLogger.LogWarning($"Scene is invalid or not loaded: '{SceneObject.name}'."); return false; } } @@ -102,9 +104,10 @@ namespace YooAsset /// /// 允许场景激活 /// + /// 是否成功执行 public bool AllowSceneActivation() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return false; if (Provider is SceneProvider) @@ -114,21 +117,24 @@ namespace YooAsset } else { - throw new System.NotImplementedException(); + throw new YooInternalException($"Unexpected provider type: '{Provider.GetType().Name}'."); } return true; } /// - /// 异步卸载场景对象 - /// 注意:场景卸载成功后,会自动释放该handle的引用计数! + /// 卸载场景对象 /// + /// + /// 场景卸载成功后,会自动释放该 handle 的引用计数。 + /// + /// 卸载场景操作 public UnloadSceneOperation UnloadSceneAsync() { string packageName = GetAssetInfo().PackageName; // 如果句柄无效 - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) { string error = $"{nameof(SceneHandle)} is invalid."; var operation = new UnloadSceneOperation(error); diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs index 96e0d850..0f3a38a9 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs @@ -1,9 +1,10 @@ +using System; using System.Collections.Generic; namespace YooAsset { /// - /// 子资源句柄,用于管理资源包内子资源对象的加载和访问 + /// 子资源句柄,用于管理资源包内子资源对象的加载和访问。 /// public sealed class SubAssetsHandle : HandleBase { @@ -18,13 +19,13 @@ namespace YooAsset } /// - /// 完成委托 + /// 当加载完成时触发 /// public event System.Action Completed { add { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(SubAssetsHandle)} is invalid. It may have been released or the provider was destroyed."); if (Provider.IsDone) value.Invoke(this); @@ -33,7 +34,7 @@ namespace YooAsset } remove { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) throw new YooHandleInvalidException($"{nameof(SubAssetsHandle)} is invalid. It may have been released or the provider was destroyed."); _callback -= value; } @@ -44,7 +45,7 @@ namespace YooAsset /// public void WaitForAsyncComplete() { - if (IsValidWithWarning == false) + if (CheckValidWithWarning() == false) return; Provider.WaitForCompletion(); } @@ -57,8 +58,8 @@ namespace YooAsset { get { - if (IsValidWithWarning == false) - return null; + if (CheckValidWithWarning() == false) + return Array.Empty(); return Provider.SubAssetObjects; } } @@ -68,9 +69,12 @@ namespace YooAsset /// /// 子资源对象类型 /// 子资源对象名称 + /// 匹配的子资源对象,未找到则返回 null。 public TObject GetSubAssetObject(string assetName) where TObject : UnityEngine.Object { - if (IsValidWithWarning == false) + if (string.IsNullOrEmpty(assetName)) + throw new System.ArgumentException("Value cannot be null or empty.", nameof(assetName)); + if (CheckValidWithWarning() == false) return null; foreach (var assetObject in Provider.SubAssetObjects) @@ -79,7 +83,7 @@ namespace YooAsset return assetObject as TObject; } - YooLogger.Warning($"Sub asset object not found: {assetName}"); + YooLogger.LogWarning($"Sub asset object not found: '{assetName}'."); return null; } @@ -87,10 +91,11 @@ namespace YooAsset /// 获取所有的子资源对象集合 /// /// 子资源对象类型 - public TObject[] GetSubAssetObjects() where TObject : UnityEngine.Object + /// 匹配类型的子资源对象集合 + public IReadOnlyList GetSubAssetObjects() where TObject : UnityEngine.Object { - if (IsValidWithWarning == false) - return null; + if (CheckValidWithWarning() == false) + return Array.Empty(); List result = new List(Provider.SubAssetObjects.Length); foreach (var assetObject in Provider.SubAssetObjects) @@ -99,7 +104,7 @@ namespace YooAsset if (retObject != null) result.Add(retObject); } - return result.ToArray(); + return result; } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs index dbe4ed8b..afa6460c 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs @@ -27,7 +27,7 @@ namespace YooAsset /// /// 实例化的游戏对象 /// - public GameObject Result = null; + public GameObject Result { get; internal set; } internal InstantiateOperation(AssetHandle handle, InstantiateOptions options) @@ -46,7 +46,7 @@ namespace YooAsset if (_steps == ESteps.LoadObject) { - if (_handle.IsValidWithWarning == false) + if (_handle.CheckValidWithWarning() == false) { _steps = ESteps.Done; SetError($"{nameof(AssetHandle)} is invalid."); @@ -116,13 +116,13 @@ namespace YooAsset else { _steps = ESteps.Done; - SetError($"The instantiate result could not be cast to GameObject."); + SetError($"Instantiate result could not be cast to GameObject."); } } else { _steps = ESteps.Done; - SetError($"The async instantiate operation returned null or empty results."); + SetError($"Async instantiate operation returned null or empty results."); } } #endif @@ -176,10 +176,12 @@ namespace YooAsset #if UNITY_2023_3_OR_NEWER /// - /// 异步实例化 - /// 注意:Unity2022.3.20f1及以上版本生效 - /// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Object.InstantiateAsync.html + /// 异步实例化游戏对象 /// + /// + /// Unity2022.3.20f1 及以上版本生效。 + /// https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Object.InstantiateAsync.html + /// internal static AsyncInstantiateOperation InstantiateAsyncInternal(UnityEngine.Object assetObject, InstantiateOptions options) { if (options.SetPositionAndRotation) diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOptions.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOptions.cs index df282063..7b35900a 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOptions.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOptions.cs @@ -5,35 +5,37 @@ namespace YooAsset /// /// 游戏对象实例化选项 /// - public struct InstantiateOptions + public readonly struct InstantiateOptions { /// /// 是否激活实例化对象 /// - public bool IsActive { private set; get; } + public bool IsActive { get; } /// /// 将指定给新对象的父对象 /// - public Transform Parent { private set; get; } + public Transform Parent { get; } /// - /// 是否在世界空间中定位新对象。 - /// 为 true 时保持世界空间位置,为 false 时相对于父对象定位。 + /// 是否在世界空间中定位新对象 /// - public bool InWorldSpace { private set; get; } + /// + /// 为 true 时保持世界空间位置,为 false 时相对于父对象定位。 + /// + public bool InWorldSpace { get; } /// /// 新对象的位置 /// - public Vector3 Position { private set; get; } + public Vector3 Position { get; } /// /// 新对象的旋转 /// - public Quaternion Rotation { private set; get; } + public Quaternion Rotation { get; } - internal bool SetPositionAndRotation { private set; get; } + internal bool SetPositionAndRotation { get; } /// /// 创建实例化选项(仅指定激活状态) diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/Internal/LoadBundleOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/Internal/LoadBundleOperation.cs index 6feebc82..95c1596f 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/Internal/LoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/Internal/LoadBundleOperation.cs @@ -7,7 +7,7 @@ namespace YooAsset /// /// 资源包加载操作 /// - internal class LoadBundleOperation : AsyncOperationBase + internal sealed class LoadBundleOperation : AsyncOperationBase { private enum ESteps { @@ -94,7 +94,7 @@ namespace YooAsset if (_loadPackageBundleOp.BundleHandle == null) { _steps = ESteps.Done; - SetError($"Bundle loaded successfully but the handle is null. Bundle: {LoadBundleInfo.Bundle.BundleName}"); + SetError($"Bundle loaded successfully but the handle is null. Bundle: '{LoadBundleInfo.Bundle.BundleName}'."); } else { @@ -123,7 +123,7 @@ namespace YooAsset } /// - /// 引用(引用计数递加) + /// 增加引用计数 /// public void Reference() { @@ -131,7 +131,7 @@ namespace YooAsset } /// - /// 释放(引用计数递减) + /// 减少引用计数 /// public void Release() { @@ -139,7 +139,7 @@ namespace YooAsset } /// - /// 销毁 + /// 销毁资源包加载器并释放资源包 /// public void DestroyLoader() { @@ -147,10 +147,10 @@ namespace YooAsset // 注意:正在加载中的任务不可以销毁 if (_steps == ESteps.LoadBundleFile) - throw new YooInternalException($"Cannot destroy loader while loading bundle: {LoadBundleInfo.Bundle.BundleName}"); + throw new YooInternalException($"Cannot destroy loader while loading bundle: '{LoadBundleInfo.Bundle.BundleName}'."); if (RefCount > 0) - throw new YooInternalException($"Cannot destroy loader with non-zero ref count {RefCount}: {LoadBundleInfo.Bundle.BundleName}"); + throw new YooInternalException($"Cannot destroy loader with non-zero ref count {RefCount}: '{LoadBundleInfo.Bundle.BundleName}'."); if (BundleHandle != null) BundleHandle.UnloadBundle(); @@ -165,6 +165,7 @@ namespace YooAsset /// /// 是否可以销毁 /// + /// 如果可以安全销毁则返回 true public bool CanDestroyLoader() { if (IsReleasable() == false) @@ -193,6 +194,7 @@ namespace YooAsset /// /// 是否可以释放 /// + /// 如果引用计数为零且未在加载中则返回 true public bool IsReleasable() { // 注意:正在加载中的任务不可以销毁 @@ -208,6 +210,7 @@ namespace YooAsset /// /// 添加附属的资源提供者 /// + /// 要关联的资源提供者 public void AddProvider(ProviderBase provider) { if (_providers.Contains(provider) == false) diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs index 8c39dca6..27bc696b 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs @@ -49,16 +49,11 @@ namespace YooAsset if (_steps == ESteps.ReleaseAll) { // 清空所有场景句柄 - _resourceManager.SceneHandles.Clear(); + _resourceManager.ClearSceneHandles(); // 释放所有资源句柄 if (_options.ShouldReleaseHandles) - { - foreach (var provider in _resourceManager.ProviderDict.Values) - { - provider.ReleaseAllHandles(); - } - } + _resourceManager.ReleaseAllHandles(); _steps = ESteps.TryAbortLoader; } @@ -67,41 +62,25 @@ namespace YooAsset { // 尝试终止所有加载任务 // 注意:正在加载AssetBundle的任务无法终止 - foreach (var loader in _resourceManager.BundleLoaderDict.Values) - { - loader.TryAbortLoader(); - } + _resourceManager.TryAbortAllBundleLoaders(); _steps = ESteps.CheckLoading; } if (_steps == ESteps.CheckLoading) { // 注意:等待所有任务完成 - foreach (var provider in _resourceManager.ProviderDict.Values) - { - if (provider.IsDone == false) - return; - } + if (_resourceManager.AreAllProvidersDone() == false) + return; _steps = ESteps.DestroyAll; } if (_steps == ESteps.DestroyAll) { // 强制销毁资源提供者 - foreach (var provider in _resourceManager.ProviderDict.Values) - { - provider.DestroyProvider(); - } + _resourceManager.DestroyAllProviders(); // 强制销毁文件加载器 - foreach (var loader in _resourceManager.BundleLoaderDict.Values) - { - loader.DestroyLoader(); - } - - // 清空数据 - _resourceManager.ProviderDict.Clear(); - _resourceManager.BundleLoaderDict.Clear(); + _resourceManager.DestroyAllBundleLoaders(); _resourceManager.IsLoadingLocked = false; // 注意:调用底层接口释放所有资源 diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOptions.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOptions.cs index e178cc21..65be2802 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOptions.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOptions.cs @@ -4,17 +4,17 @@ namespace YooAsset /// /// 卸载所有资源的选项配置 /// - public struct UnloadAllAssetsOptions + public readonly struct UnloadAllAssetsOptions { /// - /// 释放所有资源句柄,防止卸载过程中触发完成回调! + /// 是否释放所有资源句柄,防止卸载过程中触发完成回调。 /// - public bool ShouldReleaseHandles { set; get; } + public bool ShouldReleaseHandles { get; } /// - /// 卸载过程中锁定加载操作,防止新的任务请求! + /// 是否在卸载过程中锁定加载操作,防止新的任务请求。 /// - public bool ShouldLockLoading { set; get; } + public bool ShouldLockLoading { get; } /// /// 创建卸载所有资源的选项 diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs index f2e820be..34dbac79 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs @@ -39,7 +39,7 @@ namespace YooAsset } else { - throw new System.NotImplementedException(); + throw new YooInternalException($"Unexpected provider type: '{provider.GetType().Name}'."); } } protected override void InternalStart() @@ -93,7 +93,7 @@ namespace YooAsset if (_asyncOp == null) { _steps = ESteps.Done; - SetError("Failed to unload scene. The UnloadSceneAsync operation returned null."); + SetError("Failed to unload scene. UnloadSceneAsync operation returned null."); return; } } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs index 58e90429..d31f4ce5 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs @@ -1,6 +1,3 @@ -using System.Collections; -using System.Collections.Generic; - namespace YooAsset { /// @@ -37,10 +34,11 @@ namespace YooAsset if (_steps == ESteps.UnloadUnused) { + // 说明:资源包之间会有深层的依赖链表,需要多次迭代才可以在单帧内卸载! while (_loopCounter > 0) { _loopCounter--; - LoopUnloadUnused(); + _resourceManager.DestroyUnusedBundle(); if (IsBusy) break; @@ -61,36 +59,5 @@ namespace YooAsset { return $"MaxLoopCount: {_options.MaxLoopCount}"; } - - /// - /// 说明:资源包之间会有深层的依赖链表,需要多次迭代才可以在单帧内卸载! - /// - private void LoopUnloadUnused() - { - var removeList = new List(_resourceManager.BundleLoaderDict.Count); - - // 注意:优先销毁资源提供者 - foreach (var loader in _resourceManager.BundleLoaderDict.Values) - { - loader.TryDestroyProviders(); - } - - // 获取销毁列表 - foreach (var loader in _resourceManager.BundleLoaderDict.Values) - { - if (loader.CanDestroyLoader()) - { - removeList.Add(loader); - } - } - - // 销毁文件加载器 - foreach (var loader in removeList) - { - string bundleName = loader.LoadBundleInfo.Bundle.BundleName; - loader.DestroyLoader(); - _resourceManager.BundleLoaderDict.Remove(bundleName); - } - } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOptions.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOptions.cs index e0a3e70b..599839bf 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOptions.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOptions.cs @@ -4,12 +4,12 @@ namespace YooAsset /// /// 卸载未使用资源的选项配置 /// - public struct UnloadUnusedAssetsOptions + public readonly struct UnloadUnusedAssetsOptions { /// /// 最大循环迭代次数 /// - public int MaxLoopCount { set; get; } + public int MaxLoopCount { get; } /// /// 创建卸载未使用资源的选项 diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/AllAssetsProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/AllAssetsProvider.cs index b138944a..b1c19b56 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/AllAssetsProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/AllAssetsProvider.cs @@ -2,7 +2,7 @@ namespace YooAsset { /// - /// 全资源提供者,负责加载资源包内所有资源 + /// 全资源提供者,负责加载资源包内所有资源。 /// internal sealed class AllAssetsProvider : ProviderBase { @@ -11,7 +11,7 @@ namespace YooAsset public AllAssetsProvider(ResourceManager manager, string providerKey, AssetInfo assetInfo) : base(manager, providerKey, assetInfo) { } - protected override void ProcessBundleHandle() + protected override void InternalProcessBundleHandle() { if (_loadAllAssetsOp == null) { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/AssetProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/AssetProvider.cs index c956c7f6..c44c5de2 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/AssetProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/AssetProvider.cs @@ -2,7 +2,7 @@ namespace YooAsset { /// - /// 资源提供者,负责加载单个资源对象 + /// 资源提供者,负责加载单个资源对象。 /// internal sealed class AssetProvider : ProviderBase { @@ -11,7 +11,7 @@ namespace YooAsset public AssetProvider(ResourceManager manager, string providerKey, AssetInfo assetInfo) : base(manager, providerKey, assetInfo) { } - protected override void ProcessBundleHandle() + protected override void InternalProcessBundleHandle() { if (_loadAssetOp == null) { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/ErrorProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/ErrorProvider.cs index e9c1612b..d50c9af3 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/ErrorProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/ErrorProvider.cs @@ -2,7 +2,7 @@ namespace YooAsset { /// - /// 错误提供者,用于处理加载失败的情况 + /// 错误提供者,用于处理加载失败的情况。 /// internal sealed class ErrorProvider : ProviderBase { @@ -15,10 +15,7 @@ namespace YooAsset { } - /// - /// 处理资源包句柄(空实现) - /// - protected override void ProcessBundleHandle() + protected override void InternalProcessBundleHandle() { } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/ProviderBase.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/ProviderBase.cs index 1425626a..d33a1169 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/ProviderBase.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/ProviderBase.cs @@ -7,11 +7,11 @@ using System; namespace YooAsset { /// - /// 资源提供者基类,负责管理资源的加载和句柄创建 + /// 资源提供者基类,负责管理资源的加载和句柄创建。 /// internal abstract class ProviderBase : AsyncOperationBase { - protected enum ESteps + private enum ESteps { None = 0, StartBundleLoader, @@ -31,7 +31,7 @@ namespace YooAsset public AssetInfo MainAssetInfo { private set; get; } /// - /// 获取的资源对象 + /// 资源对象 /// public UnityEngine.Object AssetObject { protected set; get; } @@ -46,7 +46,7 @@ namespace YooAsset public UnityEngine.Object[] SubAssetObjects { protected set; get; } /// - /// 获取的场景对象 + /// 场景对象 /// public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; } @@ -99,14 +99,14 @@ namespace YooAsset ProviderKey = providerKey; MainAssetInfo = assetInfo; + // 注意: 以下 bundle loader 初始化不可移至 InternalStart(), + // 否则共享 loader 的引用计数会出错,导致资源被提前卸载。 if (string.IsNullOrEmpty(providerKey) == false) { - // 主资源包加载器 _mainBundleLoader = manager.GetOrCreateMainBundleLoader(assetInfo); _mainBundleLoader.AddProvider(this); _bundleLoaders.Add(_mainBundleLoader); - // 依赖资源包加载器集合 var dependLoaders = manager.GetOrCreateDependBundleLoaders(assetInfo); if (dependLoaders.Count > 0) _bundleLoaders.AddRange(dependLoaders); @@ -177,7 +177,7 @@ namespace YooAsset LoadedBundleHandle = _mainBundleLoader.BundleHandle; if (LoadedBundleHandle == null) { - SetFail($"The loaded bundle handle is null. Asset: {MainAssetInfo.AssetPath}"); + SetFail($"Loaded bundle handle is null. Asset: '{MainAssetInfo.AssetPath}'."); return; } @@ -186,7 +186,7 @@ namespace YooAsset if (_steps == ESteps.ProcessBundleHandle) { - ProcessBundleHandle(); + InternalProcessBundleHandle(); } } protected override void InternalWaitForCompletion() @@ -199,9 +199,9 @@ namespace YooAsset } /// - /// 处理资源包句柄,由子类实现具体逻辑 + /// 处理资源包句柄,由子类实现具体逻辑。 /// - protected abstract void ProcessBundleHandle(); + protected abstract void InternalProcessBundleHandle(); /// /// 销毁资源提供者 @@ -214,7 +214,7 @@ namespace YooAsset if (IsDone == false) { _steps = ESteps.Done; - SetError("The operation was aborted."); + SetError("Operation was aborted."); } // 减少引用计数 @@ -227,6 +227,7 @@ namespace YooAsset /// /// 是否可以销毁 /// + /// 如果引用计数为零且未在加载中则返回 true public bool CanDestroyProvider() { // 注意:正在加载中的任务不可以销毁 @@ -239,6 +240,8 @@ namespace YooAsset /// /// 创建资源句柄 /// + /// 句柄类型,必须是 HandleBase 的派生类型。 + /// 创建的资源句柄 public T CreateHandle() where T : HandleBase { // 引用计数增加 @@ -252,13 +255,14 @@ namespace YooAsset /// /// 释放资源句柄 /// + /// 要释放的资源句柄 public void ReleaseHandle(HandleBase handle) { if (RefCount <= 0) - throw new YooInternalException($"Attempting to release handle when RefCount is already zero. Asset: {MainAssetInfo.AssetPath}"); + throw new YooInternalException($"Attempting to release handle when RefCount is already zero. Asset: '{MainAssetInfo.AssetPath}'."); if (_handles.Remove(handle) == false) - throw new YooInternalException($"Handle not found in cache list. Asset: {MainAssetInfo.AssetPath}"); + throw new YooInternalException($"Handle not found in cache list. Asset: '{MainAssetInfo.AssetPath}'."); // 引用计数减少 RefCount--; @@ -288,7 +292,7 @@ namespace YooAsset } /// - /// 结束流程 + /// 设置成功状态并触发完成回调 /// protected void SetSuccess() { @@ -298,8 +302,9 @@ namespace YooAsset } /// - /// 结束流程 + /// 设置失败状态并触发完成回调 /// + /// 错误信息 protected void SetFail(string error) { _steps = ESteps.Done; @@ -321,7 +326,7 @@ namespace YooAsset } catch (Exception ex) { - YooLogger.Error($"Exception in completion callback: {ex}"); + YooLogger.LogError($"Exception in completion callback: {ex}."); } } } @@ -331,8 +336,11 @@ namespace YooAsset /// /// 资源加载时的活跃场景名称 /// - public string SceneName = string.Empty; + public string SceneName { get; set; } = string.Empty; + /// + /// 初始化资源提供者的调试信息 + /// [Conditional("DEBUG")] public void InitProviderDebugInfo() { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/RawFileProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/RawFileProvider.cs index f2583513..fd845fab 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/RawFileProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/RawFileProvider.cs @@ -2,14 +2,14 @@ namespace YooAsset { /// - /// 原生文件提供者,负责加载原始文件资源 + /// 原生文件提供者,负责加载原始文件资源。 /// - internal class RawFileProvider : ProviderBase + internal sealed class RawFileProvider : ProviderBase { public RawFileProvider(ResourceManager manager, string providerKey, AssetInfo assetInfo) : base(manager, providerKey, assetInfo) { } - protected override void ProcessBundleHandle() + protected override void InternalProcessBundleHandle() { SetSuccess(); } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/SceneProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/SceneProvider.cs index df2b6767..4dd74a63 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/SceneProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/SceneProvider.cs @@ -7,7 +7,7 @@ using UnityEngine.SceneManagement; namespace YooAsset { /// - /// 场景提供者,负责场景资源的加载 + /// 场景提供者,负责场景资源的加载。 /// internal sealed class SceneProvider : ProviderBase { @@ -21,7 +21,7 @@ namespace YooAsset _allowSceneActivation = allowSceneActivation; LoadedSceneName = Path.GetFileNameWithoutExtension(assetInfo.AssetPath); } - protected override void ProcessBundleHandle() + protected override void InternalProcessBundleHandle() { if (_loadSceneOp == null) { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Providers/SubAssetsProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Providers/SubAssetsProvider.cs index e2f71fa1..3bc98ea7 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Providers/SubAssetsProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Providers/SubAssetsProvider.cs @@ -2,7 +2,7 @@ namespace YooAsset { /// - /// 子资源提供者,负责加载资源包内的子资源 + /// 子资源提供者,负责加载资源包内的子资源。 /// internal sealed class SubAssetsProvider : ProviderBase { @@ -11,7 +11,7 @@ namespace YooAsset public SubAssetsProvider(ResourceManager manager, string providerKey, AssetInfo assetInfo) : base(manager, providerKey, assetInfo) { } - protected override void ProcessBundleHandle() + protected override void InternalProcessBundleHandle() { if (_loadSubAssetsOp == null) { diff --git a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs index f81f0efc..209e8fe0 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs @@ -8,26 +8,16 @@ using UnityEngine.SceneManagement; namespace YooAsset { /// - /// 资源管理器 - /// 注意:此类不是线程安全的,所有方法必须在Unity主线程调用 + /// 资源管理器,负责管理资源的加载、卸载和句柄创建。 /// + /// + /// 此类不是线程安全的,所有方法必须在 Unity 主线程调用。 + /// internal class ResourceManager { - /// - /// 资源提供者字典,Key 为 ProviderKey - /// - internal readonly Dictionary ProviderDict = new Dictionary(5000); - - /// - /// 资源包加载器字典,Key 为 BundleName - /// - internal readonly Dictionary BundleLoaderDict = new Dictionary(5000); - - /// - /// 已加载的场景句柄列表 - /// - internal readonly List SceneHandles = new List(100); - + private readonly Dictionary _providerDict = new Dictionary(5000); + private readonly Dictionary _bundleLoaderDict = new Dictionary(5000); + private readonly List _sceneHandles = new List(100); private readonly List _tempSceneHandles = new List(100); private FileSystemHost _fileSystemHost; private int _bundleLoadingMaxConcurrency; @@ -35,7 +25,7 @@ namespace YooAsset private long _sceneInstanceCounter; /// - /// 当资源句柄引用计数为零时,是否自动卸载对应的资源包 + /// 当资源句柄引用计数为零时,是否自动卸载对应的资源包。 /// public bool AutoUnloadBundleWhenUnused { get; private set; } @@ -45,7 +35,7 @@ namespace YooAsset public bool WebGLForceSyncLoadAsset { get; private set; } /// - /// 所属资源包名称 + /// 所属包裹名称 /// public readonly string PackageName; @@ -58,7 +48,7 @@ namespace YooAsset /// /// 创建资源管理器实例 /// - /// 资源包名称 + /// 包裹名称 public ResourceManager(string packageName) { PackageName = packageName; @@ -67,6 +57,8 @@ namespace YooAsset /// /// 初始化 /// + /// 初始化配置选项 + /// 文件系统宿主 public void Initialize(InitializePackageOptions options, FileSystemHost host) { _fileSystemHost = host; @@ -87,16 +79,18 @@ namespace YooAsset /// /// 尝试卸载指定资源的资源包(包括依赖资源) /// + /// 要卸载的资源信息 + /// 循环尝试次数,用于处理复杂依赖链。 public void TryUnloadUnusedAsset(AssetInfo assetInfo, int loopCount) { if (assetInfo == null) { - YooLogger.Error($"{nameof(AssetInfo)} is null."); + YooLogger.LogError($"{nameof(AssetInfo)} is null."); return; } if (assetInfo.IsValid == false) { - YooLogger.Error($"Failed to unload asset. Error: {assetInfo.Error}"); + YooLogger.LogError($"Failed to unload asset. Error: {assetInfo.Error}"); return; } @@ -116,7 +110,7 @@ namespace YooAsset if (mainLoader.CanDestroyLoader()) { mainLoader.DestroyLoader(); - BundleLoaderDict.Remove(mainBundleName); + _bundleLoaderDict.Remove(mainBundleName); hasUnloaded = true; } } @@ -131,7 +125,7 @@ namespace YooAsset if (dependLoader.CanDestroyLoader()) { dependLoader.DestroyLoader(); - BundleLoaderDict.Remove(dependBundleName); + _bundleLoaderDict.Remove(dependBundleName); hasUnloaded = true; } } @@ -145,15 +139,22 @@ namespace YooAsset /// /// 加载场景对象 - /// 注意:返回的场景句柄是唯一的,每个场景句柄对应自己的场景提供者对象。 - /// 注意:业务逻辑层应该避免同时加载一个子场景。 /// + /// + /// 返回的场景句柄是唯一的,每个场景句柄对应自己的场景提供者对象。 + /// 业务逻辑层应该避免同时加载一个子场景。 + /// + /// 场景资源信息 + /// 场景加载参数 + /// 是否允许场景加载完成后自动激活 + /// 加载优先级 + /// 场景句柄 public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool allowSceneActivation, uint priority) { if (IsLoadingLocked) { string error = $"Loading is currently locked. New load requests are rejected."; - YooLogger.Error(error); + YooLogger.LogError(error); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(error); return errorProvider.CreateHandle(); @@ -161,7 +162,7 @@ namespace YooAsset if (assetInfo.IsValid == false) { - YooLogger.Error($"Failed to load scene. Error: {assetInfo.Error}"); + YooLogger.LogError($"Failed to load scene. Error: {assetInfo.Error}"); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(assetInfo.Error); return errorProvider.CreateHandle(); @@ -173,26 +174,29 @@ namespace YooAsset { provider = new SceneProvider(this, providerKey, assetInfo, loadSceneParams, allowSceneActivation); provider.InitProviderDebugInfo(); - ProviderDict.Add(providerKey, provider); + _providerDict.Add(providerKey, provider); AsyncOperationSystem.StartOperation(PackageName, provider); } provider.Priority = priority; var handle = provider.CreateHandle(); handle.PackageName = PackageName; - SceneHandles.Add(handle); + _sceneHandles.Add(handle); return handle; } /// /// 加载资源对象 /// + /// 资源信息 + /// 加载优先级 + /// 资源句柄 public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority) { if (IsLoadingLocked) { string error = $"Loading is currently locked. New load requests are rejected."; - YooLogger.Error(error); + YooLogger.LogError(error); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(error); return errorProvider.CreateHandle(); @@ -200,7 +204,7 @@ namespace YooAsset if (assetInfo.IsValid == false) { - YooLogger.Error($"Failed to load asset. Error: {assetInfo.Error}"); + YooLogger.LogError($"Failed to load asset. Error: {assetInfo.Error}"); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(assetInfo.Error); return errorProvider.CreateHandle(); @@ -212,7 +216,7 @@ namespace YooAsset { provider = new AssetProvider(this, providerKey, assetInfo); provider.InitProviderDebugInfo(); - ProviderDict.Add(providerKey, provider); + _providerDict.Add(providerKey, provider); AsyncOperationSystem.StartOperation(PackageName, provider); } @@ -223,12 +227,15 @@ namespace YooAsset /// /// 加载子资源对象 /// + /// 资源信息 + /// 加载优先级 + /// 子资源句柄 public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority) { if (IsLoadingLocked) { string error = $"Loading is currently locked. New load requests are rejected."; - YooLogger.Error(error); + YooLogger.LogError(error); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(error); return errorProvider.CreateHandle(); @@ -236,7 +243,7 @@ namespace YooAsset if (assetInfo.IsValid == false) { - YooLogger.Error($"Failed to load sub assets. Error: {assetInfo.Error}"); + YooLogger.LogError($"Failed to load sub assets. Error: {assetInfo.Error}"); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(assetInfo.Error); return errorProvider.CreateHandle(); @@ -248,7 +255,7 @@ namespace YooAsset { provider = new SubAssetsProvider(this, providerKey, assetInfo); provider.InitProviderDebugInfo(); - ProviderDict.Add(providerKey, provider); + _providerDict.Add(providerKey, provider); AsyncOperationSystem.StartOperation(PackageName, provider); } @@ -259,12 +266,15 @@ namespace YooAsset /// /// 加载所有资源对象 /// + /// 资源信息 + /// 加载优先级 + /// 全资源句柄 public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority) { if (IsLoadingLocked) { string error = $"Loading is currently locked. New load requests are rejected."; - YooLogger.Error(error); + YooLogger.LogError(error); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(error); return errorProvider.CreateHandle(); @@ -272,7 +282,7 @@ namespace YooAsset if (assetInfo.IsValid == false) { - YooLogger.Error($"Failed to load all assets. Error: {assetInfo.Error}"); + YooLogger.LogError($"Failed to load all assets. Error: {assetInfo.Error}"); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(assetInfo.Error); return errorProvider.CreateHandle(); @@ -284,7 +294,7 @@ namespace YooAsset { provider = new AllAssetsProvider(this, providerKey, assetInfo); provider.InitProviderDebugInfo(); - ProviderDict.Add(providerKey, provider); + _providerDict.Add(providerKey, provider); AsyncOperationSystem.StartOperation(PackageName, provider); } @@ -295,12 +305,15 @@ namespace YooAsset /// /// 加载原生文件 /// + /// 资源信息 + /// 加载优先级 + /// 原生文件句柄 public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority) { if (IsLoadingLocked) { string error = $"Loading is currently locked. New load requests are rejected."; - YooLogger.Error(error); + YooLogger.LogError(error); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(error); return errorProvider.CreateHandle(); @@ -308,7 +321,7 @@ namespace YooAsset if (assetInfo.IsValid == false) { - YooLogger.Error($"Failed to load raw file. Error: {assetInfo.Error}"); + YooLogger.LogError($"Failed to load raw file. Error: {assetInfo.Error}"); ErrorProvider errorProvider = new ErrorProvider(this, assetInfo); errorProvider.SetCompletedWithError(assetInfo.Error); return errorProvider.CreateHandle(); @@ -320,7 +333,7 @@ namespace YooAsset { provider = new RawFileProvider(this, providerKey, assetInfo); provider.InitProviderDebugInfo(); - ProviderDict.Add(providerKey, provider); + _providerDict.Add(providerKey, provider); AsyncOperationSystem.StartOperation(PackageName, provider); } @@ -359,7 +372,7 @@ namespace YooAsset { foreach (var provider in removeList) { - ProviderDict.Remove(provider.ProviderKey); + _providerDict.Remove(provider.ProviderKey); } } @@ -392,7 +405,101 @@ namespace YooAsset /// internal bool HasAnyLoader() { - return BundleLoaderDict.Count > 0; + return _bundleLoaderDict.Count > 0; + } + + /// + /// 释放所有 Provider 持有的句柄 + /// + internal void ReleaseAllHandles() + { + foreach (var provider in _providerDict.Values) + { + provider.ReleaseAllHandles(); + } + } + + /// + /// 检查是否所有 Provider 都已完成 + /// + internal bool AreAllProvidersDone() + { + foreach (var provider in _providerDict.Values) + { + if (provider.IsDone == false) + return false; + } + return true; + } + + /// + /// 销毁所有 Provider 并清空字典 + /// + internal void DestroyAllProviders() + { + foreach (var provider in _providerDict.Values) + { + provider.DestroyProvider(); + } + _providerDict.Clear(); + } + + /// + /// 尝试终止所有 BundleLoader + /// + internal void TryAbortAllBundleLoaders() + { + foreach (var loader in _bundleLoaderDict.Values) + { + loader.TryAbortLoader(); + } + } + + /// + /// 销毁所有 BundleLoader 并清空字典 + /// + internal void DestroyAllBundleLoaders() + { + foreach (var loader in _bundleLoaderDict.Values) + { + loader.DestroyLoader(); + } + _bundleLoaderDict.Clear(); + } + + /// + /// 销毁未使用的 Bundle + /// + internal void DestroyUnusedBundle() + { + // 注意:优先销毁资源提供者 + foreach (var loader in _bundleLoaderDict.Values) + { + loader.TryDestroyProviders(); + } + + // 获取销毁列表 + var removeList = new List(_bundleLoaderDict.Count); + foreach (var loader in _bundleLoaderDict.Values) + { + if (loader.CanDestroyLoader()) + removeList.Add(loader); + } + + // 销毁文件加载器 + foreach (var loader in removeList) + { + loader.DestroyLoader(); + _bundleLoaderDict.Remove(loader.LoadBundleInfo.Bundle.BundleName); + } + } + + /// + /// 清空场景句柄列表 + /// + internal void ClearSceneHandles() + { + _sceneHandles.Clear(); } /// @@ -411,7 +518,7 @@ namespace YooAsset _bundleLoadingCounter--; if (_bundleLoadingCounter < 0) { - YooLogger.Error("Bundle loading counter became negative and was reset to zero."); + YooLogger.LogError("Bundle loading counter became negative and was reset to zero."); _bundleLoadingCounter = 0; } } @@ -442,19 +549,19 @@ namespace YooAsset // 新增下载需求 loaderOperation = new LoadBundleOperation(this, bundleInfo); - BundleLoaderDict.Add(bundleName, loaderOperation); + _bundleLoaderDict.Add(bundleName, loaderOperation); return loaderOperation; } private LoadBundleOperation GetBundleLoader(string bundleName) { - if (BundleLoaderDict.TryGetValue(bundleName, out LoadBundleOperation value)) + if (_bundleLoaderDict.TryGetValue(bundleName, out LoadBundleOperation value)) return value; else return null; } private ProviderBase GetAssetProvider(string providerKey) { - if (ProviderDict.TryGetValue(providerKey, out ProviderBase value)) + if (_providerDict.TryGetValue(providerKey, out ProviderBase value)) return value; else return null; @@ -462,7 +569,7 @@ namespace YooAsset private void OnSceneUnloaded(Scene scene) { _tempSceneHandles.Clear(); //复用列表 - foreach (var sceneHandle in SceneHandles) + foreach (var sceneHandle in _sceneHandles) { if (sceneHandle.IsValid) { @@ -475,7 +582,7 @@ namespace YooAsset } foreach (var sceneHandle in _tempSceneHandles) { - SceneHandles.Remove(sceneHandle); + _sceneHandles.Remove(sceneHandle); } } @@ -485,8 +592,8 @@ namespace YooAsset /// internal List DebugGetProviderInfos() { - List result = new List(ProviderDict.Count); - foreach (var provider in ProviderDict.Values) + List result = new List(_providerDict.Count); + foreach (var provider in _providerDict.Values) { DiagnosticProviderInfo providerInfo = new DiagnosticProviderInfo(); providerInfo.AssetPath = provider.MainAssetInfo.AssetPath; @@ -506,8 +613,8 @@ namespace YooAsset /// internal List DebugGetBundleInfos() { - List result = new List(BundleLoaderDict.Values.Count); - foreach (var bundleLoader in BundleLoaderDict.Values) + List result = new List(_bundleLoaderDict.Values.Count); + foreach (var bundleLoader in _bundleLoaderDict.Values) { var packageBundle = bundleLoader.LoadBundleInfo.Bundle; var bundleInfo = new DiagnosticBundleInfo(); @@ -530,7 +637,7 @@ namespace YooAsset List result = new List(referrerBundleNames.Count); foreach (var bundleName in referrerBundleNames) { - if (BundleLoaderDict.ContainsKey(bundleName)) + if (_bundleLoaderDict.ContainsKey(bundleName)) result.Add(bundleName); } return result; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/AssetInfo.cs b/Assets/YooAsset/Runtime/ResourcePackage/AssetInfo.cs index fc61429a..98796442 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/AssetInfo.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/AssetInfo.cs @@ -1,47 +1,47 @@ namespace YooAsset { + /// + /// 资源加载方法枚举 + /// + internal enum ELoadMethod + { + /// + /// 无加载方法 + /// + None = 0, + + /// + /// 加载单个资源 + /// + LoadAsset, + + /// + /// 加载子资源集合 + /// + LoadSubAssets, + + /// + /// 加载所有资源 + /// + LoadAllAssets, + + /// + /// 加载场景 + /// + LoadScene, + + /// + /// 加载原生文件 + /// + LoadRawFile, + } + /// /// 资源信息类 /// public class AssetInfo { - /// - /// 资源加载方法枚举 - /// - internal enum ELoadMethod - { - /// - /// 无加载方法 - /// - None = 0, - - /// - /// 加载单个资源 - /// - LoadAsset, - - /// - /// 加载子资源集合 - /// - LoadSubAssets, - - /// - /// 加载所有资源 - /// - LoadAllAssets, - - /// - /// 加载场景 - /// - LoadScene, - - /// - /// 加载原生文件 - /// - LoadRawFile, - } - private readonly PackageAsset _packageAsset; private string _assetKey; @@ -63,10 +63,10 @@ namespace YooAsset /// /// 加载方法 /// - internal ELoadMethod LoadMethod; + internal ELoadMethod LoadMethod { get; set; } /// - /// 资源对象 + /// 资源描述 /// internal PackageAsset Asset { @@ -126,10 +126,10 @@ namespace YooAsset } /// - /// 创建有效的资源信息 + /// 创建有效的资源信息实例 /// /// 所属包裹名称 - /// 清单中的资源对象 + /// 清单中的资源描述 /// 资源类型 internal AssetInfo(string packageName, PackageAsset packageAsset, System.Type assetType) { @@ -144,7 +144,7 @@ namespace YooAsset } /// - /// 创建无效的资源信息 + /// 创建无效的资源信息实例 /// /// 所属包裹名称 /// 错误信息 diff --git a/Assets/YooAsset/Runtime/ResourcePackage/BundleInfo.cs b/Assets/YooAsset/Runtime/ResourcePackage/BundleInfo.cs index 4c91d914..79179ea0 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/BundleInfo.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/BundleInfo.cs @@ -10,16 +10,16 @@ namespace YooAsset private readonly string _importFilePath; /// - /// 资源包对象 + /// 资源包描述 /// public readonly PackageBundle Bundle; /// - /// 创建资源包信息 + /// 创建资源包信息实例 /// /// 所属文件系统 - /// 资源包对象 + /// 资源包描述 public BundleInfo(IFileSystem fileSystem, PackageBundle bundle) { _fileSystem = fileSystem; @@ -28,10 +28,10 @@ namespace YooAsset } /// - /// 创建资源包信息(带导入路径) + /// 创建资源包信息实例(带导入路径) /// /// 所属文件系统 - /// 资源包对象 + /// 资源包描述 /// 导入文件路径 public BundleInfo(IFileSystem fileSystem, PackageBundle bundle, string importFilePath) { @@ -64,7 +64,7 @@ namespace YooAsset /// /// 是否需要从远端下载 /// - /// 如果需要下载返回true,否则返回false + /// 如果需要下载返回true,否则返回false。 public bool IsDownloadRequired() { return _fileSystem.IsDownloadRequired(Bundle); diff --git a/Assets/YooAsset/Runtime/ResourcePackage/EPlayMode.cs b/Assets/YooAsset/Runtime/ResourcePackage/EPlayMode.cs index df6dee54..a5ad882f 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/EPlayMode.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/EPlayMode.cs @@ -1,4 +1,4 @@ - + namespace YooAsset { /// @@ -6,6 +6,11 @@ namespace YooAsset /// public enum EPlayMode { + /// + /// 未指定运行模式 + /// + None = 0, + /// /// 编辑器下的模拟模式 /// diff --git a/Assets/YooAsset/Runtime/ResourcePackage/FileSystemHost.cs b/Assets/YooAsset/Runtime/ResourcePackage/FileSystemHost.cs index 49ce6ba8..8424f30e 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/FileSystemHost.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/FileSystemHost.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 文件系统宿主,管理多个文件系统 + /// 文件系统宿主,管理多个文件系统。 /// internal class FileSystemHost { @@ -14,7 +14,7 @@ namespace YooAsset /// /// 所属包裹名称 /// - public readonly string PackageName; + public string PackageName { get; } /// /// 文件系统列表 @@ -28,7 +28,7 @@ namespace YooAsset /// - /// 创建文件系统宿主 + /// 创建文件系统宿主实例 /// /// 所属包裹名称 public FileSystemHost(string packageName) @@ -37,7 +37,7 @@ namespace YooAsset } /// - /// 异步初始化文件系统 + /// 初始化文件系统 /// /// 文件系统初始化参数 /// 返回文件系统初始化操作对象 @@ -50,7 +50,7 @@ namespace YooAsset } /// - /// 异步初始化文件系统(双文件系统) + /// 初始化文件系统(双文件系统) /// /// 第一个文件系统初始化参数 /// 第二个文件系统初始化参数 @@ -66,7 +66,7 @@ namespace YooAsset } /// - /// 异步初始化文件系统(多文件系统) + /// 初始化文件系统(多文件系统) /// /// 文件系统初始化参数列表 /// 返回文件系统初始化操作对象 @@ -108,8 +108,8 @@ namespace YooAsset /// /// 获取主文件系统 /// - /// 返回主文件系统,如果没有文件系统则返回null - /// 文件系统列表里,最后一个属于主文件系统 + /// 返回主文件系统,如果没有文件系统则返回null。 + /// 文件系统列表里,最后一个属于主文件系统。 public IFileSystem GetMainFileSystem() { int count = _fileSystems.Count; @@ -121,8 +121,8 @@ namespace YooAsset /// /// 获取资源包所属的文件系统 /// - /// 资源包对象 - /// 返回资源包所属的文件系统,如果未找到则返回null + /// 资源包描述 + /// 返回资源包所属的文件系统,如果未找到则返回null。 private IFileSystem GetOwnerFileSystem(PackageBundle packageBundle) { for (int i = 0; i < _fileSystems.Count; i++) @@ -134,7 +134,7 @@ namespace YooAsset } } - YooLogger.Error($"Cannot find the file system for bundle: {packageBundle.BundleName}"); + YooLogger.LogError($"Could not find file system for bundle: '{packageBundle.BundleName}'."); return null; } @@ -142,7 +142,7 @@ namespace YooAsset /// /// 创建资源包信息对象 /// - /// 资源包对象 + /// 资源包描述 /// 返回资源包信息对象 private BundleInfo CreateBundleInfo(PackageBundle packageBundle) { @@ -156,7 +156,7 @@ namespace YooAsset return bundleInfo; } - throw new System.InvalidOperationException($"Cannot find the file system for bundle: {packageBundle.BundleName}"); + throw new System.InvalidOperationException($"Could not find file system for bundle: '{packageBundle.BundleName}'."); } /// @@ -198,7 +198,7 @@ namespace YooAsset // 注意:如果清单里未找到资源包会抛出异常! List depends; - if (assetInfo.LoadMethod == AssetInfo.ELoadMethod.LoadAllAssets) + if (assetInfo.LoadMethod == ELoadMethod.LoadAllAssets) { var mainBundle = ActiveManifest.GetMainPackageBundle(assetInfo.Asset); depends = ActiveManifest.GetAllBundleDependencies(mainBundle); @@ -225,12 +225,12 @@ namespace YooAsset /// 获取指定资源需要下载的文件总大小 /// /// 资源信息对象 - /// 返回需要下载的字节数,0 表示不需要下载 + /// 返回需要下载的字节数,0 表示不需要下载。 public long GetDownloadSize(AssetInfo assetInfo) { if (assetInfo.IsValid == false) { - YooLogger.Warning(assetInfo.Error); + YooLogger.LogWarning(assetInfo.Error); return 0; } @@ -450,7 +450,7 @@ namespace YooAsset { if (assetInfo.IsValid == false) { - YooLogger.Warning(assetInfo.Error); + YooLogger.LogWarning(assetInfo.Error); continue; } @@ -530,15 +530,15 @@ namespace YooAsset { if (manifest.TryGetPackageBundleByBundleName(fileInfo.BundleName, out packageBundle) == false) { - YooLogger.Warning($"Package bundle not found, bundle name: {fileInfo.BundleName}"); + YooLogger.LogWarning($"Package bundle not found, bundle name: '{fileInfo.BundleName}'."); continue; } } - else if (string.IsNullOrEmpty(fileInfo.BundleGUID) == false) + else if (string.IsNullOrEmpty(fileInfo.BundleGuid) == false) { - if (manifest.TryGetPackageBundleByBundleGUID(fileInfo.BundleGUID, out packageBundle) == false) + if (manifest.TryGetPackageBundleByBundleGuid(fileInfo.BundleGuid, out packageBundle) == false) { - YooLogger.Warning($"Package bundle not found, bundle GUID: {fileInfo.BundleGUID}"); + YooLogger.LogWarning($"Package bundle not found, bundle GUID: '{fileInfo.BundleGuid}'."); continue; } } @@ -547,7 +547,7 @@ namespace YooAsset string fileName = System.IO.Path.GetFileName(filePath); if (manifest.TryGetPackageBundleByFileName(fileName, out packageBundle) == false) { - YooLogger.Warning($"Package bundle not found, file name: {fileName}"); + YooLogger.LogWarning($"Package bundle not found, file name: '{fileName}'."); continue; } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs index 2a96c8cf..eb84031b 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs @@ -43,7 +43,7 @@ namespace YooAsset if (fileSystems == null || fileSystems.Count == 0) { _steps = ESteps.Done; - SetError("The file system list is null or empty."); + SetError("File system list is null or empty."); return; } @@ -52,7 +52,7 @@ namespace YooAsset if (fileSystem == null) { _steps = ESteps.Done; - SetError("The list contains a null element."); + SetError("List contains a null element."); return; } } @@ -73,7 +73,7 @@ namespace YooAsset var fileSystem = _cloneList[0]; _cloneList.RemoveAt(0); - _clearCacheFilesOp = fileSystem.ClearCacheAsync(_options.ConvertTo()); + _clearCacheFilesOp = fileSystem.ClearCacheAsync(_options.ConvertTo(_host.ActiveManifest)); _clearCacheFilesOp.StartOperation(); AddChildOperation(_clearCacheFilesOp); _steps = ESteps.CheckClearResult; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOptions.cs index e827c354..ecadf190 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOptions.cs @@ -4,56 +4,49 @@ namespace YooAsset /// /// 清理缓存选项 /// - public struct ClearCacheOptions + public readonly struct ClearCacheOptions { /// /// 清理方式 /// - public string ClearMethod { get; set; } + public string ClearMethod { get; } /// /// 附加参数 /// - public object ClearParameter { get; set; } + public object ClearParameter { get; } /// - /// 资源清单 - /// - internal PackageManifest Manifest { get; set; } - - /// - /// 创建清理缓存选项 + /// 创建清理缓存选项实例 /// /// 清理方式 public ClearCacheOptions(string clearMethod) { ClearMethod = clearMethod; ClearParameter = null; - Manifest = null; } /// - /// 创建清理缓存选项 + /// 创建清理缓存选项实例 /// - /// 清理方式 + /// 清理方式 /// 附加参数 public ClearCacheOptions(string clearMethod, object clearParam) { ClearMethod = clearMethod; ClearParameter = clearParam; - Manifest = null; } /// /// 转换为 FileSystem 的清理缓存选项 /// - internal FSClearCacheOptions ConvertTo() + /// 资源清单 + internal FSClearCacheOptions ConvertTo(PackageManifest manifest) { - var options = new FSClearCacheOptions(); - options.ClearMethod = ClearMethod; - options.ClearParameter = ClearParameter; - options.Manifest = Manifest; - return options; + return new FSClearCacheOptions( + clearMethod: ClearMethod, + clearParameter: ClearParameter, + manifest: manifest); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs index 7ee1ab94..c0f88e92 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 销毁资源包裹操作 /// - public class DestroyPackageOperation : AsyncOperationBase + public sealed class DestroyPackageOperation : AsyncOperationBase { private enum ESteps { @@ -21,7 +21,7 @@ namespace YooAsset private ESteps _steps = ESteps.None; - public DestroyPackageOperation(ResourcePackage resourcePackage, UnloadAllAssetsOptions options) + internal DestroyPackageOperation(ResourcePackage resourcePackage, UnloadAllAssetsOptions options) { _resourcePackage = resourcePackage; _options = options; @@ -47,7 +47,7 @@ namespace YooAsset case EOperationStatus.Processing: _steps = ESteps.Done; - SetError("The package is initializing. Please try to destroy it again later."); + SetError("Package is initializing. Please try to destroy it again later."); break; case EOperationStatus.Succeeded: @@ -58,7 +58,7 @@ namespace YooAsset break; default: - throw new System.NotImplementedException(_resourcePackage.InitializeStatus.ToString()); + throw new System.NotImplementedException($"Initialize status is not implemented: {_resourcePackage.InitializeStatus}."); } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderEventArgs.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderEventArgs.cs index 5fa8ed28..008b747f 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderEventArgs.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderEventArgs.cs @@ -4,33 +4,45 @@ namespace YooAsset /// /// 下载完成事件参数 /// - public struct DownloadCompletedEventArgs + public readonly struct DownloadCompletedEventArgs { /// /// 所属包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 是否成功 /// - public bool Succeeded { get; set; } + public bool Succeeded { get; } /// - /// 如果下载失败,获取的错误信息。 + /// 下载失败时的错误信息 /// - public string Error { get; set; } + public string Error { get; } + + /// + /// 创建下载完成事件参数实例 + /// + /// 所属包裹名称 + /// 是否下载成功 + /// 下载失败时的错误信息 + public DownloadCompletedEventArgs(string packageName, bool succeeded, string error) + { + PackageName = packageName; + Succeeded = succeeded; + Error = error; + } /// /// 创建表示成功下载的事件参数 /// internal static DownloadCompletedEventArgs CreateSucceeded(string packageName) { - var args = new DownloadCompletedEventArgs(); - args.PackageName = packageName; - args.Succeeded = true; - args.Error = null; - return args; + return new DownloadCompletedEventArgs( + packageName: packageName, + succeeded: true, + error: null); } /// @@ -38,117 +50,143 @@ namespace YooAsset /// internal static DownloadCompletedEventArgs CreateFailed(string packageName, string error) { - var args = new DownloadCompletedEventArgs(); - args.PackageName = packageName; - args.Succeeded = false; - args.Error = error; - return args; + return new DownloadCompletedEventArgs( + packageName: packageName, + succeeded: false, + error: error); } } - /// - /// 下载完成事件委托 - /// - public delegate void DownloadCompletedEventHandler(DownloadCompletedEventArgs args); - - /// /// 下载进度更新事件参数 /// - public struct DownloadProgressChangedEventArgs + public readonly struct DownloadProgressChangedEventArgs { /// /// 所属包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 下载进度 (0-1f) /// - public float Progress { get; set; } + public float Progress { get; } /// /// 下载文件总数 /// - public int TotalDownloadCount { get; set; } + public int TotalDownloadCount { get; } /// /// 下载数据总大小(单位:字节) /// - public long TotalDownloadBytes { get; set; } + public long TotalDownloadBytes { get; } /// /// 当前完成的下载文件数量 /// - public int CurrentDownloadCount { get; set; } + public int CurrentDownloadCount { get; } /// /// 当前完成的下载数据大小(单位:字节) /// - public long CurrentDownloadBytes { get; set; } + public long CurrentDownloadBytes { get; } + + /// + /// 创建下载进度更新事件参数实例 + /// + /// 所属包裹名称 + /// 下载进度(0-1f) + /// 下载文件总数 + /// 下载数据总大小(单位:字节) + /// 当前完成的下载文件数量 + /// 当前完成的下载数据大小(单位:字节) + public DownloadProgressChangedEventArgs(string packageName, float progress, + int totalDownloadCount, long totalDownloadBytes, + int currentDownloadCount, long currentDownloadBytes) + { + PackageName = packageName; + Progress = progress; + TotalDownloadCount = totalDownloadCount; + TotalDownloadBytes = totalDownloadBytes; + CurrentDownloadCount = currentDownloadCount; + CurrentDownloadBytes = currentDownloadBytes; + } } - /// - /// 下载进度更新事件委托 - /// - public delegate void DownloadProgressChangedEventHandler(DownloadProgressChangedEventArgs args); - - /// /// 下载错误事件参数 /// - public struct DownloadErrorEventArgs + public readonly struct DownloadErrorEventArgs { /// /// 所属包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 下载失败的文件名称 /// - public string FileName { get; set; } + public string FileName { get; } /// /// 错误信息 /// - public string ErrorInfo { get; set; } + public string ErrorInfo { get; } + + /// + /// 创建下载错误事件参数实例 + /// + /// 所属包裹名称 + /// 下载失败的文件名称 + /// 错误信息 + public DownloadErrorEventArgs(string packageName, string fileName, string errorInfo) + { + PackageName = packageName; + FileName = fileName; + ErrorInfo = errorInfo; + } } - /// - /// 下载错误事件委托 - /// - public delegate void DownloadErrorEventHandler(DownloadErrorEventArgs args); - - /// /// 开始下载单个文件事件参数 /// - public struct DownloadFileStartedEventArgs + public readonly struct DownloadFileStartedEventArgs { /// /// 所属包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; } /// /// 资源包名称 /// - public string BundleName { get; set; } + public string BundleName { get; } /// /// 文件名称 /// - public string FileName { get; set; } + public string FileName { get; } /// /// 文件大小 /// - public long FileSize { get; set; } + public long FileSize { get; } + + /// + /// 创建开始下载单个文件事件参数实例 + /// + /// 所属包裹名称 + /// 资源包名称 + /// 文件名称 + /// 文件大小(单位:字节) + public DownloadFileStartedEventArgs(string packageName, string bundleName, string fileName, long fileSize) + { + PackageName = packageName; + BundleName = bundleName; + FileName = fileName; + FileSize = fileSize; + } } - /// - /// 开始下载单个文件事件委托 - /// - public delegate void DownloadFileStartedEventHandler(DownloadFileStartedEventArgs args); -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs index ffcb7a62..9d94a1d4 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 下载操作基类,提供资源下载、暂停、恢复和取消功能 + /// 下载操作基类,提供资源下载、暂停、恢复和取消功能。 /// public abstract class DownloaderOperation : AsyncOperationBase { @@ -17,14 +17,14 @@ namespace YooAsset Done, } - private const int MAX_LOADER_COUNT = 64; + private const int MaxLoaderCount = 32; private readonly string _packageName; private readonly int _maxConcurrency; private readonly int _retryCount; private readonly List _bundleInfoList; - private readonly List _downloaders = new List(MAX_LOADER_COUNT); - private readonly List _removeList = new List(MAX_LOADER_COUNT); - private readonly List _failedList = new List(MAX_LOADER_COUNT); + private readonly List _downloaders = new List(MaxLoaderCount); + private readonly List _removeList = new List(MaxLoaderCount); + private readonly List _failedList = new List(MaxLoaderCount); // 数据相关 private bool _isPause = false; @@ -62,24 +62,24 @@ namespace YooAsset } /// - /// 下载完成事件(无论成功或失败) + /// 当下载完成时触发(无论成功或失败)。 /// - public event DownloadCompletedEventHandler DownloadCompleted; + public event System.Action DownloadCompleted; /// - /// 下载进度更新事件 + /// 当下载进度更新时触发 /// - public event DownloadProgressChangedEventHandler DownloadProgressChanged; + public event System.Action DownloadProgressChanged; /// - /// 下载错误事件 + /// 当发生下载错误时触发 /// - public event DownloadErrorEventHandler DownloadError; + public event System.Action DownloadError; /// - /// 开始下载单个文件事件 + /// 当开始下载单个文件时触发 /// - public event DownloadFileStartedEventHandler DownloadFileStarted; + public event System.Action DownloadFileStarted; /// @@ -93,7 +93,7 @@ namespace YooAsset { _packageName = packageName; _bundleInfoList = downloadList; - _maxConcurrency = UnityEngine.Mathf.Clamp(maximumConcurrency, 1, MAX_LOADER_COUNT); + _maxConcurrency = UnityEngine.Mathf.Clamp(maximumConcurrency, 1, MaxLoaderCount); _retryCount = retryCount; // 统计下载信息 @@ -101,7 +101,7 @@ namespace YooAsset } protected override void InternalStart() { - YooLogger.Log($"Beginning download of {TotalDownloadCount} files ({TotalDownloadBytes} bytes)"); + YooLogger.Log($"Beginning download of {TotalDownloadCount} files ({TotalDownloadBytes} bytes)."); _steps = ESteps.Check; } protected override void InternalUpdate() @@ -181,18 +181,19 @@ namespace YooAsset if (DownloadProgressChanged != null) { - var data = new DownloadProgressChangedEventArgs(); - data.PackageName = _packageName; - data.Progress = Progress; - data.TotalDownloadCount = TotalDownloadCount; - data.TotalDownloadBytes = TotalDownloadBytes; - data.CurrentDownloadCount = _lastDownloadCount; - data.CurrentDownloadBytes = _lastDownloadBytes; + var data = new DownloadProgressChangedEventArgs( + packageName: _packageName, + progress: Progress, + totalDownloadCount: TotalDownloadCount, + totalDownloadBytes: TotalDownloadBytes, + currentDownloadCount: _lastDownloadCount, + currentDownloadBytes: _lastDownloadBytes); DownloadProgressChanged.Invoke(data); } } // 动态创建新的下载器到最大数量限制 + // 注意:每帧仅创建一个下载器,将初始化开销分摊到多帧,避免移动端单帧尖峰。 // 注意:如果期间有下载失败的文件,暂停动态创建下载器 if (_bundleInfoList.Count > 0 && _failedList.Count == 0) { @@ -212,11 +213,11 @@ namespace YooAsset if (DownloadFileStarted != null) { - var data = new DownloadFileStartedEventArgs(); - data.PackageName = _packageName; - data.BundleName = bundleInfo.Bundle.BundleName; - data.FileName = bundleInfo.Bundle.FileName; - data.FileSize = bundleInfo.Bundle.FileSize; + var data = new DownloadFileStartedEventArgs( + packageName: _packageName, + bundleName: bundleInfo.Bundle.BundleName, + fileName: bundleInfo.Bundle.GetFileName(), + fileSize: bundleInfo.Bundle.FileSize); DownloadFileStarted.Invoke(data); } } @@ -236,14 +237,14 @@ namespace YooAsset var failedDownloader = _failedList[0]; string bundleName = failedDownloader.Bundle.BundleName; _steps = ESteps.Done; - SetError($"Failed to download file: {bundleName}"); + SetError($"Failed to download file: '{bundleName}'."); if (DownloadError != null) { - var data = new DownloadErrorEventArgs(); - data.PackageName = _packageName; - data.FileName = bundleName; - data.ErrorInfo = failedDownloader.Error; + var data = new DownloadErrorEventArgs( + packageName: _packageName, + fileName: bundleName, + errorInfo: failedDownloader.Error); DownloadError.Invoke(data); } @@ -296,9 +297,15 @@ namespace YooAsset private float CalculateProgress() { if (TotalDownloadBytes == 0) + { + if (TotalDownloadCount == 0) + return 1f; return (float)_lastDownloadCount / TotalDownloadCount; + } else + { return (float)_lastDownloadBytes / TotalDownloadBytes; + } } /// @@ -309,13 +316,13 @@ namespace YooAsset { if (_packageName != downloader._packageName) { - YooLogger.Error("The downloaders have different resource packages."); + YooLogger.LogError("Downloaders have different resource packages."); return; } if (Status != EOperationStatus.None) { - YooLogger.Error("Cannot combine downloaders while a download is in progress."); + YooLogger.LogError("Cannot combine downloaders while a download is in progress."); return; } @@ -384,6 +391,12 @@ namespace YooAsset { downloader.AbortOperation(); } + + if (DownloadCompleted != null) + { + var args = DownloadCompletedEventArgs.CreateFailed(_packageName, Error); + DownloadCompleted.Invoke(args); + } } } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOptions.cs index 90229fe0..a7453b23 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOptions.cs @@ -4,31 +4,31 @@ namespace YooAsset /// /// 按资源信息创建下载器的选项 /// - public struct BundleDownloaderOptions + public readonly struct BundleDownloaderOptions { /// /// 最大并发数量 /// - public int MaximumConcurrency { get; set; } + public int MaximumConcurrency { get; } /// /// 失败后的重试次数 /// - public int RetryCount { get; set; } + public int RetryCount { get; } /// /// 下载资源对象所属资源包内所有资源对象依赖的资源包 /// - public bool DownloadBundleDependencies { get; set; } + public bool DownloadBundleDependencies { get; } /// /// 资源信息列表 /// /// 如果列表为NULL,则下载所有资源 - public AssetInfo[] AssetInfos { get; set; } + public AssetInfo[] AssetInfos { get; } /// - /// 创建资源下载选项(单个资源) + /// 创建资源下载选项实例(单个资源) /// /// 资源信息 /// 是否下载依赖资源包 @@ -43,7 +43,7 @@ namespace YooAsset } /// - /// 创建资源下载选项(多个资源) + /// 创建资源下载选项实例(多个资源) /// /// 资源信息数组 /// 是否下载依赖资源包 @@ -61,26 +61,26 @@ namespace YooAsset /// /// 按资源标签创建下载器的选项 /// - public struct ResourceDownloaderOptions + public readonly struct ResourceDownloaderOptions { /// /// 最大并发数量 /// - public int MaximumConcurrency { get; set; } + public int MaximumConcurrency { get; } /// /// 失败后的重试次数 /// - public int RetryCount { get; set; } + public int RetryCount { get; } /// /// 资源标签列表 /// /// 如果列表为NULL,则下载所有资源 - public string[] Tags { get; set; } + public string[] Tags { get; } /// - /// 创建资源下载选项(下载所有资源) + /// 创建资源下载选项实例(下载所有资源) /// /// 最大并发数量 /// 失败后的重试次数 @@ -92,7 +92,7 @@ namespace YooAsset } /// - /// 创建资源下载选项(按标签下载) + /// 创建资源下载选项实例(按标签下载) /// /// 资源标签 /// 最大并发数量 @@ -105,7 +105,7 @@ namespace YooAsset } /// - /// 创建资源下载选项(按多个标签下载) + /// 创建资源下载选项实例(按多个标签下载) /// /// 资源标签数组 /// 最大并发数量 @@ -121,26 +121,26 @@ namespace YooAsset /// /// 资源解压选项 /// - public struct ResourceUnpackerOptions + public readonly struct ResourceUnpackerOptions { /// /// 最大并发数量 /// - public int MaximumConcurrency { get; set; } + public int MaximumConcurrency { get; } /// /// 失败后的重试次数 /// - public int RetryCount { get; set; } + public int RetryCount { get; } /// /// 资源标签列表 /// /// 如果列表为NULL,则解压所有资源 - public string[] Tags { get; set; } + public string[] Tags { get; } /// - /// 创建资源解压选项(解压所有资源) + /// 创建资源解压选项实例(解压所有资源) /// /// 最大并发数量 /// 失败后的重试次数 @@ -152,7 +152,7 @@ namespace YooAsset } /// - /// 创建资源解压选项(按标签解压) + /// 创建资源解压选项实例(按标签解压) /// /// 资源标签 /// 最大并发数量 @@ -165,7 +165,7 @@ namespace YooAsset } /// - /// 创建资源解压选项(按多个标签解压) + /// 创建资源解压选项实例(按多个标签解压) /// /// 资源标签数组 /// 最大并发数量 @@ -181,25 +181,25 @@ namespace YooAsset /// /// 资源导入选项 /// - public struct BundleImporterOptions + public readonly struct BundleImporterOptions { /// /// 最大并发数量 /// - public int MaximumConcurrency { get; set; } + public int MaximumConcurrency { get; } /// /// 失败后的重试次数 /// - public int RetryCount { get; set; } + public int RetryCount { get; } /// /// 资源包信息列表 /// - public ImportBundleInfo[] BundleInfos { get; set; } + public ImportBundleInfo[] BundleInfos { get; } /// - /// 创建资源导入选项 + /// 创建资源导入选项实例 /// /// 资源包信息数组 /// 最大并发数量 @@ -215,21 +215,34 @@ namespace YooAsset /// /// 导入的资源包信息 /// - public struct ImportBundleInfo + public readonly struct ImportBundleInfo { /// /// 本地文件路径 /// - public string FilePath; + public string FilePath { get; } /// /// 资源包名称 /// - public string BundleName; + public string BundleName { get; } /// /// 资源包GUID /// - public string BundleGUID; + public string BundleGuid { get; } + + /// + /// 创建导入的资源包信息实例 + /// + /// 本地文件路径 + /// 资源包名称 + /// 资源包GUID + public ImportBundleInfo(string filePath, string bundleName, string bundleGuid) + { + FilePath = filePath; + BundleName = bundleName; + BundleGuid = bundleGuid; + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs index 4a0f54f9..c3b7123a 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 初始化资源包裹操作 /// - public class InitializePackageOperation : AsyncOperationBase + public sealed class InitializePackageOperation : AsyncOperationBase { private enum ESteps { @@ -51,7 +51,7 @@ namespace YooAsset else if (_options is CustomPlayModeOptions) _playMode = EPlayMode.CustomPlayMode; else - throw new NotImplementedException($"{_options.GetType().Name}"); + throw new NotImplementedException($"Options type is not implemented: {_options.GetType().Name}."); _steps = ESteps.CheckOptions; } @@ -63,7 +63,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError($"{nameof(_options.BundleLoadingMaxConcurrency)} value must be greater than zero."); - YooLogger.Error(Error); + YooLogger.LogError(Error); return; } @@ -113,7 +113,7 @@ namespace YooAsset } else { - throw new NotImplementedException(_playMode.ToString()); + throw new NotImplementedException($"Play mode is not implemented: {_playMode}."); } _initializeFileSystemOp.StartOperation(); @@ -133,7 +133,7 @@ namespace YooAsset { _steps = ESteps.Done; SetError(_initializeFileSystemOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs index 7c15b443..fe744b09 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs @@ -7,20 +7,22 @@ namespace YooAsset /// public abstract class InitializePackageOptions { + protected InitializePackageOptions() { } + /// /// 同时加载Bundle文件的最大并发数 /// - public int BundleLoadingMaxConcurrency = int.MaxValue; + public int BundleLoadingMaxConcurrency { get; set; } = int.MaxValue; /// - /// 当资源引用计数为零的时候自动释放资源包 + /// 是否在资源引用计数为零时自动释放资源包 /// - public bool AutoUnloadBundleWhenUnused = false; + public bool AutoUnloadBundleWhenUnused { get; set; } = false; /// - /// WebGL平台强制同步加载资源对象 + /// 是否在WebGL平台强制同步加载资源对象 /// - public bool WebGLForceSyncLoadAsset = false; + public bool WebGLForceSyncLoadAsset { get; set; } = false; } /// @@ -31,7 +33,7 @@ namespace YooAsset /// /// 编辑器文件系统初始化参数 /// - public FileSystemParameters EditorFileSystemParameters; + public FileSystemParameters EditorFileSystemParameters { get; set; } } /// @@ -42,7 +44,7 @@ namespace YooAsset /// /// 内置文件系统初始化参数 /// - public FileSystemParameters BuiltinFileSystemParameters; + public FileSystemParameters BuiltinFileSystemParameters { get; set; } } /// @@ -53,12 +55,12 @@ namespace YooAsset /// /// 内置文件系统初始化参数 /// - public FileSystemParameters BuiltinFileSystemParameters; + public FileSystemParameters BuiltinFileSystemParameters { get; set; } /// /// 缓存文件系统初始化参数 /// - public FileSystemParameters CacheFileSystemParameters; + public FileSystemParameters CacheFileSystemParameters { get; set; } } /// @@ -69,12 +71,12 @@ namespace YooAsset /// /// Web服务器文件系统初始化参数 /// - public FileSystemParameters WebServerFileSystemParameters; + public FileSystemParameters WebServerFileSystemParameters { get; set; } /// /// Web远程文件系统初始化参数 /// - public FileSystemParameters WebRemoteFileSystemParameters; + public FileSystemParameters WebRemoteFileSystemParameters { get; set; } } /// diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/DeserializeManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/DeserializeManifestOperation.cs index 899b4598..1110dd28 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/DeserializeManifestOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/DeserializeManifestOperation.cs @@ -36,6 +36,11 @@ namespace YooAsset /// public PackageManifest Manifest { get; private set; } + /// + /// 创建反序列化清单文件操作实例 + /// + /// 清单解密器,为null时不解密 + /// 清单二进制数据 public DeserializeManifestOperation(IManifestDecryptor decryptor, byte[] binaryData) { _decryptor = decryptor; @@ -77,7 +82,7 @@ namespace YooAsset if (fileMagic != PackageManifestConsts.FileMagic) { _steps = ESteps.Done; - SetError("The manifest file format is invalid."); + SetError("Manifest file format is invalid."); return; } @@ -86,7 +91,7 @@ namespace YooAsset if (fileVersion != PackageManifestConsts.FileVersion) { _steps = ESteps.Done; - SetError($"The manifest file version is not compatible: {fileVersion} != {PackageManifestConsts.FileVersion}"); + SetError($"Manifest file version is not compatible: {fileVersion} != {PackageManifestConsts.FileVersion}."); return; } @@ -96,7 +101,7 @@ namespace YooAsset Manifest.EnableAddressable = _buffer.ReadBoolean(); Manifest.SupportExtensionless = _buffer.ReadBoolean(); Manifest.LocationToLower = _buffer.ReadBoolean(); - Manifest.IncludeAssetGUID = _buffer.ReadBoolean(); + Manifest.IncludeAssetGuid = _buffer.ReadBoolean(); Manifest.ReplaceAssetPathWithAddress = _buffer.ReadBoolean(); Manifest.OutputNameStyle = _buffer.ReadInt32(); Manifest.BuildBundleType = _buffer.ReadInt32(); @@ -143,14 +148,14 @@ namespace YooAsset { packageAsset.AssetPath = _buffer.ReadString(); } - packageAsset.AssetGUID = _buffer.ReadString(); + packageAsset.AssetGuid = _buffer.ReadString(); packageAsset.AssetTags = _buffer.ReadStringArray(); packageAsset.BundleID = _buffer.ReadInt32(); packageAsset.DependentBundleIDs = _buffer.ReadInt32Array(); FillAssetCollection(Manifest, packageAsset, replaceAssetPath); _packageAssetCount--; - Progress = 1f - (_packageAssetCount / (float)_progressTotalValue); + Progress = CalculateMultiStageProgress(0, 2, _packageAssetCount, _progressTotalValue); if (IsBusy) break; } @@ -184,7 +189,7 @@ namespace YooAsset FillBundleCollection(Manifest, packageBundle); _packageBundleCount--; - Progress = 1f - (_packageBundleCount / (float)_progressTotalValue); + Progress = CalculateMultiStageProgress(1, 2, _packageBundleCount, _progressTotalValue); if (IsBusy) break; } @@ -224,7 +229,7 @@ namespace YooAsset manifest.AssetPathsByLocation = new Dictionary(assetCount * 2); } - if (manifest.IncludeAssetGUID) + if (manifest.IncludeAssetGuid) manifest.AssetPathsByGuid = new Dictionary(assetCount); else manifest.AssetPathsByGuid = new Dictionary(); @@ -237,7 +242,7 @@ namespace YooAsset // 注意:我们不允许原始路径存在重名 string assetPath = packageAsset.AssetPath; if (manifest.AssetDictionary.ContainsKey(assetPath)) - throw new YooManifestInvalidException($"Asset path already exists: {assetPath}"); + throw new YooManifestInvalidException($"Asset path already exists: '{assetPath}'."); else manifest.AssetDictionary.Add(assetPath, packageAsset); @@ -247,7 +252,7 @@ namespace YooAsset // 添加原生路径的映射 if (manifest.AssetPathsByLocation.ContainsKey(location)) - throw new YooManifestInvalidException($"Location already exists: {location}"); + throw new YooManifestInvalidException($"Location already exists: '{location}'."); else manifest.AssetPathsByLocation.Add(location, packageAsset.AssetPath); @@ -258,7 +263,7 @@ namespace YooAsset if (ReferenceEquals(location, locationWithoutExtension) == false) { if (manifest.AssetPathsByLocation.ContainsKey(locationWithoutExtension)) - YooLogger.Warning($"Location already exists: {locationWithoutExtension}"); + YooLogger.LogWarning($"Location already exists: '{locationWithoutExtension}'."); else manifest.AssetPathsByLocation.Add(locationWithoutExtension, packageAsset.AssetPath); } @@ -266,12 +271,12 @@ namespace YooAsset } // 填充AssetPathMapping2 - if (manifest.IncludeAssetGUID) + if (manifest.IncludeAssetGuid) { - if (manifest.AssetPathsByGuid.ContainsKey(packageAsset.AssetGUID)) - throw new YooManifestInvalidException($"Asset GUID already exists: {packageAsset.AssetGUID}"); + if (manifest.AssetPathsByGuid.ContainsKey(packageAsset.AssetGuid)) + throw new YooManifestInvalidException($"Asset GUID already exists: '{packageAsset.AssetGuid}'."); else - manifest.AssetPathsByGuid.Add(packageAsset.AssetGUID, packageAsset.AssetPath); + manifest.AssetPathsByGuid.Add(packageAsset.AssetGuid, packageAsset.AssetPath); } // 添加可寻址地址 @@ -281,7 +286,7 @@ namespace YooAsset if (string.IsNullOrEmpty(location) == false) { if (manifest.AssetPathsByLocation.ContainsKey(location)) - throw new YooManifestInvalidException($"Location already exists: {location}"); + throw new YooManifestInvalidException($"Location already exists: '{location}'."); else manifest.AssetPathsByLocation.Add(location, packageAsset.AssetPath); } @@ -304,7 +309,7 @@ namespace YooAsset manifest.BundleList.Add(packageBundle); manifest.BundlesByBundleName.Add(packageBundle.BundleName, packageBundle); - manifest.BundlesByFileName.Add(packageBundle.FileName, packageBundle); + manifest.BundlesByFileName.Add(packageBundle.GetFileName(), packageBundle); manifest.BundlesByGuid.Add(packageBundle.BundleGuid, packageBundle); } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs index fa9fa5ba..142e1e49 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 初始化文件系统操作 /// - public class InitializeFileSystemOperation : AsyncOperationBase + public sealed class InitializeFileSystemOperation : AsyncOperationBase { private enum ESteps { @@ -42,7 +42,7 @@ namespace YooAsset if (_parametersList == null || _parametersList.Count == 0) { _steps = ESteps.Done; - SetError("The file system parameters list is null or empty."); + SetError("File system parameters list is null or empty."); return; } @@ -51,7 +51,7 @@ namespace YooAsset if (fileSystemParam == null) { _steps = ESteps.Done; - SetError("The list contains a null element."); + SetError("List contains a null element."); return; } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs index 678883f6..49b9e5b8 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs @@ -66,6 +66,13 @@ namespace YooAsset if (_loadManifestOp == null) { var mainFileSystem = _host.GetMainFileSystem(); + if (mainFileSystem == null) + { + _steps = ESteps.Done; + SetError("Main file system is null."); + return; + } + _loadManifestOp = mainFileSystem.LoadPackageManifestAsync(_options.ConvertTo()); _loadManifestOp.StartOperation(); AddChildOperation(_loadManifestOp); diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOptions.cs index 4e4e714c..46052883 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOptions.cs @@ -4,20 +4,20 @@ namespace YooAsset /// /// 加载清单选项 /// - public struct LoadPackageManifestOptions + public readonly struct LoadPackageManifestOptions { /// /// 包裹版本 /// - public string PackageVersion { get; set; } + public string PackageVersion { get; } /// /// 超时时间 /// - public int Timeout { get; set; } + public int Timeout { get; } /// - /// 创建加载清单选项 + /// 创建加载清单选项实例 /// /// 包裹版本 /// 超时时间(秒) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs index dd7cdbed..ee5639e3 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 预取清单操作,用于提前加载指定版本的资源清单 + /// 预取清单操作,用于提前加载指定版本的资源清单。 /// public sealed class PrefetchManifestOperation : AsyncOperationBase { @@ -72,6 +72,13 @@ namespace YooAsset if (_loadPackageManifestOp == null) { var mainFileSystem = _host.GetMainFileSystem(); + if (mainFileSystem == null) + { + _steps = ESteps.Done; + SetError("Main file system is null."); + return; + } + var options = new LoadPackageManifestOptions(_options.PackageVersion, _options.Timeout); _loadPackageManifestOp = mainFileSystem.LoadPackageManifestAsync(options.ConvertTo()); _loadPackageManifestOp.StartOperation(); @@ -97,13 +104,15 @@ namespace YooAsset } /// - /// 创建资源下载器,用于下载指定的资源标签列表关联的资源包文件 + /// 创建资源下载器,用于下载指定的资源标签列表关联的资源包文件。 /// + /// 资源下载选项 + /// 资源下载操作实例 public ResourceDownloaderOperation CreateResourceDownloader(ResourceDownloaderOptions options) { if (Status != EOperationStatus.Succeeded) { - YooLogger.Error($"{nameof(PrefetchManifestOperation)} did not succeed."); + YooLogger.LogError($"{nameof(PrefetchManifestOperation)} did not succeed."); return ResourceDownloaderOperation.CreateEmptyDownloader(_host.PackageName); } @@ -111,13 +120,15 @@ namespace YooAsset } /// - /// 创建资源下载器,用于下载指定的资源信息列表依赖的资源包文件 + /// 创建资源下载器,用于下载指定的资源信息列表依赖的资源包文件。 /// + /// 资源包下载选项 + /// 资源下载操作实例 public ResourceDownloaderOperation CreateBundleDownloader(BundleDownloaderOptions options) { if (Status != EOperationStatus.Succeeded) { - YooLogger.Error($"{nameof(PrefetchManifestOperation)} did not succeed."); + YooLogger.LogError($"{nameof(PrefetchManifestOperation)} did not succeed."); return ResourceDownloaderOperation.CreateEmptyDownloader(_host.PackageName); } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOptions.cs index bb52231a..b0fc9f5c 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOptions.cs @@ -4,20 +4,20 @@ namespace YooAsset /// /// 预取清单选项 /// - public struct PrefetchManifestOptions + public readonly struct PrefetchManifestOptions { /// /// 预取的包裹版本 /// - public string PackageVersion { get; set; } + public string PackageVersion { get; } /// /// 资源清单请求超时时间 /// - public int Timeout { get; set; } + public int Timeout { get; } /// - /// 创建预取清单选项 + /// 创建预取清单选项实例 /// /// 预取的包裹版本 /// 资源清单请求超时时间(秒) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs index 6815b5b9..7b0291c0 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs @@ -43,6 +43,13 @@ namespace YooAsset if (_requestVersionOp == null) { var mainFileSystem = _host.GetMainFileSystem(); + if (mainFileSystem == null) + { + _steps = ESteps.Done; + SetError("Main file system is null."); + return; + } + _requestVersionOp = mainFileSystem.RequestPackageVersionAsync(_options.ConvertTo()); _requestVersionOp.StartOperation(); AddChildOperation(_requestVersionOp); diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOptions.cs index 233d00f4..7411b949 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOptions.cs @@ -4,20 +4,20 @@ namespace YooAsset /// /// 请求版本选项 /// - public struct RequestPackageVersionOptions + public readonly struct RequestPackageVersionOptions { /// - /// 在URL末尾添加时间戳 + /// 是否在URL末尾添加时间戳 /// - public bool AppendTimeTicks { get; set; } + public bool AppendTimeTicks { get; } /// /// 超时时间 /// - public int Timeout { get; set; } + public int Timeout { get; } /// - /// 创建请求版本选项 + /// 创建请求版本选项实例 /// /// 是否在URL末尾添加时间戳 /// 超时时间(秒) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageAsset.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageAsset.cs index ef0628e6..8c068543 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageAsset.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageAsset.cs @@ -4,7 +4,7 @@ using System.Linq; namespace YooAsset { /// - /// 清单中的资源对象 + /// 清单中的资源描述 /// [Serializable] internal class PackageAsset @@ -22,7 +22,7 @@ namespace YooAsset /// /// 资源GUID /// - public string AssetGUID; + public string AssetGuid; /// /// 资源的分类标签 @@ -50,7 +50,7 @@ namespace YooAsset /// 是否包含指定的标签 /// /// 要检查的标签数组 - /// 如果包含任意一个标签返回true,否则返回false + /// 如果包含任意一个标签返回true,否则返回false。 public bool HasAnyTag(string[] tags) { if (tags == null || tags.Length == 0) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs index 2484dcfd..1c076685 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; namespace YooAsset { /// - /// 清单中的资源包对象 + /// 清单中的资源包描述 /// [Serializable] internal class PackageBundle @@ -60,46 +60,6 @@ namespace YooAsset get { return FileHash; } } - /// - /// 资源包类型 - /// - public int BundleType - { - get - { - return _bundleType; - } - } - private int _bundleType; - - /// - /// 文件名称 - /// - public string FileName - { - get - { - if (string.IsNullOrEmpty(_fileName)) - throw new YooInternalException("File name cannot be null or empty."); - return _fileName; - } - } - private string _fileName; - - /// - /// 文件后缀名 - /// - public string FileExtension - { - get - { - if (string.IsNullOrEmpty(_fileExtension)) - throw new YooInternalException("File extension cannot be null or empty."); - return _fileExtension; - } - } - private string _fileExtension; - /// /// 包含的主资源集合 /// @@ -114,6 +74,11 @@ namespace YooAsset public readonly List ReferrerBundleIDs = new List(10); private readonly HashSet _referrerBundleIDs = new HashSet(); + private PackageManifest _manifest; + private bool _isInitialized; + private int _bundleType; + private string _fileName; + /// /// 创建资源包实例 @@ -128,10 +93,33 @@ namespace YooAsset /// 所属的资源清单 public void Initialize(PackageManifest manifest) { + _isInitialized = true; _manifest = manifest; _bundleType = manifest.BuildBundleType; - _fileExtension = PackageManifestHelper.GetRemoteBundleFileExtension(BundleName); - _fileName = PackageManifestHelper.GetRemoteBundleFileName(manifest.OutputNameStyle, BundleName, _fileExtension, FileHash); + string fileExtension = PackageManifestHelper.GetRemoteBundleFileExtension(BundleName); + _fileName = PackageManifestHelper.GetRemoteBundleFileName(manifest.OutputNameStyle, BundleName, fileExtension, FileHash); + } + + /// + /// 获取资源包类型 + /// + /// 返回资源包类型 + public int GetBundleType() + { + if (_isInitialized == false) + throw new YooInternalException("PackageBundle is not initialized."); + return _bundleType; + } + + /// + /// 获取文件名称 + /// + /// 返回资源包文件名称 + public string GetFileName() + { + if (_isInitialized == false) + throw new YooInternalException("PackageBundle is not initialized."); + return _fileName; } /// @@ -152,7 +140,7 @@ namespace YooAsset /// 是否包含指定的标签 /// /// 要检查的标签数组 - /// 如果包含任意一个标签返回true,否则返回false + /// 如果包含任意一个标签返回true,否则返回false。 public bool HasAnyTag(string[] tags) { if (tags == null || tags.Length == 0) @@ -171,21 +159,20 @@ namespace YooAsset /// /// 是否包含分类标签 /// - /// 如果包含至少一个标签返回true,否则返回false + /// 如果包含至少一个标签返回true,否则返回false。 public bool IsTagged() { return Tags != null && Tags.Length > 0; } #region 调试信息 - private PackageManifest _manifest; private List _debugReferrerBundleNames; /// /// 获取引用该资源包的资源包名称列表 /// /// 返回引用该资源包的所有资源包名称列表 - /// 仅用于调试目的,结果会被缓存 + /// 仅用于调试目的,结果会被缓存。 public List DebugGetReferrerBundleNames() { if (_debugReferrerBundleNames == null) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageDetails.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageDetails.cs index 63a20d44..98ef8071 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageDetails.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageDetails.cs @@ -2,78 +2,78 @@ namespace YooAsset { /// - /// 资源包裹的详细信息,用于外部查询包裹配置 + /// 资源包裹的详细信息,用于外部查询包裹配置。 /// public class PackageDetails { /// /// 文件版本 /// - public int FileVersion { get; set; } + public int FileVersion { get; internal set; } /// /// 启用可寻址资源定位 /// - public bool EnableAddressable { get; set; } + public bool EnableAddressable { get; internal set; } /// /// 支持无后缀名的资源定位地址 /// - public bool SupportExtensionless { get; set; } + public bool SupportExtensionless { get; internal set; } /// /// 资源定位地址大小写不敏感 /// - public bool LocationToLower { get; set; } + public bool LocationToLower { get; internal set; } /// /// 包含资源GUID数据 /// - public bool IncludeAssetGUID { get; set; } + public bool IncludeAssetGuid { get; internal set; } /// /// 使用可寻址地址代替资源路径 /// - public bool ReplaceAssetPathWithAddress { get; set; } + public bool ReplaceAssetPathWithAddress { get; internal set; } /// /// 文件名称样式 /// - public int OutputNameStyle { get; set; } + public int OutputNameStyle { get; internal set; } /// /// 构建资源包类型 /// - public int BuildBundleType { get; set; } + public int BuildBundleType { get; internal set; } /// /// 构建管线名称 /// - public string BuildPipeline { get; set; } + public string BuildPipeline { get; internal set; } /// /// 资源包裹名称 /// - public string PackageName { get; set; } + public string PackageName { get; internal set; } /// /// 资源包裹的版本信息 /// - public string PackageVersion { get; set; } + public string PackageVersion { get; internal set; } /// /// 资源包裹的备注信息 /// - public string PackageNote { get; set; } + public string PackageNote { get; internal set; } /// /// 主资源文件总数 /// - public int AssetTotalCount { get; set; } + public int AssetTotalCount { get; internal set; } /// /// 资源包文件总数 /// - public int BundleTotalCount { get; set; } + public int BundleTotalCount { get; internal set; } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs index a625c977..e428189e 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs @@ -34,7 +34,7 @@ namespace YooAsset /// /// 包含资源GUID数据 /// - public bool IncludeAssetGUID; + public bool IncludeAssetGuid; /// /// 使用可寻址地址代替资源路径 @@ -112,7 +112,7 @@ namespace YooAsset public Dictionary BundlesByFileName; /// - /// 资源包集合(提供BundleGUID获取PackageBundle) + /// 资源包集合(提供BundleGuid获取PackageBundle) /// [NonSerialized] public Dictionary BundlesByGuid; @@ -134,7 +134,7 @@ namespace YooAsset } else { - throw new System.ArgumentOutOfRangeException($"Invalid bundle ID: {bundleID}. Valid range is 0 to {BundleList.Count - 1}"); + throw new System.ArgumentOutOfRangeException($"Invalid bundle ID: {bundleID}. Valid range is 0 to {BundleList.Count - 1}."); } } @@ -144,8 +144,15 @@ namespace YooAsset var sourceBundle = BundleList[index]; foreach (int dependIndex in sourceBundle.DependentBundleIDs) { - var dependBundle = BundleList[dependIndex]; - dependBundle.AddReferrerBundleID(index); + if (dependIndex >= 0 && dependIndex < BundleList.Count) + { + var dependBundle = BundleList[dependIndex]; + dependBundle.AddReferrerBundleID(index); + } + else + { + throw new System.ArgumentOutOfRangeException($"Invalid dependent bundle index: {dependIndex}. Valid range is 0 to {BundleList.Count - 1}."); + } } } } @@ -161,7 +168,7 @@ namespace YooAsset details.EnableAddressable = EnableAddressable; details.SupportExtensionless = SupportExtensionless; details.LocationToLower = LocationToLower; - details.IncludeAssetGUID = IncludeAssetGUID; + details.IncludeAssetGuid = IncludeAssetGuid; details.ReplaceAssetPathWithAddress = ReplaceAssetPathWithAddress; details.OutputNameStyle = OutputNameStyle; details.BuildBundleType = BuildBundleType; @@ -178,7 +185,7 @@ namespace YooAsset /// 尝试将定位地址映射为资源路径 /// /// 资源定位地址 - /// 如果映射成功返回资源路径,否则返回空字符串 + /// 如果映射成功返回资源路径,否则返回空字符串。 public string TryMappingToAssetPath(string location) { if (string.IsNullOrEmpty(location)) @@ -194,8 +201,8 @@ namespace YooAsset /// 获取主资源包 /// /// 资源包ID - /// 返回对应的资源包对象 - /// 传入的资源包ID必须合法有效,否则会抛出异常 + /// 返回对应的资源包描述 + /// 传入的资源包ID必须合法有效,否则会抛出异常。 public PackageBundle GetMainPackageBundle(int bundleID) { if (bundleID >= 0 && bundleID < BundleList.Count) @@ -207,27 +214,27 @@ namespace YooAsset } else { - throw new System.ArgumentOutOfRangeException($"Invalid bundle ID: {bundleID}. Valid range is 0 to {BundleList.Count - 1}"); + throw new System.ArgumentOutOfRangeException($"Invalid bundle ID: {bundleID}. Valid range is 0 to {BundleList.Count - 1}."); } } /// /// 获取主资源包 /// - /// 资源对象 - /// 返回资源对象所属的资源包 - /// 传入的资源对象必须合法有效,否则会抛出异常 + /// 资源描述 + /// 返回资源描述所属的资源包 + /// 传入的资源描述必须合法有效,否则会抛出异常。 public PackageBundle GetMainPackageBundle(PackageAsset packageAsset) { return GetMainPackageBundle(packageAsset.BundleID); } /// - /// 获取资源对象的所有依赖资源包列表 + /// 获取资源描述的所有依赖资源包列表 /// - /// 资源对象 + /// 资源描述 /// 返回依赖的资源包列表 - /// 框架层查询结果,传入的资源对象必须合法有效 + /// 框架层查询结果,传入的资源描述必须合法有效。 public List GetAllAssetDependencies(PackageAsset packageAsset) { List result = new List(packageAsset.DependentBundleIDs.Length); @@ -242,9 +249,9 @@ namespace YooAsset /// /// 获取资源包的所有依赖资源包列表 /// - /// 资源包对象 + /// 资源包描述 /// 返回依赖的资源包列表 - /// 引擎层查询结果,传入的资源包对象必须合法有效 + /// 引擎层查询结果,传入的资源包描述必须合法有效。 public List GetAllBundleDependencies(PackageBundle packageBundle) { List result = new List(packageBundle.DependentBundleIDs.Length); @@ -260,8 +267,8 @@ namespace YooAsset /// 尝试获取包裹的资源 /// /// 资源路径 - /// 输出的资源对象 - /// 如果找到返回true,否则返回false + /// 输出的资源描述 + /// 如果找到返回true,否则返回false。 public bool TryGetPackageAsset(string assetPath, out PackageAsset result) { return AssetDictionary.TryGetValue(assetPath, out result); @@ -271,8 +278,8 @@ namespace YooAsset /// 尝试通过文件名获取包裹的资源包 /// /// 文件名称 - /// 输出的资源包对象 - /// 如果找到返回true,否则返回false + /// 输出的资源包描述 + /// 如果找到返回true,否则返回false。 public bool TryGetPackageBundleByFileName(string fileName, out PackageBundle result) { return BundlesByFileName.TryGetValue(fileName, out result); @@ -282,8 +289,8 @@ namespace YooAsset /// 尝试通过资源包名称获取包裹的资源包 /// /// 资源包名称 - /// 输出的资源包对象 - /// 如果找到返回true,否则返回false + /// 输出的资源包描述 + /// 如果找到返回true,否则返回false。 public bool TryGetPackageBundleByBundleName(string bundleName, out PackageBundle result) { return BundlesByBundleName.TryGetValue(bundleName, out result); @@ -292,22 +299,22 @@ namespace YooAsset /// /// 尝试通过资源包GUID获取包裹的资源包 /// - /// 资源包GUID - /// 输出的资源包对象 - /// 如果找到返回true,否则返回false - public bool TryGetPackageBundleByBundleGUID(string bundleGUID, out PackageBundle result) + /// 资源包GUID + /// 输出的资源包描述 + /// 如果找到返回true,否则返回false。 + public bool TryGetPackageBundleByBundleGuid(string bundleGuid, out PackageBundle result) { - return BundlesByGuid.TryGetValue(bundleGUID, out result); + return BundlesByGuid.TryGetValue(bundleGuid, out result); } /// /// 是否包含指定的资源文件 /// - /// 资源包GUID - /// 如果包含返回true,否则返回false - public bool ContainsBundle(string bundleGUID) + /// 资源包GUID + /// 如果包含返回true,否则返回false。 + public bool ContainsBundle(string bundleGuid) { - return BundlesByGuid.ContainsKey(bundleGUID); + return BundlesByGuid.ContainsKey(bundleGuid); } /// @@ -350,7 +357,7 @@ namespace YooAsset /// /// 资源定位地址 /// 资源类型 - /// 返回资源信息对象,如果转换失败会返回一个无效的资源信息 + /// 返回资源信息对象,如果转换失败会返回一个无效的资源信息。 public AssetInfo ConvertLocationToAssetInfo(string location, System.Type assetType) { DebugCheckLocation(location); @@ -365,9 +372,9 @@ namespace YooAsset { string error; if (string.IsNullOrEmpty(location)) - error = $"The location is null or empty."; + error = "Location is null or empty."; else - error = $"The location is invalid: {location}"; + error = $"Location is invalid: '{location}'."; AssetInfo assetInfo = new AssetInfo(PackageName, error); return assetInfo; } @@ -376,7 +383,7 @@ namespace YooAsset { if (string.IsNullOrEmpty(location)) { - YooLogger.Error("Failed to map location to asset path, the location is null or empty."); + YooLogger.LogError("Failed to map location to asset path. Location is null or empty."); return string.Empty; } @@ -386,7 +393,7 @@ namespace YooAsset } else { - YooLogger.Warning($"Failed to map location to asset path: {location}"); + YooLogger.LogWarning($"Failed to map location to asset path: '{location}'."); return string.Empty; } } @@ -396,17 +403,17 @@ namespace YooAsset /// /// 资源GUID /// 资源类型 - /// 返回资源信息对象,如果转换失败会返回一个无效的资源信息 - public AssetInfo ConvertAssetGUIDToAssetInfo(string assetGUID, System.Type assetType) + /// 返回资源信息对象,如果转换失败会返回一个无效的资源信息。 + public AssetInfo ConvertAssetGuidToAssetInfo(string assetGuid, System.Type assetType) { - if (IncludeAssetGUID == false) + if (IncludeAssetGuid == false) { - YooLogger.Warning("Package manifest does not include asset GUID. Please check asset bundle collector settings."); - AssetInfo assetInfo = new AssetInfo(PackageName, "AssetGUID data is empty."); + YooLogger.LogWarning("Package manifest does not include asset GUID. Please check asset bundle collector settings."); + AssetInfo assetInfo = new AssetInfo(PackageName, "AssetGuid data is empty."); return assetInfo; } - string assetPath = ResolveGuidToAssetPath(assetGUID); + string assetPath = ResolveGuidToAssetPath(assetGuid); if (TryGetPackageAsset(assetPath, out PackageAsset packageAsset)) { AssetInfo assetInfo = new AssetInfo(PackageName, packageAsset, assetType); @@ -415,29 +422,29 @@ namespace YooAsset else { string error; - if (string.IsNullOrEmpty(assetGUID)) - error = $"The assetGUID is null or empty."; + if (string.IsNullOrEmpty(assetGuid)) + error = "Asset GUID is null or empty."; else - error = $"The asset GUID is invalid: {assetGUID}"; + error = $"Asset GUID is invalid: '{assetGuid}'."; AssetInfo assetInfo = new AssetInfo(PackageName, error); return assetInfo; } } - private string ResolveGuidToAssetPath(string assetGUID) + private string ResolveGuidToAssetPath(string assetGuid) { - if (string.IsNullOrEmpty(assetGUID)) + if (string.IsNullOrEmpty(assetGuid)) { - YooLogger.Error("Failed to map asset GUID to asset path, the asset GUID is null or empty."); + YooLogger.LogError("Failed to map asset GUID to asset path. Asset GUID is null or empty."); return string.Empty; } - if (AssetPathsByGuid.TryGetValue(assetGUID, out string assetPath)) + if (AssetPathsByGuid.TryGetValue(assetGuid, out string assetPath)) { return assetPath; } else { - YooLogger.Warning($"Failed to map asset GUID to asset path: {assetGUID}"); + YooLogger.LogWarning($"Failed to map asset GUID to asset path: '{assetGuid}'."); return string.Empty; } } @@ -453,11 +460,11 @@ namespace YooAsset if (index != -1) { if (location.Length == index + 1) - YooLogger.Warning($"Found trailing whitespace in location: \"{location}\""); + YooLogger.LogWarning($"Found trailing whitespace in location: '{location}'."); } if (location.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0) - YooLogger.Warning($"Found invalid path character in location: \"{location}\""); + YooLogger.LogWarning($"Found invalid path character in location: '{location}'."); } } #endregion diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestConsts.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestConsts.cs index a338136a..348d6804 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestConsts.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestConsts.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 清单文件常量定义 /// - internal class PackageManifestConsts + internal static class PackageManifestConsts { /// /// 文件极限大小(100MB) @@ -20,5 +20,10 @@ namespace YooAsset /// 文件版本号 /// public const int FileVersion = 1; + + /// + /// 文件最小合法大小(37字节) + /// + public const int MinFileSize = 37; } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestHelper.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestHelper.cs index 0f2bf457..93554ce4 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestHelper.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifestHelper.cs @@ -21,7 +21,7 @@ namespace YooAsset /// /// 文件二进制数据 /// 期望的哈希值 - /// 如果验证通过返回true,否则返回false + /// 如果验证通过返回true,否则返回false。 public static bool VerifyManifestData(byte[] fileData, string hashValue) { if (fileData == null || fileData.Length == 0) @@ -73,7 +73,7 @@ namespace YooAsset buffer.WriteBoolean(manifest.EnableAddressable); buffer.WriteBoolean(manifest.SupportExtensionless); buffer.WriteBoolean(manifest.LocationToLower); - buffer.WriteBoolean(manifest.IncludeAssetGUID); + buffer.WriteBoolean(manifest.IncludeAssetGuid); buffer.WriteBoolean(manifest.ReplaceAssetPathWithAddress); buffer.WriteInt32(manifest.OutputNameStyle); buffer.WriteInt32(manifest.BuildBundleType); @@ -89,7 +89,7 @@ namespace YooAsset var packageAsset = manifest.AssetList[i]; buffer.WriteString(packageAsset.Address); buffer.WriteString(packageAsset.AssetPath); - buffer.WriteString(packageAsset.AssetGUID); + buffer.WriteString(packageAsset.AssetGuid); buffer.WriteStringArray(packageAsset.AssetTags); buffer.WriteInt32(packageAsset.BundleID); buffer.WriteInt32Array(packageAsset.DependentBundleIDs); @@ -204,7 +204,7 @@ namespace YooAsset } default: - throw new NotImplementedException($"Invalid name style: {nameStyle}"); + throw new NotImplementedException($"Invalid name style: {nameStyle}."); } } } diff --git a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs index d28d7c66..05e26f55 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs @@ -18,7 +18,7 @@ namespace YooAsset /// /// 包裹名称 /// - public readonly string PackageName; + public string PackageName { get; } /// /// 包裹是否有效 @@ -84,12 +84,15 @@ namespace YooAsset } /// - /// 异步初始化包裹 + /// 初始化包裹 /// /// 初始化参数 /// 返回初始化操作对象 public InitializePackageOperation InitializePackageAsync(InitializePackageOptions options) { + if (options == null) + throw new System.ArgumentNullException(nameof(options)); + // 注意:联机平台因为网络原因可能会初始化失败! TryResetAfterFailure(); @@ -111,7 +114,7 @@ namespace YooAsset } /// - /// 异步销毁包裹 + /// 销毁包裹 /// /// 返回销毁包裹操作对象 public DestroyPackageOperation DestroyPackageAsync() @@ -159,7 +162,7 @@ namespace YooAsset // 注意:强烈建议在更新之前保持加载器为空! if (_resourceManager.HasAnyLoader()) { - YooLogger.Warning($"Found loaded bundles before updating the manifest. It is recommended to call the {nameof(UnloadAllAssetsAsync)} method to release loaded bundles."); + YooLogger.LogWarning($"Found loaded bundles before updating the manifest. It is recommended to call the {nameof(UnloadAllAssetsAsync)} method to release loaded bundles."); } var operation = new LoadPackageManifestOperation(_fileSystemHost, options); @@ -188,7 +191,6 @@ namespace YooAsset public ClearCacheOperation ClearCacheAsync(ClearCacheOptions options) { CheckInitialized(false); - options.Manifest = _fileSystemHost.ActiveManifest; var operation = new ClearCacheOperation(_fileSystemHost, options); AsyncOperationSystem.StartOperation(PackageName, operation); return operation; @@ -255,7 +257,7 @@ namespace YooAsset /// 回收不再使用的资源 /// /// 返回卸载未使用资源操作对象 - /// 卸载引用计数为零的资源,默认循环10次 + /// 卸载引用计数为零的资源,默认循环10次。 public UnloadUnusedAssetsOperation UnloadUnusedAssetsAsync() { int defaultMaxLoopCount = 10; @@ -306,7 +308,7 @@ namespace YooAsset /// 获取指定资源需要下载的文件总大小 /// /// 资源的定位地址 - /// 返回需要下载的字节数,0 表示不需要下载 + /// 返回需要下载的字节数,0 表示不需要下载。 public long GetDownloadSize(string location) { CheckInitialized(); @@ -318,7 +320,7 @@ namespace YooAsset /// 获取指定资源需要下载的文件总大小 /// /// 资源信息 - /// 返回需要下载的字节数,0 表示不需要下载 + /// 返回需要下载的字节数,0 表示不需要下载。 public long GetDownloadSize(AssetInfo assetInfo) { CheckInitialized(); @@ -384,31 +386,31 @@ namespace YooAsset /// /// 获取资源信息 /// - /// 资源GUID + /// 资源GUID /// 返回资源信息对象 - public AssetInfo GetAssetInfoByGUID(string assetGUID) + public AssetInfo GetAssetInfoByGuid(string assetGuid) { CheckInitialized(); - return ConvertAssetGUIDToAssetInfo(assetGUID, null); + return ConvertAssetGuidToAssetInfo(assetGuid, null); } /// /// 获取资源信息 /// - /// 资源GUID + /// 资源GUID /// 资源类型 /// 返回资源信息对象 - public AssetInfo GetAssetInfoByGUID(string assetGUID, System.Type type) + public AssetInfo GetAssetInfoByGuid(string assetGuid, System.Type type) { CheckInitialized(); - return ConvertAssetGUIDToAssetInfo(assetGUID, type); + return ConvertAssetGuidToAssetInfo(assetGuid, type); } /// /// 资源定位地址是否有效 /// /// 资源的定位地址 - /// 如果地址有效返回true,否则返回false + /// 如果地址有效返回true,否则返回false。 public bool IsLocationValid(string location) { CheckInitialized(); @@ -442,7 +444,7 @@ namespace YooAsset } /// - /// 异步加载原生文件 + /// 加载原生文件 /// /// 资源信息 /// 加载的优先级 @@ -454,7 +456,7 @@ namespace YooAsset } /// - /// 异步加载原生文件 + /// 加载原生文件 /// /// 资源的定位地址 /// 加载的优先级 @@ -469,7 +471,7 @@ namespace YooAsset private RawFileHandle LoadRawFileInternal(AssetInfo assetInfo, bool waitForAsyncComplete, uint priority) { - assetInfo.LoadMethod = AssetInfo.ELoadMethod.LoadRawFile; + assetInfo.LoadMethod = ELoadMethod.LoadRawFile; var handle = _resourceManager.LoadRawFileAsync(assetInfo, priority); if (waitForAsyncComplete) handle.WaitForAsyncComplete(); @@ -506,7 +508,7 @@ namespace YooAsset } /// - /// 异步加载场景 + /// 加载场景 /// /// 场景的定位地址 /// 场景加载模式 @@ -522,7 +524,7 @@ namespace YooAsset } /// - /// 异步加载场景 + /// 加载场景 /// /// 场景的资源信息 /// 场景加载模式 @@ -539,7 +541,7 @@ namespace YooAsset private SceneHandle LoadSceneInternal(AssetInfo assetInfo, bool waitForAsyncComplete, LoadSceneMode sceneMode, LocalPhysicsMode physicsMode, bool allowSceneActivation, uint priority) { DebugValidateAssetType(assetInfo.AssetType); - assetInfo.LoadMethod = AssetInfo.ELoadMethod.LoadScene; + assetInfo.LoadMethod = ELoadMethod.LoadScene; var loadSceneParams = new LoadSceneParameters(sceneMode, physicsMode); var handle = _resourceManager.LoadSceneAsync(assetInfo, loadSceneParams, allowSceneActivation, priority); if (waitForAsyncComplete) @@ -600,7 +602,7 @@ namespace YooAsset /// - /// 异步加载资源对象 + /// 加载资源对象 /// /// 资源信息 /// 加载的优先级 @@ -612,7 +614,7 @@ namespace YooAsset } /// - /// 异步加载资源对象 + /// 加载资源对象 /// /// 资源类型 /// 资源的定位地址 @@ -626,7 +628,7 @@ namespace YooAsset } /// - /// 异步加载资源对象 + /// 加载资源对象 /// /// 资源的定位地址 /// 资源类型 @@ -640,7 +642,7 @@ namespace YooAsset } /// - /// 异步加载资源对象 + /// 加载资源对象 /// /// 资源的定位地址 /// 加载的优先级 @@ -656,7 +658,7 @@ namespace YooAsset private AssetHandle LoadAssetInternal(AssetInfo assetInfo, bool waitForAsyncComplete, uint priority) { DebugValidateAssetType(assetInfo.AssetType); - assetInfo.LoadMethod = AssetInfo.ELoadMethod.LoadAsset; + assetInfo.LoadMethod = ELoadMethod.LoadAsset; var handle = _resourceManager.LoadAssetAsync(assetInfo, priority); if (waitForAsyncComplete) handle.WaitForAsyncComplete(); @@ -716,7 +718,7 @@ namespace YooAsset /// - /// 异步加载子资源对象 + /// 加载子资源对象 /// /// 资源信息 /// 加载的优先级 @@ -728,7 +730,7 @@ namespace YooAsset } /// - /// 异步加载子资源对象 + /// 加载子资源对象 /// /// 资源类型 /// 资源的定位地址 @@ -742,7 +744,7 @@ namespace YooAsset } /// - /// 异步加载子资源对象 + /// 加载子资源对象 /// /// 资源的定位地址 /// 子对象类型 @@ -756,7 +758,7 @@ namespace YooAsset } /// - /// 异步加载子资源对象 + /// 加载子资源对象 /// /// 资源的定位地址 /// 加载的优先级 @@ -772,7 +774,7 @@ namespace YooAsset private SubAssetsHandle LoadSubAssetsInternal(AssetInfo assetInfo, bool waitForAsyncComplete, uint priority) { DebugValidateAssetType(assetInfo.AssetType); - assetInfo.LoadMethod = AssetInfo.ELoadMethod.LoadSubAssets; + assetInfo.LoadMethod = ELoadMethod.LoadSubAssets; var handle = _resourceManager.LoadSubAssetsAsync(assetInfo, priority); if (waitForAsyncComplete) handle.WaitForAsyncComplete(); @@ -832,7 +834,7 @@ namespace YooAsset /// - /// 异步加载资源包内所有资源对象 + /// 加载资源包内所有资源对象 /// /// 资源信息 /// 加载的优先级 @@ -844,7 +846,7 @@ namespace YooAsset } /// - /// 异步加载资源包内所有资源对象 + /// 加载资源包内所有资源对象 /// /// 资源类型 /// 资源的定位地址 @@ -858,7 +860,7 @@ namespace YooAsset } /// - /// 异步加载资源包内所有资源对象 + /// 加载资源包内所有资源对象 /// /// 资源的定位地址 /// 子对象类型 @@ -872,7 +874,7 @@ namespace YooAsset } /// - /// 异步加载资源包内所有资源对象 + /// 加载资源包内所有资源对象 /// /// 资源的定位地址 /// 加载的优先级 @@ -888,7 +890,7 @@ namespace YooAsset private AllAssetsHandle LoadAllAssetsInternal(AssetInfo assetInfo, bool waitForAsyncComplete, uint priority) { DebugValidateAssetType(assetInfo.AssetType); - assetInfo.LoadMethod = AssetInfo.ELoadMethod.LoadAllAssets; + assetInfo.LoadMethod = ELoadMethod.LoadAllAssets; var handle = _resourceManager.LoadAllAssetsAsync(assetInfo, priority); if (waitForAsyncComplete) handle.WaitForAsyncComplete(); @@ -898,7 +900,7 @@ namespace YooAsset #region 资源下载 /// - /// 创建资源下载器,用于下载指定的资源标签关联的资源包文件 + /// 创建资源下载器,用于下载指定的资源标签关联的资源包文件。 /// /// 资源下载选项 /// 返回资源下载操作对象 @@ -909,7 +911,7 @@ namespace YooAsset } /// - /// 创建资源下载器,用于下载指定的资源信息列表依赖的资源包文件 + /// 创建资源下载器,用于下载指定的资源信息列表依赖的资源包文件。 /// /// 资源下载选项 /// 返回资源下载操作对象 @@ -922,7 +924,7 @@ namespace YooAsset #region 资源解压 /// - /// 创建内置资源解压器,用于解压指定的资源标签关联的资源包文件 + /// 创建内置资源解压器,用于解压指定的资源标签关联的资源包文件。 /// /// 资源解压选项 /// 返回资源解压操作对象 @@ -951,9 +953,9 @@ namespace YooAsset { return _fileSystemHost.ActiveManifest.ConvertLocationToAssetInfo(location, assetType); } - internal AssetInfo ConvertAssetGUIDToAssetInfo(string assetGUID, System.Type assetType) + internal AssetInfo ConvertAssetGuidToAssetInfo(string assetGuid, System.Type assetType) { - return _fileSystemHost.ActiveManifest.ConvertAssetGUIDToAssetInfo(assetGUID, assetType); + return _fileSystemHost.ActiveManifest.ConvertAssetGuidToAssetInfo(assetGuid, assetType); } #endregion @@ -990,10 +992,10 @@ namespace YooAsset return; if (typeof(UnityEngine.Behaviour).IsAssignableFrom(type)) - throw new System.ArgumentException($"Load asset type is invalid: {type.FullName}"); + throw new System.ArgumentException($"Load asset type is invalid: '{type.FullName}'.", nameof(type)); if (typeof(UnityEngine.Object).IsAssignableFrom(type) == false) - throw new System.ArgumentException($"Load asset type is invalid: {type.FullName}"); + throw new System.ArgumentException($"Load asset type is invalid: '{type.FullName}'.", nameof(type)); } #endregion diff --git a/Assets/YooAsset/Runtime/Settings/YooAssetConfiguration.cs b/Assets/YooAsset/Runtime/Settings/YooAssetConfiguration.cs index 2eb8dba2..32b82796 100644 --- a/Assets/YooAsset/Runtime/Settings/YooAssetConfiguration.cs +++ b/Assets/YooAsset/Runtime/Settings/YooAssetConfiguration.cs @@ -1,10 +1,11 @@ +using System; using System.IO; using UnityEngine; namespace YooAsset { /// - /// 提供 YooAsset 全局配置的访问入口。 + /// 提供 YooAsset 全局配置的访问入口 /// public static class YooAssetConfiguration { @@ -12,185 +13,223 @@ namespace YooAsset [UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)] private static void OnRuntimeInitialize() { - s_settings = null; + if (s_settings != null) + { + if (UnityEditor.AssetDatabase.Contains(s_settings) == false) + UnityEngine.Object.DestroyImmediate(s_settings); + s_settings = null; + } } #endif private static YooAssetSettings s_settings = null; - internal static YooAssetSettings Settings - { - get - { - if (s_settings == null) - LoadSettings(); - return s_settings; - } - } /// - /// 加载配置文件 + /// 获取全局配置实例 /// - private static void LoadSettings() + /// 全局配置实例 + /// 首次调用时从 Resources 加载,加载失败则创建默认实例 + internal static YooAssetSettings GetSettings() { - s_settings = Resources.Load("YooAssetSettings"); if (s_settings == null) { - YooLogger.Log("No YooAssetSettings found, using default configuration."); - s_settings = ScriptableObject.CreateInstance(); - } - else - { - YooLogger.Log("YooAssetSettings loaded successfully."); + s_settings = Resources.Load("YooAssetSettings"); + if (s_settings == null) + { + YooLogger.Log("YooAssetSettings not found, using default configuration."); + s_settings = ScriptableObject.CreateInstance(); + } + else + { + YooLogger.Log("YooAssetSettings loaded successfully."); + } } + return s_settings; } /// - /// 资源包裹的根文件夹名称。 + /// 获取资源包裹的根文件夹名称 /// /// 文件夹名称。如果未配置则返回默认值 "yoo"。 public static string GetYooFolderName() { - return Settings.YooFolderName; + return GetSettings().YooFolderName; } /// - /// 获取构建报告的文件名。 + /// 获取构建报告的文件名 /// - /// 包裹名称。 - /// 包裹版本号。 - /// 包含 .report 扩展名的文件名。 + /// 包裹名称 + /// 包裹版本号 + /// 包含 .report 扩展名的文件名 public static string GetBuildReportFileName(string packageName, string packageVersion) { - if (string.IsNullOrEmpty(Settings.PackageFilePrefix)) + if (string.IsNullOrEmpty(packageName)) + throw new ArgumentNullException(nameof(packageName)); + if (string.IsNullOrEmpty(packageVersion)) + throw new ArgumentNullException(nameof(packageVersion)); + + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.PackageFilePrefix)) return $"{packageName}_{packageVersion}.report"; else - return $"{Settings.PackageFilePrefix}_{packageName}_{packageVersion}.report"; + return $"{settings.PackageFilePrefix}_{packageName}_{packageVersion}.report"; } /// - /// 获取清单二进制文件的文件名。 + /// 获取清单二进制文件的文件名 /// - /// 包裹名称。 - /// 包裹版本号。 - /// 包含 .bytes 扩展名的文件名。 + /// 包裹名称 + /// 包裹版本号 + /// 包含 .bytes 扩展名的文件名 public static string GetManifestBinaryFileName(string packageName, string packageVersion) { - if (string.IsNullOrEmpty(Settings.PackageFilePrefix)) + if (string.IsNullOrEmpty(packageName)) + throw new ArgumentNullException(nameof(packageName)); + if (string.IsNullOrEmpty(packageVersion)) + throw new ArgumentNullException(nameof(packageVersion)); + + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.PackageFilePrefix)) return $"{packageName}_{packageVersion}.bytes"; else - return $"{Settings.PackageFilePrefix}_{packageName}_{packageVersion}.bytes"; + return $"{settings.PackageFilePrefix}_{packageName}_{packageVersion}.bytes"; } /// - /// 获取清单 JSON 文件的文件名。 + /// 获取清单 JSON 文件的文件名 /// - /// 包裹名称。 - /// 包裹版本号。 - /// 包含 .json 扩展名的文件名。 + /// 包裹名称 + /// 包裹版本号 + /// 包含 .json 扩展名的文件名 public static string GetManifestJsonFileName(string packageName, string packageVersion) { - if (string.IsNullOrEmpty(Settings.PackageFilePrefix)) + if (string.IsNullOrEmpty(packageName)) + throw new ArgumentNullException(nameof(packageName)); + if (string.IsNullOrEmpty(packageVersion)) + throw new ArgumentNullException(nameof(packageVersion)); + + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.PackageFilePrefix)) return $"{packageName}_{packageVersion}.json"; else - return $"{Settings.PackageFilePrefix}_{packageName}_{packageVersion}.json"; + return $"{settings.PackageFilePrefix}_{packageName}_{packageVersion}.json"; } /// - /// 获取包裹的哈希校验文件名。 + /// 获取包裹的哈希校验文件名 /// - /// 包裹名称。 - /// 包裹版本号。 - /// 包含 .hash 扩展名的文件名。 + /// 包裹名称 + /// 包裹版本号 + /// 包含 .hash 扩展名的文件名 public static string GetPackageHashFileName(string packageName, string packageVersion) { - if (string.IsNullOrEmpty(Settings.PackageFilePrefix)) + if (string.IsNullOrEmpty(packageName)) + throw new ArgumentNullException(nameof(packageName)); + if (string.IsNullOrEmpty(packageVersion)) + throw new ArgumentNullException(nameof(packageVersion)); + + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.PackageFilePrefix)) return $"{packageName}_{packageVersion}.hash"; else - return $"{Settings.PackageFilePrefix}_{packageName}_{packageVersion}.hash"; + return $"{settings.PackageFilePrefix}_{packageName}_{packageVersion}.hash"; } /// - /// 获取包裹的版本记录文件名。 + /// 获取包裹的版本记录文件名 /// - /// 包裹名称。 - /// 包含 .version 扩展名的文件名。 + /// 包裹名称 + /// 包含 .version 扩展名的文件名 public static string GetPackageVersionFileName(string packageName) { - if (string.IsNullOrEmpty(Settings.PackageFilePrefix)) + if (string.IsNullOrEmpty(packageName)) + throw new ArgumentNullException(nameof(packageName)); + + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.PackageFilePrefix)) return $"{packageName}.version"; else - return $"{Settings.PackageFilePrefix}_{packageName}.version"; + return $"{settings.PackageFilePrefix}_{packageName}.version"; } #region 路径相关 /// /// 获取编辑器下缓存文件根目录 /// + /// 缓存文件根目录的绝对路径 internal static string GetEditorCacheRoot() { - if (string.IsNullOrEmpty(Settings.YooFolderName)) - { - string projectPath = Path.GetDirectoryName(Application.dataPath); - projectPath = PathUtility.NormalizePath(projectPath); + // 注意:为了方便调试查看,编辑器下把存储目录放到项目根目录下。 + string projectPath = Path.GetDirectoryName(Application.dataPath); + if (string.IsNullOrEmpty(projectPath)) + throw new InvalidOperationException("Could not determine project root path from Application.dataPath."); + projectPath = PathUtility.NormalizePath(projectPath); + + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.YooFolderName)) return projectPath; - } else - { - // 注意:为了方便调试查看,编辑器下把存储目录放到项目根目录下。 - string projectPath = Path.GetDirectoryName(Application.dataPath); - projectPath = PathUtility.NormalizePath(projectPath); - return PathUtility.Combine(projectPath, Settings.YooFolderName); - } + return PathUtility.Combine(projectPath, settings.YooFolderName); } /// /// 获取PC平台缓存文件根目录 /// + /// 缓存文件根目录的绝对路径 internal static string GetWindowsCacheRoot() { - if (string.IsNullOrEmpty(Settings.YooFolderName)) + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.YooFolderName)) return Application.dataPath; else - return PathUtility.Combine(Application.dataPath, Settings.YooFolderName); + return PathUtility.Combine(Application.dataPath, settings.YooFolderName); } /// /// 获取Linux平台缓存文件根目录 /// + /// 缓存文件根目录的绝对路径 internal static string GetLinuxCacheRoot() { - if (string.IsNullOrEmpty(Settings.YooFolderName)) + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.YooFolderName)) return Application.dataPath; else - return PathUtility.Combine(Application.dataPath, Settings.YooFolderName); + return PathUtility.Combine(Application.dataPath, settings.YooFolderName); } /// /// 获取Mac平台缓存文件根目录 /// + /// 缓存文件根目录的绝对路径 internal static string GetMacCacheRoot() { - if (string.IsNullOrEmpty(Settings.YooFolderName)) + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.YooFolderName)) return Application.persistentDataPath; else - return PathUtility.Combine(Application.persistentDataPath, Settings.YooFolderName); + return PathUtility.Combine(Application.persistentDataPath, settings.YooFolderName); } /// /// 获取移动平台缓存文件根目录 /// + /// 缓存文件根目录的绝对路径 internal static string GetMobileCacheRoot() { - if (string.IsNullOrEmpty(Settings.YooFolderName)) + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.YooFolderName)) return Application.persistentDataPath; else - return PathUtility.Combine(Application.persistentDataPath, Settings.YooFolderName); + return PathUtility.Combine(Application.persistentDataPath, settings.YooFolderName); } /// /// 获取默认的缓存文件根目录 /// + /// 缓存文件根目录的绝对路径 internal static string GetDefaultCacheRoot() { #if UNITY_EDITOR @@ -209,12 +248,14 @@ namespace YooAsset /// /// 获取默认的内置文件根目录 /// + /// 内置文件根目录的绝对路径 internal static string GetDefaultBuiltinRoot() { - if (string.IsNullOrEmpty(Settings.YooFolderName)) + var settings = GetSettings(); + if (string.IsNullOrEmpty(settings.YooFolderName)) return Application.streamingAssetsPath; else - return PathUtility.Combine(Application.streamingAssetsPath, Settings.YooFolderName); + return PathUtility.Combine(Application.streamingAssetsPath, settings.YooFolderName); } #endregion } diff --git a/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs b/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs index 2e27db55..ec2b5d27 100644 --- a/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs +++ b/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs @@ -9,15 +9,15 @@ namespace YooAsset internal class YooAssetSettings : ScriptableObject { /// - /// 资源包裹的根文件夹名称。 + /// 资源包裹的根文件夹名称 /// - /// 设为空则直接使用平台默认路径。 + /// 设为空则直接使用平台默认路径 public string YooFolderName = "yoo"; /// - /// 资源包裹的文件名称前缀。 + /// 资源包裹的文件名称前缀 /// - /// 设为空则不添加前缀。 + /// 设为空则不添加前缀 public string PackageFilePrefix = string.Empty; @@ -25,5 +25,15 @@ namespace YooAsset /// 构建输出文件夹名称 /// public const string OutputFolderName = "OutputCache"; + +#if UNITY_EDITOR + private void OnValidate() + { + if (PathUtility.ContainsInvalidFileNameChars(YooFolderName)) + Debug.LogError($"YooFolderName '{YooFolderName}' contains invalid file name characters."); + if (PathUtility.ContainsInvalidFileNameChars(PackageFilePrefix)) + Debug.LogError($"PackageFilePrefix '{PackageFilePrefix}' contains invalid file name characters."); + } +#endif } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/Utility/BufferReader.cs b/Assets/YooAsset/Runtime/Utility/BufferReader.cs index f3b615e3..d3f70fa5 100644 --- a/Assets/YooAsset/Runtime/Utility/BufferReader.cs +++ b/Assets/YooAsset/Runtime/Utility/BufferReader.cs @@ -19,6 +19,8 @@ namespace YooAsset /// public BufferReader(byte[] data) { + if (data == null) + throw new ArgumentNullException(nameof(data)); _buffer = data; } @@ -37,7 +39,7 @@ namespace YooAsset } /// - /// 获取缓冲区的总字节数 + /// 缓冲区的总字节数 /// public int Capacity { @@ -208,7 +210,7 @@ namespace YooAsset { if (_position + length > Capacity) { - throw new IndexOutOfRangeException(); + throw new InvalidOperationException("Insufficient buffer capacity."); } } } diff --git a/Assets/YooAsset/Runtime/Utility/BufferWriter.cs b/Assets/YooAsset/Runtime/Utility/BufferWriter.cs index ad7b8f64..b70e7509 100644 --- a/Assets/YooAsset/Runtime/Utility/BufferWriter.cs +++ b/Assets/YooAsset/Runtime/Utility/BufferWriter.cs @@ -24,7 +24,7 @@ namespace YooAsset } /// - /// 获取缓冲区的总字节数 + /// 缓冲区的总字节数 /// public int Capacity { @@ -62,6 +62,8 @@ namespace YooAsset /// public void WriteBytes(byte[] data) { + if (data == null) + throw new ArgumentNullException(nameof(data)); int count = data.Length; EnsureCapacity(count); Buffer.BlockCopy(data, 0, _buffer, _position, count); @@ -156,7 +158,10 @@ namespace YooAsset /// public void WriteString(string value) { - if (string.IsNullOrEmpty(value)) + if (value == null) + throw new ArgumentNullException(nameof(value)); + + if (value.Length == 0) { WriteUInt16(0); } @@ -179,20 +184,16 @@ namespace YooAsset public void WriteInt32Array(int[] values) { if (values == null) - { - WriteUInt16(0); - } - else - { - int count = values.Length; - if (count > ushort.MaxValue) - throw new OverflowException($"Array length exceeds the maximum value of {ushort.MaxValue}."); + throw new ArgumentNullException(nameof(values)); - WriteUInt16(Convert.ToUInt16(count)); - for (int i = 0; i < count; i++) - { - WriteInt32(values[i]); - } + int count = values.Length; + if (count > ushort.MaxValue) + throw new OverflowException($"Array length exceeds the maximum value of {ushort.MaxValue}."); + + WriteUInt16(Convert.ToUInt16(count)); + for (int i = 0; i < count; i++) + { + WriteInt32(values[i]); } } @@ -202,20 +203,16 @@ namespace YooAsset public void WriteInt64Array(long[] values) { if (values == null) - { - WriteUInt16(0); - } - else - { - int count = values.Length; - if (count > ushort.MaxValue) - throw new OverflowException($"Array length exceeds the maximum value of {ushort.MaxValue}."); + throw new ArgumentNullException(nameof(values)); - WriteUInt16(Convert.ToUInt16(count)); - for (int i = 0; i < count; i++) - { - WriteInt64(values[i]); - } + int count = values.Length; + if (count > ushort.MaxValue) + throw new OverflowException($"Array length exceeds the maximum value of {ushort.MaxValue}."); + + WriteUInt16(Convert.ToUInt16(count)); + for (int i = 0; i < count; i++) + { + WriteInt64(values[i]); } } @@ -225,20 +222,16 @@ namespace YooAsset public void WriteStringArray(string[] values) { if (values == null) - { - WriteUInt16(0); - } - else - { - int count = values.Length; - if (count > ushort.MaxValue) - throw new OverflowException($"Array length exceeds the maximum value of {ushort.MaxValue}."); + throw new ArgumentNullException(nameof(values)); - WriteUInt16(Convert.ToUInt16(count)); - for (int i = 0; i < count; i++) - { - WriteString(values[i]); - } + int count = values.Length; + if (count > ushort.MaxValue) + throw new OverflowException($"Array length exceeds the maximum value of {ushort.MaxValue}."); + + WriteUInt16(Convert.ToUInt16(count)); + for (int i = 0; i < count; i++) + { + WriteString(values[i]); } } @@ -247,7 +240,7 @@ namespace YooAsset { if (_position + length > Capacity) { - throw new IndexOutOfRangeException(); + throw new InvalidOperationException("Insufficient buffer capacity."); } } } diff --git a/Assets/YooAsset/Runtime/Utility/CRC32Algorithm.cs b/Assets/YooAsset/Runtime/Utility/CRC32Algorithm.cs index b2b64284..4c2b0fc4 100644 --- a/Assets/YooAsset/Runtime/Utility/CRC32Algorithm.cs +++ b/Assets/YooAsset/Runtime/Utility/CRC32Algorithm.cs @@ -133,9 +133,10 @@ namespace YooAsset public static uint Append(uint initial, byte[] input, int offset, int length) { if (input == null) - throw new ArgumentNullException("input"); - if (offset < 0 || length < 0 || offset + length > input.Length) - throw new ArgumentOutOfRangeException("length"); + throw new ArgumentNullException(nameof(input)); + long end = (long)offset + length; + if (offset < 0 || length < 0 || end > input.Length) + throw new ArgumentOutOfRangeException(nameof(length)); return AppendInternal(initial, input, offset, length); } @@ -152,7 +153,7 @@ namespace YooAsset public static uint Append(uint initial, byte[] input) { if (input == null) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(input)); return AppendInternal(initial, input, 0, input.Length); } @@ -188,7 +189,7 @@ namespace YooAsset public static uint ComputeAndWriteToEnd(byte[] input, int offset, int length) { if (length + 4 > input.Length) - throw new ArgumentOutOfRangeException("length", "Data length exceeds buffer capacity (need 4 bytes reserved for CRC)"); + throw new ArgumentOutOfRangeException(nameof(length), "Data length exceeds buffer capacity (4 bytes must be reserved for CRC)."); var crc = Append(0, input, offset, length); var r = offset + length; input[r] = (byte)crc; @@ -206,7 +207,7 @@ namespace YooAsset public static uint ComputeAndWriteToEnd(byte[] input) { if (input.Length < 4) - throw new ArgumentOutOfRangeException("input", "Input array must be at least 4 bytes"); + throw new ArgumentOutOfRangeException(nameof(input), "Input array must be at least 4 bytes."); return ComputeAndWriteToEnd(input, 0, input.Length - 4); } @@ -230,17 +231,17 @@ namespace YooAsset public static bool IsValidWithCrcAtEnd(byte[] input) { if (input.Length < 4) - throw new ArgumentOutOfRangeException("input", "Input array must be at least 4 bytes"); + throw new ArgumentOutOfRangeException(nameof(input), "Input array must be at least 4 bytes."); return Append(0, input, 0, input.Length) == 0x2144DF1C; } - private static readonly Crc32Table _table = new Crc32Table(); + private static readonly Crc32Table s_table = new Crc32Table(); private static uint AppendInternal(uint initial, byte[] input, int offset, int length) { if (length > 0) { - return _table.Append(initial, input, offset, length); + return s_table.Append(initial, input, offset, length); } else return initial; diff --git a/Assets/YooAsset/Runtime/Utility/Utilities/FileUtility.cs b/Assets/YooAsset/Runtime/Utility/Utilities/FileUtility.cs index 878131cc..48b76938 100644 --- a/Assets/YooAsset/Runtime/Utility/Utilities/FileUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/Utilities/FileUtility.cs @@ -28,7 +28,7 @@ namespace YooAsset public static string ReadAllText(string filePath) { if (File.Exists(filePath) == false) - return null; + return string.Empty; return File.ReadAllText(filePath, Encoding.UTF8); } @@ -39,7 +39,7 @@ namespace YooAsset public static byte[] ReadAllBytes(string filePath) { if (File.Exists(filePath) == false) - return null; + return Array.Empty(); return File.ReadAllBytes(filePath); } @@ -49,7 +49,11 @@ namespace YooAsset /// public static void WriteAllText(string filePath, string content) { - // 创建文件夹路径 + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + if (content == null) + throw new ArgumentNullException(nameof(content)); + EnsureParentDirectoryExists(filePath); byte[] bytes = Encoding.UTF8.GetBytes(content); @@ -61,7 +65,11 @@ namespace YooAsset /// public static void WriteAllBytes(string filePath, byte[] data) { - // 创建文件夹路径 + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + if (data == null) + throw new ArgumentNullException(nameof(data)); + EnsureParentDirectoryExists(filePath); File.WriteAllBytes(filePath, data); diff --git a/Assets/YooAsset/Runtime/Utility/Utilities/HashUtility.cs b/Assets/YooAsset/Runtime/Utility/Utilities/HashUtility.cs index efd196cc..cadbf54d 100644 --- a/Assets/YooAsset/Runtime/Utility/Utilities/HashUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/Utilities/HashUtility.cs @@ -12,66 +12,30 @@ namespace YooAsset { private static string ToHexString(byte[] hashBytes) { - string result = BitConverter.ToString(hashBytes); - result = result.Replace("-", ""); - return result.ToLower(); - } - - #region SHA1 - /// - /// 计算字符串的SHA1哈希值 - /// - public static string ComputeSHA1(string str) - { - byte[] buffer = Encoding.UTF8.GetBytes(str); - return ComputeSHA1(buffer); - } - - /// - /// 计算文件的SHA1哈希值 - /// - public static string ComputeFileSHA1(string filePath) - { - using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + char[] chars = new char[hashBytes.Length * 2]; + for (int i = 0; i < hashBytes.Length; i++) { - return ComputeSHA1(fs); + byte b = hashBytes[i]; + chars[i * 2] = GetHexChar(b >> 4); + chars[i * 2 + 1] = GetHexChar(b & 0xF); } + return new string(chars); } - - /// - /// 计算数据流的SHA1哈希值 - /// - public static string ComputeSHA1(Stream stream) + private static char GetHexChar(int value) { - // 说明:创建的是SHA1类的实例,生成的是160位的散列码 - using (HashAlgorithm hash = HashAlgorithm.Create()) - { - byte[] hashBytes = hash.ComputeHash(stream); - return ToHexString(hashBytes); - } + return (char)(value < 10 ? '0' + value : 'a' + value - 10); } - /// - /// 计算字节数组的SHA1哈希值 - /// - public static string ComputeSHA1(byte[] buffer) - { - // 说明:创建的是SHA1类的实例,生成的是160位的散列码 - using (HashAlgorithm hash = HashAlgorithm.Create()) - { - byte[] hashBytes = hash.ComputeHash(buffer); - return ToHexString(hashBytes); - } - } - #endregion - #region MD5 /// /// 计算字符串的MD5哈希值 /// - public static string ComputeMD5(string str) + public static string ComputeMD5(string value) { - byte[] buffer = Encoding.UTF8.GetBytes(str); + if (value == null) + throw new ArgumentNullException(nameof(value)); + + byte[] buffer = Encoding.UTF8.GetBytes(value); return ComputeMD5(buffer); } @@ -80,6 +44,9 @@ namespace YooAsset /// public static string ComputeFileMD5(string filePath) { + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { return ComputeMD5(fs); @@ -91,9 +58,12 @@ namespace YooAsset /// public static string ComputeMD5(Stream stream) { - using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider()) + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (var md5 = MD5.Create()) { - byte[] hashBytes = provider.ComputeHash(stream); + byte[] hashBytes = md5.ComputeHash(stream); return ToHexString(hashBytes); } } @@ -103,9 +73,12 @@ namespace YooAsset /// public static string ComputeMD5(byte[] buffer) { - using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider()) + if (buffer == null) + throw new ArgumentNullException(nameof(buffer)); + + using (var md5 = MD5.Create()) { - byte[] hashBytes = provider.ComputeHash(buffer); + byte[] hashBytes = md5.ComputeHash(buffer); return ToHexString(hashBytes); } } @@ -115,18 +88,24 @@ namespace YooAsset /// /// 计算字符串的CRC32哈希值 /// - public static string ComputeCrc32(string str) + public static string ComputeCrc32(string value) { - byte[] buffer = Encoding.UTF8.GetBytes(str); + if (value == null) + throw new ArgumentNullException(nameof(value)); + + byte[] buffer = Encoding.UTF8.GetBytes(value); return ComputeCrc32(buffer); } /// /// 计算字符串的CRC32值(返回无符号整数) /// - public static uint ComputeCrc32AsUInt(string str) + public static uint ComputeCrc32AsUInt(string value) { - byte[] buffer = Encoding.UTF8.GetBytes(str); + if (value == null) + throw new ArgumentNullException(nameof(value)); + + byte[] buffer = Encoding.UTF8.GetBytes(value); return ComputeCrc32AsUInt(buffer); } @@ -135,6 +114,9 @@ namespace YooAsset /// public static string ComputeFileCrc32(string filePath) { + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { return ComputeCrc32(fs); @@ -146,6 +128,9 @@ namespace YooAsset /// public static uint ComputeFileCrc32AsUInt(string filePath) { + if (filePath == null) + throw new ArgumentNullException(nameof(filePath)); + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { return ComputeCrc32AsUInt(fs); @@ -157,6 +142,9 @@ namespace YooAsset /// public static string ComputeCrc32(Stream stream) { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + using (Crc32Algorithm hash = new Crc32Algorithm()) { byte[] hashBytes = hash.ComputeHash(stream); @@ -169,6 +157,9 @@ namespace YooAsset /// public static uint ComputeCrc32AsUInt(Stream stream) { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + using (Crc32Algorithm hash = new Crc32Algorithm()) { hash.ComputeHash(stream); @@ -181,6 +172,9 @@ namespace YooAsset /// public static string ComputeCrc32(byte[] buffer) { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer)); + using (Crc32Algorithm hash = new Crc32Algorithm()) { byte[] hashBytes = hash.ComputeHash(buffer); @@ -193,6 +187,9 @@ namespace YooAsset /// public static uint ComputeCrc32AsUInt(byte[] buffer) { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer)); + using (Crc32Algorithm hash = new Crc32Algorithm()) { hash.ComputeHash(buffer); @@ -201,4 +198,4 @@ namespace YooAsset } #endregion } -} \ No newline at end of file +} diff --git a/Assets/YooAsset/Runtime/Utility/Utilities/PathUtility.cs b/Assets/YooAsset/Runtime/Utility/Utilities/PathUtility.cs index e000c717..808687df 100644 --- a/Assets/YooAsset/Runtime/Utility/Utilities/PathUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/Utilities/PathUtility.cs @@ -1,4 +1,5 @@ using System; +using System.IO; namespace YooAsset { @@ -12,22 +13,38 @@ namespace YooAsset /// public static string NormalizePath(string path) { + if (path == null) + throw new ArgumentNullException(nameof(path)); return path.Replace('\\', '/'); } /// /// 移除路径里的后缀名 /// - public static string RemoveExtension(string str) + public static string RemoveExtension(string value) { - if (string.IsNullOrEmpty(str)) - return str; + if (string.IsNullOrEmpty(value)) + return value; - int index = str.LastIndexOf('.'); - if (index == -1) - return str; - else - return str.Remove(index); //"assets/config/test.unity3d" --> "assets/config/test" + // 定位最后一个路径分隔符,确保只移除文件名部分的扩展名。 + // 避免目录名含点时(如 "com.unity.render/shader")被错误截断。 + int sepIndex = Math.Max(value.LastIndexOf('/'), value.LastIndexOf('\\')); + int dotIndex = value.LastIndexOf('.'); + if (dotIndex == -1 || dotIndex < sepIndex) + return value; + return value.Remove(dotIndex); + } + + /// + /// 检查文件名是否包含非法字符 + /// + /// 待检查的文件名 + /// 包含非法字符返回 true,否则返回 false + public static bool ContainsInvalidFileNameChars(string fileName) + { + if (string.IsNullOrEmpty(fileName)) + return false; + return fileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0; } /// @@ -36,7 +53,7 @@ namespace YooAsset public static bool ContainsDoubleSlashes(string url) { if (url == null) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(url)); int protocolIndex = url.IndexOf("://"); string partToCheck = protocolIndex == -1 ? url : url.Substring(protocolIndex + 3); @@ -49,6 +66,10 @@ namespace YooAsset public static string Combine(string path1, string path2) { // 注意:某些静态服务器的规则可能不接受双斜杠路径 + if (path1 == null) + throw new ArgumentNullException(nameof(path1)); + if (path2 == null) + throw new ArgumentNullException(nameof(path2)); return StringUtility.Format("{0}/{1}", path1.TrimEnd('/'), path2.Trim('/')); } @@ -58,6 +79,12 @@ namespace YooAsset public static string Combine(string path1, string path2, string path3) { // 注意:某些静态服务器的规则可能不接受双斜杠路径 + if (path1 == null) + throw new ArgumentNullException(nameof(path1)); + if (path2 == null) + throw new ArgumentNullException(nameof(path2)); + if (path3 == null) + throw new ArgumentNullException(nameof(path3)); return StringUtility.Format("{0}/{1}/{2}", path1.TrimEnd('/'), path2.Trim('/'), path3.Trim('/')); } @@ -67,6 +94,14 @@ namespace YooAsset public static string Combine(string path1, string path2, string path3, string path4) { // 注意:某些静态服务器的规则可能不接受双斜杠路径 + if (path1 == null) + throw new ArgumentNullException(nameof(path1)); + if (path2 == null) + throw new ArgumentNullException(nameof(path2)); + if (path3 == null) + throw new ArgumentNullException(nameof(path3)); + if (path4 == null) + throw new ArgumentNullException(nameof(path4)); return StringUtility.Format("{0}/{1}/{2}/{3}", path1.TrimEnd('/'), path2.Trim('/'), path3.Trim('/'), path4.Trim('/')); } } diff --git a/Assets/YooAsset/Runtime/Utility/Utilities/StringUtility.cs b/Assets/YooAsset/Runtime/Utility/Utilities/StringUtility.cs index 7cd497aa..a5b5fe6f 100644 --- a/Assets/YooAsset/Runtime/Utility/Utilities/StringUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/Utilities/StringUtility.cs @@ -11,25 +11,49 @@ namespace YooAsset [ThreadStatic] private static StringBuilder t_cachedBuilder; - private static StringBuilder GetCachedBuilder() + [ThreadStatic] + private static bool t_inUse; + + // 重入保护:Format 的参数可能在 ToString() 中再次调用 Format, + // 若复用同一个 StringBuilder 会导致外层内容被清空而静默返回错误数据。 + // 当检测到嵌套调用时,退化为创建新实例以保证正确性。 + private static StringBuilder AcquireBuilder() { + if (t_inUse) + return new StringBuilder(256); + if (t_cachedBuilder == null) t_cachedBuilder = new StringBuilder(2048); + t_cachedBuilder.Length = 0; + t_inUse = true; return t_cachedBuilder; } + private static void ReleaseBuilder(StringBuilder sb) + { + if (sb == t_cachedBuilder) + t_inUse = false; + } + /// /// 无GC格式化字符串 /// public static string Format(string format, object arg0) { if (string.IsNullOrEmpty(format)) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(format)); - var sb = GetCachedBuilder(); - sb.AppendFormat(format, arg0); - return sb.ToString(); + var sb = AcquireBuilder(); + try + { + sb.AppendFormat(format, arg0); + return sb.ToString(); + } + finally + { + ReleaseBuilder(sb); + } } /// @@ -38,11 +62,18 @@ namespace YooAsset public static string Format(string format, object arg0, object arg1) { if (string.IsNullOrEmpty(format)) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(format)); - var sb = GetCachedBuilder(); - sb.AppendFormat(format, arg0, arg1); - return sb.ToString(); + var sb = AcquireBuilder(); + try + { + sb.AppendFormat(format, arg0, arg1); + return sb.ToString(); + } + finally + { + ReleaseBuilder(sb); + } } /// @@ -51,11 +82,18 @@ namespace YooAsset public static string Format(string format, object arg0, object arg1, object arg2) { if (string.IsNullOrEmpty(format)) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(format)); - var sb = GetCachedBuilder(); - sb.AppendFormat(format, arg0, arg1, arg2); - return sb.ToString(); + var sb = AcquireBuilder(); + try + { + sb.AppendFormat(format, arg0, arg1, arg2); + return sb.ToString(); + } + finally + { + ReleaseBuilder(sb); + } } /// @@ -64,14 +102,21 @@ namespace YooAsset public static string Format(string format, params object[] args) { if (string.IsNullOrEmpty(format)) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(format)); if (args == null) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(args)); - var sb = GetCachedBuilder(); - sb.AppendFormat(format, args); - return sb.ToString(); + var sb = AcquireBuilder(); + try + { + sb.AppendFormat(format, args); + return sb.ToString(); + } + finally + { + ReleaseBuilder(sb); + } } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/Utility/Utilities/TextUtility.cs b/Assets/YooAsset/Runtime/Utility/Utilities/TextUtility.cs index 41b874be..2d955d8c 100644 --- a/Assets/YooAsset/Runtime/Utility/Utilities/TextUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/Utilities/TextUtility.cs @@ -35,7 +35,7 @@ namespace YooAsset } // 检验首尾空白 - if (content != content.Trim()) + if (char.IsWhiteSpace(content[0]) || char.IsWhiteSpace(content[content.Length - 1])) { error = "Text content contains leading or trailing whitespace."; return false; diff --git a/Assets/YooAsset/Runtime/Utility/Utilities/TimeUtility.cs b/Assets/YooAsset/Runtime/Utility/Utilities/TimeUtility.cs index d3fcb63b..83504426 100644 --- a/Assets/YooAsset/Runtime/Utility/Utilities/TimeUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/Utilities/TimeUtility.cs @@ -7,7 +7,7 @@ namespace YooAsset internal static class TimeUtility { /// - /// 获取游戏启动以来经过的真实时间(单位:秒) + /// 游戏启动以来经过的真实时间(单位:秒) /// public static double RealtimeSinceStartup { diff --git a/Assets/YooAsset/Runtime/Utility/YooException.cs b/Assets/YooAsset/Runtime/Utility/YooException.cs index 1e3c469c..c250ef79 100644 --- a/Assets/YooAsset/Runtime/Utility/YooException.cs +++ b/Assets/YooAsset/Runtime/Utility/YooException.cs @@ -6,7 +6,7 @@ namespace YooAsset /// Base exception for all YooAsset custom exceptions. /// /// - /// Use catch (YooException) to handle all YooAsset-related exceptions. + /// Use catch (YooException) to handle all YooAsset-related exceptions. /// [Serializable] public class YooException : Exception @@ -26,15 +26,15 @@ namespace YooAsset /// /// /// Thrown when an unexpected internal error occurs, typically indicating a code defect that needs to be fixed. - /// The message is automatically prefixed with "An internal error occurred: " for identification. + /// The message is automatically prefixed with "An internal error occurred: " for identification. /// [Serializable] public class YooInternalException : YooException { - public YooInternalException() : base("An internal error occurred. This indicates a bug in the code.") { } - public YooInternalException(string message) : base($"An internal error occurred: {message}") { } - public YooInternalException(Exception inner) : base("An internal error occurred. This indicates a bug in the code.", inner) { } - public YooInternalException(string message, Exception inner) : base($"An internal error occurred: {message}", inner) { } + public YooInternalException() : base("Internal error occurred. This indicates a bug in the code.") { } + public YooInternalException(string message) : base($"Internal error occurred: {message}") { } + public YooInternalException(Exception inner) : base("Internal error occurred. This indicates a bug in the code.", inner) { } + public YooInternalException(string message, Exception inner) : base($"Internal error occurred: {message}", inner) { } } /// diff --git a/Assets/YooAsset/Runtime/Utility/YooLogger.cs b/Assets/YooAsset/Runtime/Utility/YooLogger.cs index 2d513365..dbe4cc48 100644 --- a/Assets/YooAsset/Runtime/Utility/YooLogger.cs +++ b/Assets/YooAsset/Runtime/Utility/YooLogger.cs @@ -15,17 +15,17 @@ namespace YooAsset /// /// 输出警告日志 /// - void Warning(string message); + void LogWarning(string message); /// /// 输出错误日志 /// - void Error(string message); + void LogError(string message); /// /// 输出异常日志 /// - void Exception(System.Exception exception); + void LogException(System.Exception exception); } /// @@ -34,9 +34,9 @@ namespace YooAsset internal static class YooLogger { /// - /// 获取或设置自定义日志处理器实例 + /// 自定义日志处理器实例 /// - public static ILogger Current = null; + public static ILogger Current { get; set; } /// /// 输出调试日志(仅在 DEBUG 模式下生效) @@ -57,11 +57,11 @@ namespace YooAsset /// /// 输出警告日志 /// - public static void Warning(string message) + public static void LogWarning(string message) { if (Current != null) { - Current.Warning(message); + Current.LogWarning(message); } else { @@ -72,11 +72,11 @@ namespace YooAsset /// /// 输出错误日志 /// - public static void Error(string message) + public static void LogError(string message) { if (Current != null) { - Current.Error(message); + Current.LogError(message); } else { @@ -87,11 +87,11 @@ namespace YooAsset /// /// 输出异常日志 /// - public static void Exception(System.Exception exception) + public static void LogException(System.Exception exception) { if (Current != null) { - Current.Exception(exception); + Current.LogException(exception); } else { diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs index 12b931c5..a5a590cb 100644 --- a/Assets/YooAsset/Runtime/YooAssets.cs +++ b/Assets/YooAsset/Runtime/YooAssets.cs @@ -16,50 +16,57 @@ namespace YooAsset [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void OnRuntimeInitialize() { - _isInitialized = false; - _packages.Clear(); + s_isInitialized = false; + s_driver = null; + s_packages.Clear(); } #endif - private static bool _isInitialized; - private static GameObject _driver; - private static readonly Dictionary _packages = new Dictionary(10); + private static bool s_isInitialized; + private static GameObject s_driver; + private static readonly Dictionary s_packages = new Dictionary(10); /// /// 是否已经初始化 /// public static bool IsInitialized { - get { return _isInitialized; } + get { return s_isInitialized; } + } + + /// + /// 初始化资源系统 + /// + public static void Initialize() + { + Initialize(null); } /// /// 初始化资源系统 /// /// 自定义日志处理 - public static void Initialize(ILogger logger = null) + public static void Initialize(ILogger logger) { - if (_isInitialized) - { - YooLogger.Warning("YooAssets is already initialized."); - return; - } + if (s_isInitialized) + throw new System.InvalidOperationException("YooAssets is already initialized."); YooLogger.Current = logger; // 创建驱动器 - _isInitialized = true; - _driver = new UnityEngine.GameObject($"[{nameof(YooAssets)}]"); - _driver.AddComponent(); - UnityEngine.Object.DontDestroyOnLoad(_driver); + s_driver = new UnityEngine.GameObject($"[{nameof(YooAssets)}]"); + s_driver.AddComponent(); + UnityEngine.Object.DontDestroyOnLoad(s_driver); #if DEBUG // 添加远程调试脚本 - _driver.AddComponent(); + s_driver.AddComponent(); #endif // 初始化异步操作系统 AsyncOperationSystem.Initialize(); + + s_isInitialized = true; } /// @@ -67,12 +74,16 @@ namespace YooAsset /// public static void Destroy() { - if (_isInitialized) + if (s_isInitialized) { - _isInitialized = false; + s_isInitialized = false; - if (_driver != null) - GameObject.Destroy(_driver); + // 销毁驱动器 + if (s_driver != null) + { + GameObject.Destroy(s_driver); + s_driver = null; + } // 销毁异步操作系统 AsyncOperationSystem.Shutdown(); @@ -81,7 +92,11 @@ namespace YooAsset AssetBundle.UnloadAllAssetBundles(true); // 清空资源包裹列表 - _packages.Clear(); + foreach (var kv in s_packages) + { + kv.Value.InternalDestroy(); + } + s_packages.Clear(); } } @@ -90,25 +105,36 @@ namespace YooAsset /// internal static void Update() { - if (_isInitialized) + if (s_isInitialized) { AsyncOperationSystem.Update(); } } + /// + /// 创建资源包裹 + /// + /// 包裹名称 + /// 新创建的资源包裹实例 + public static ResourcePackage CreatePackage(string packageName) + { + return CreatePackage(packageName, 0); + } + /// /// 创建资源包裹 /// /// 包裹名称 /// 包裹优先级(值越大越优先更新) - public static ResourcePackage CreatePackage(string packageName, uint packagePriority = 0) + /// 新创建的资源包裹实例 + public static ResourcePackage CreatePackage(string packageName, uint packagePriority) { CheckInitialized(packageName); if (ContainsPackage(packageName)) throw new System.InvalidOperationException($"Resource package '{packageName}' already exists."); ResourcePackage package = new ResourcePackage(packageName); - _packages.Add(packageName, package); + s_packages.Add(packageName, package); // 注册包裹调度器 AsyncOperationSystem.CreatePackageScheduler(packageName, packagePriority); @@ -120,12 +146,13 @@ namespace YooAsset /// 获取资源包裹 /// /// 包裹名称 + /// 指定名称的资源包裹实例 public static ResourcePackage GetPackage(string packageName) { CheckInitialized(packageName); var package = GetPackageInternal(packageName); if (package == null) - YooLogger.Error($"Cannot find resource package: {packageName}"); + throw new System.InvalidOperationException($"Could not find resource package: '{packageName}'."); return package; } @@ -133,8 +160,8 @@ namespace YooAsset /// 尝试获取资源包裹 /// /// 包裹名称 - /// 获取到的资源包裹,如果不存在则为null - /// 如果资源包裹存在返回true,否则返回false + /// 获取到的资源包裹,如果不存在则为null。 + /// 如果资源包裹存在返回true,否则返回false。 public static bool TryGetPackage(string packageName, out ResourcePackage package) { CheckInitialized(packageName); @@ -145,41 +172,37 @@ namespace YooAsset /// /// 获取所有资源包裹 /// + /// 当前已注册的所有资源包裹的只读列表 public static IReadOnlyList GetPackages() { - return _packages.Values.ToList(); + CheckInitialized(); + return s_packages.Values.ToList().AsReadOnly(); } /// /// 移除资源包裹 /// /// 包裹名称 - public static bool RemovePackage(string packageName) + public static void RemovePackage(string packageName) { CheckInitialized(packageName); ResourcePackage package = GetPackageInternal(packageName); if (package == null) - { - YooLogger.Error($"Cannot find resource package: {packageName}"); - return false; - } + throw new System.InvalidOperationException($"Could not find resource package: '{packageName}'."); if (package.InitializeStatus != EOperationStatus.None) - { - YooLogger.Error($"Resource package '{packageName}' has not been destroyed. Call {nameof(ResourcePackage.DestroyPackageAsync)} before removing it."); - return false; - } + throw new System.InvalidOperationException($"Resource package '{packageName}' has not been destroyed. Call {nameof(ResourcePackage.DestroyPackageAsync)} before removing it."); // 先销毁调度器,再移除包裹 AsyncOperationSystem.DestroyPackageScheduler(packageName); - - return _packages.Remove(packageName); + s_packages.Remove(packageName); } /// /// 检测资源包裹是否存在 /// /// 包裹名称 + /// 如果资源包裹存在返回true,否则返回false。 public static bool ContainsPackage(string packageName) { CheckInitialized(packageName); @@ -188,25 +211,32 @@ namespace YooAsset } /// - /// 设置异步系统参数,每帧执行消耗的最大时间切片 + /// 设置异步系统参数,每帧执行消耗的最大时间切片。 /// - /// 最大时间切片(单位:毫秒) + /// 最大时间切片(单位:毫秒),不能为负数。 public static void SetAsyncOperationMaxTimeSlice(long milliseconds) { + if (milliseconds < 0) + throw new System.ArgumentOutOfRangeException(nameof(milliseconds), milliseconds, "Max time slice cannot be negative."); AsyncOperationSystem.MaxTimeSlice = milliseconds; } private static ResourcePackage GetPackageInternal(string packageName) { - _packages.TryGetValue(packageName, out var package); + s_packages.TryGetValue(packageName, out var package); return package; } #region 调试方法 + private static void CheckInitialized() + { + if (s_isInitialized == false) + throw new System.InvalidOperationException($"YooAssets is not initialized. Please call {nameof(YooAssets.Initialize)} first."); + } + private static void CheckInitialized(string packageName) { - if (_isInitialized == false) - throw new System.InvalidOperationException($"YooAssets not initialized. Please call {nameof(YooAssets.Initialize)} first."); + CheckInitialized(); if (string.IsNullOrEmpty(packageName)) throw new System.ArgumentException("Package name cannot be null or empty.", nameof(packageName)); @@ -214,10 +244,14 @@ namespace YooAsset #endregion #region 调试信息 + /// + /// 收集所有资源包裹的诊断数据 + /// + /// 包含所有资源包裹诊断数据的报告 internal static DiagnosticReport GetDiagnosticReport() { DiagnosticReport report = DiagnosticReport.Create(); - foreach (var kv in _packages) + foreach (var kv in s_packages) { var packageData = kv.Value.GetDiagnosticData(); report.PackageDataList.Add(packageData); diff --git a/Assets/YooAsset/Runtime/YooAssetsDriver.cs b/Assets/YooAsset/Runtime/YooAssetsDriver.cs index e610cf4b..f201a69f 100644 --- a/Assets/YooAsset/Runtime/YooAssetsDriver.cs +++ b/Assets/YooAsset/Runtime/YooAssetsDriver.cs @@ -3,6 +3,9 @@ using UnityEngine; namespace YooAsset { + /// + /// 资源系统的驱动器 + /// internal class YooAssetsDriver : MonoBehaviour { #if UNITY_EDITOR @@ -24,7 +27,7 @@ namespace YooAsset #if UNITY_EDITOR void OnApplicationQuit() { - //注意:在编辑器下确保播放被停止时IO类操作被终止。 + // 注意:在编辑器下确保播放被停止时IO类操作被终止。 YooAssets.Destroy(); } #endif @@ -35,7 +38,7 @@ namespace YooAsset if (s_latestUpdateFrame > 0) { if (s_latestUpdateFrame == Time.frameCount) - YooLogger.Warning($"Duplicate {nameof(YooAssetsDriver)} detected in the scene. Ensure there is always exactly one driver."); + YooLogger.LogWarning($"Duplicate {nameof(YooAssetsDriver)} detected in the scene. Ensure there is always exactly one driver."); } s_latestUpdateFrame = Time.frameCount; diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs index b37de8c9..633c3d7a 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs @@ -78,8 +78,8 @@ namespace YooAsset.Editor foreach (var packageBundle in manifest.BundleList) { fileCount++; - string sourcePath = $"{outputDirectory}/{packageBundle.FileName}"; - string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsRoot()}/{_packageName}/{packageBundle.FileName}"; + string sourcePath = $"{outputDirectory}/{packageBundle.GetFileName()}"; + string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsRoot()}/{_packageName}/{packageBundle.GetFileName()}"; EditorTools.CopyFile(sourcePath, destPath, true); } diff --git a/Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs b/Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs index 4f0c010b..5cbf5825 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs @@ -168,7 +168,7 @@ public struct ImportFileInfo /// /// 资源包GUID /// - public string BundleGUID; + public string BundleGuid; } #endregion @@ -444,11 +444,10 @@ public static class CompatibleResourcePackage ImportBundleInfo[] bundleInfos = new ImportBundleInfo[fileInfos.Length]; for (int i = 0; i < fileInfos.Length; i++) { - ImportBundleInfo bundleInfo = new ImportBundleInfo(); - bundleInfo.FilePath = fileInfos[i].FilePath; - bundleInfo.BundleName = fileInfos[i].BundleName; - bundleInfo.BundleGUID = fileInfos[i].BundleGUID; - bundleInfos[i] = bundleInfo; + bundleInfos[i] = new ImportBundleInfo( + filePath: fileInfos[i].FilePath, + bundleName: fileInfos[i].BundleName, + bundleGuid: fileInfos[i].BundleGuid); } var options = new BundleImporterOptions(bundleInfos, importerMaxNumber, failedTryAgain); diff --git a/Assets/YooAsset/Samples~/Extension Sample/Runtime/GameObjectAssetReference.cs b/Assets/YooAsset/Samples~/Extension Sample/Runtime/GameObjectAssetReference.cs index 60fa0e9b..82dc97ec 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Runtime/GameObjectAssetReference.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Runtime/GameObjectAssetReference.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using UnityEngine; using YooAsset; #if UNITY_EDITOR @@ -50,7 +50,7 @@ public class GameObjectAssetReference : MonoBehaviour public void Start() { var package = YooAssets.GetPackage("DefaultPackage"); - var assetInfo = package.GetAssetInfoByGUID(AssetGUID); + var assetInfo = package.GetAssetInfoByGuid(AssetGUID); _handle = package.LoadAssetAsync(assetInfo); _handle.Completed += Handle_Completed; } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/AlipayFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/AlipayFileSystem.cs index 01bf203f..67bea8ed 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/AlipayFileSystem.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/AlipayFileSystem.cs @@ -135,22 +135,22 @@ internal class AlipayFileSystem : IFileSystem } public virtual FSDownloadBundleOperation DownloadBundleAsync(PackageBundle bundle, DownloadFileOptions options) { - string mainURL = RemoteService.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteService.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var operation = new APFSDownloadBundleOperation(this, bundle, options); return operation; } public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) { - if (bundle.BundleType == (int)EBuildBundleType.AssetBundle) + if (bundle.GetBundleType() == (int)EBuildBundleType.AssetBundle) { var operation = new APFSLoadBundleOperation(this, bundle); return operation; } else { - string error = $"{nameof(AlipayFileSystem)} not support load bundle type : {bundle.BundleType}"; + string error = $"{nameof(AlipayFileSystem)} not support load bundle type : {bundle.GetBundleType()}"; var operation = new FSLoadBundleCompleteOperation(error); return operation; } @@ -172,7 +172,7 @@ internal class AlipayFileSystem : IFileSystem } else { - YooLogger.Warning($"Invalid parameter : {paramName}"); + YooLogger.LogWarning($"Invalid parameter : {paramName}"); } } public virtual void OnCreate(string packageName, string rootDirectory) @@ -188,7 +188,7 @@ internal class AlipayFileSystem : IFileSystem // 注意:CDN服务未启用的情况下,使用WEB服务器 if (RemoteService == null) { - string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.Settings.YooFolderName, packageName); + string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.GetSettings().YooFolderName, packageName); RemoteService = new WebRemoteService(webRoot); } @@ -268,10 +268,10 @@ internal class AlipayFileSystem : IFileSystem } private string GetCacheFileLoadPath(PackageBundle bundle) { - if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false) + if (_cacheFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) { - filePath = PathUtility.Combine(_aliCacheRoot, bundle.FileName); - _cacheFilePathMapping.Add(bundle.BundleGUID, filePath); + filePath = PathUtility.Combine(_aliCacheRoot, bundle.GetFileName()); + _cacheFilePathMapping.Add(bundle.BundleGuid, filePath); } return filePath; } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSDownloadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSDownloadBundleOperation.cs index b52680cb..5d979043 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSDownloadBundleOperation.cs @@ -69,13 +69,13 @@ internal class APFSDownloadBundleOperation : FSDownloadBundleOperation if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_webCacheRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_webCacheRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_webCacheRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSLoadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSLoadBundleOperation.cs index e08be5f3..2bc7de89 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/APFSLoadBundleOperation.cs @@ -33,8 +33,8 @@ internal class APFSLoadBundleOperation : FSLoadBundleOperation { if (_loadWebAssetBundleOp == null) { - string mainURL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.FileName); - string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.FileName); + string mainURL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.GetFileName()); + string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.GetFileName()); DownloadFileOptions options = new DownloadFileOptions(int.MaxValue); options.SetURL(mainURL, fallbackURL); diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/internal/LoadAlipayAssetBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/internal/LoadAlipayAssetBundleOperation.cs index a33be0c2..dfe70b54 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/internal/LoadAlipayAssetBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/AlipayFileSystem/Operation/internal/LoadAlipayAssetBundleOperation.cs @@ -71,13 +71,13 @@ namespace YooAsset if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_unityAssetBundleRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs index 16a14940..1e1bb72d 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs @@ -1,4 +1,4 @@ -#if UNITY_ANDROID && GOOGLE_PLAY +#if UNITY_ANDROID && GOOGLE_PLAY using System.Collections.Generic; using UnityEngine; using YooAsset; @@ -26,14 +26,14 @@ internal class GooglePlayFileSystem : DefaultBuildinFileSystem public override FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) { - if (bundle.BundleType == (int)EBuildBundleType.AssetBundle) + if (bundle.GetBundleType() == (int)EBuildBundleType.AssetBundle) { var operation = new GPFSLoadAssetBundleOperation(this, bundle); return operation; } else { - string error = $"{nameof(GooglePlayFileSystem)} not support load bundle type : {bundle.BundleType}"; + string error = $"{nameof(GooglePlayFileSystem)} not support load bundle type : {bundle.GetBundleType()}"; var operation = new FSLoadBundleCompleteOperation(error); return operation; } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/Operation/GPFSLoadAssetBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/Operation/GPFSLoadAssetBundleOperation.cs index 1652cf63..d5ff96c3 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/Operation/GPFSLoadAssetBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/Operation/GPFSLoadAssetBundleOperation.cs @@ -42,11 +42,11 @@ internal class GPFSLoadAssetBundleOperation : FSLoadBundleOperation { _steps = ESteps.Done; SetError($"The {nameof(GooglePlayFileSystem)} not support bundle encrypted !"); - YooLogger.Error(Error); + YooLogger.LogError(Error); return; } - _bundleRequest = PlayAssetDelivery.RetrieveAssetBundleAsync(_bundle.FileName); + _bundleRequest = PlayAssetDelivery.RetrieveAssetBundleAsync(_bundle.GetFileName()); _steps = ESteps.CheckResult; } @@ -59,7 +59,7 @@ internal class GPFSLoadAssetBundleOperation : FSLoadBundleOperation { _steps = ESteps.Done; SetError($"Failed to load delivery asset bundle file : {_bundle.BundleName} Error : {_bundleRequest.Error}"); - YooLogger.Error(Error); + YooLogger.LogError(Error); } else { diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadBundleOperation.cs index ffa9ae6c..1602d6e8 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadBundleOperation.cs @@ -69,13 +69,13 @@ internal class TPFSDownloadBundleOperation : FSDownloadBundleOperation if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_webCacheRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_webCacheRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_webCacheRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs index c96ee3dc..ec61613d 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs @@ -33,8 +33,8 @@ internal class TPFSLoadBundleOperation : FSLoadBundleOperation { if (_loadWebAssetBundleOp == null) { - string mainURL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.FileName); - string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.FileName); + string mainURL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.GetFileName()); + string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.GetFileName()); DownloadFileOptions options = new DownloadFileOptions(int.MaxValue); options.SetURL(mainURL, fallbackURL); diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs index 834a2456..bec0178a 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs @@ -70,13 +70,13 @@ namespace YooAsset if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_unityAssetBundleRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs index 54c5c09e..2b0395ff 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs @@ -136,22 +136,22 @@ internal class TaptapFileSystem : IFileSystem } public virtual FSDownloadBundleOperation DownloadBundleAsync(PackageBundle bundle, DownloadFileOptions options) { - string mainURL = RemoteService.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteService.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var operation = new TPFSDownloadBundleOperation(this, bundle, options); return operation; } public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) { - if (bundle.BundleType == (int)EBuildBundleType.AssetBundle) + if (bundle.GetBundleType() == (int)EBuildBundleType.AssetBundle) { var operation = new TPFSLoadBundleOperation(this, bundle); return operation; } else { - string error = $"{nameof(TaptapFileSystem)} not support load bundle type : {bundle.BundleType}"; + string error = $"{nameof(TaptapFileSystem)} not support load bundle type : {bundle.GetBundleType()}"; var operation = new FSLoadBundleCompleteOperation(error); return operation; } @@ -173,7 +173,7 @@ internal class TaptapFileSystem : IFileSystem } else { - YooLogger.Warning($"Invalid parameter : {paramName}"); + YooLogger.LogWarning($"Invalid parameter : {paramName}"); } } public virtual void OnCreate(string packageName, string rootDirectory) @@ -189,7 +189,7 @@ internal class TaptapFileSystem : IFileSystem // 注意:CDN服务未启用的情况下,使用WEB服务器 if (RemoteService == null) { - string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.Settings.YooFolderName, packageName); + string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.GetSettings().YooFolderName, packageName); RemoteService = new WebRemoteService(webRoot); } @@ -269,10 +269,10 @@ internal class TaptapFileSystem : IFileSystem } private string GetCacheFileLoadPath(PackageBundle bundle) { - if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false) + if (_cacheFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) { - filePath = PathUtility.Combine(_tapCacheRoot, bundle.FileName); - _cacheFilePathMapping.Add(bundle.BundleGUID, filePath); + filePath = PathUtility.Combine(_tapCacheRoot, bundle.GetFileName()); + _cacheFilePathMapping.Add(bundle.BundleGuid, filePath); } return filePath; } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSDownloadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSDownloadBundleOperation.cs index 07f5c155..86ab17e0 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSDownloadBundleOperation.cs @@ -69,13 +69,13 @@ internal class TTFSDownloadBundleOperation : FSDownloadBundleOperation if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_webCacheRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_webCacheRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_webCacheRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSLoadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSLoadBundleOperation.cs index 58a01d4a..843f184a 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/TTFSLoadBundleOperation.cs @@ -33,8 +33,8 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation { if (_loadWebAssetBundleOp == null) { - string mainRUL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.FileName); - string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.FileName); + string mainRUL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.GetFileName()); + string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.GetFileName()); DownloadFileOptions options = new DownloadFileOptions(int.MaxValue); options.SetURL(mainRUL, fallbackURL); diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/internal/LoadTiktokAssetBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/internal/LoadTiktokAssetBundleOperation.cs index ee554b9c..b0ddb57b 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/internal/LoadTiktokAssetBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/Operation/internal/LoadTiktokAssetBundleOperation.cs @@ -70,13 +70,13 @@ namespace YooAsset if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_unityAssetBundleRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/TiktokFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/TiktokFileSystem.cs index 4f16d14d..e2f69eec 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/TiktokFileSystem.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TiktokFileSystem/TiktokFileSystem.cs @@ -135,22 +135,22 @@ internal class TiktokFileSystem : IFileSystem } public virtual FSDownloadBundleOperation DownloadBundleAsync(PackageBundle bundle, DownloadFileOptions options) { - string mainURL = RemoteService.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteService.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var operation = new TTFSDownloadBundleOperation(this, bundle, options); return operation; } public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) { - if (bundle.BundleType == (int)EBuildBundleType.AssetBundle) + if (bundle.GetBundleType() == (int)EBuildBundleType.AssetBundle) { var operation = new TTFSLoadBundleOperation(this, bundle); return operation; } else { - string error = $"{nameof(TiktokFileSystem)} not support load bundle type : {bundle.BundleType}"; + string error = $"{nameof(TiktokFileSystem)} not support load bundle type : {bundle.GetBundleType()}"; var operation = new FSLoadBundleCompleteOperation(error); return operation; } @@ -172,7 +172,7 @@ internal class TiktokFileSystem : IFileSystem } else { - YooLogger.Warning($"Invalid parameter : {paramName}"); + YooLogger.LogWarning($"Invalid parameter : {paramName}"); } } public virtual void OnCreate(string packageName, string packageRoot) @@ -188,7 +188,7 @@ internal class TiktokFileSystem : IFileSystem // 注意:CDN服务未启用的情况下,使用WEB服务器 if (RemoteService == null) { - string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.Settings.YooFolderName, packageName); + string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.GetSettings().YooFolderName, packageName); RemoteService = new WebRemoteService(webRoot); } @@ -258,15 +258,15 @@ internal class TiktokFileSystem : IFileSystem } public bool CheckCacheFileExist(PackageBundle bundle) { - string url = RemoteService.GetRemoteMainURL(bundle.FileName); + string url = RemoteService.GetRemoteMainURL(bundle.GetFileName()); return _fileSystemMgr.IsUrlCached(url); } private string GetCacheFileLoadPath(PackageBundle bundle) { - if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false) + if (_cacheFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) { - filePath = _fileSystemMgr.GetLocalCachedPathForUrl(bundle.FileName); - _cacheFilePathMapping.Add(bundle.BundleGUID, filePath); + filePath = _fileSystemMgr.GetLocalCachedPathForUrl(bundle.GetFileName()); + _cacheFilePathMapping.Add(bundle.BundleGuid, filePath); } return filePath; } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSClearUnusedBundleFilesAsync.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSClearUnusedBundleFilesAsync.cs index 5c640303..6a4b5aaa 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSClearUnusedBundleFilesAsync.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSClearUnusedBundleFilesAsync.cs @@ -61,8 +61,8 @@ internal class WXFSClearUnusedBundleFilesAsync : FSClearCacheFilesOperation // 注意:适配不同的文件命名方式! string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileStat.path); - string bundleGUID = fileNameWithoutExtension.Split('_').Last(); - if (_manifest.TryGetPackageBundleByBundleGUID(bundleGUID, out PackageBundle value) == false) + string bundleGuid = fileNameWithoutExtension.Split('_').Last(); + if (_manifest.TryGetPackageBundleByBundleGuid(bundleGuid, out PackageBundle value) == false) { string filePath = _fileSystem.FileRoot + fileStat.path; if (_unusedCacheFiles.Contains(filePath) == false) diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSDownloadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSDownloadBundleOperation.cs index 57ea6407..6b223b7c 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSDownloadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSDownloadBundleOperation.cs @@ -71,13 +71,13 @@ internal class WXFSDownloadBundleOperation : FSDownloadBundleOperation if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_webCacheRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_webCacheRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_webCacheRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSLoadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSLoadBundleOperation.cs index 13738771..2de7d195 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/WXFSLoadBundleOperation.cs @@ -33,8 +33,8 @@ internal class WXFSLoadBundleOperation : FSLoadBundleOperation { if (_loadWebAssetBundleOp == null) { - string mainURL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.FileName); - string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.FileName); + string mainURL = _fileSystem.RemoteService.GetRemoteMainURL(_bundle.GetFileName()); + string fallbackURL = _fileSystem.RemoteService.GetRemoteFallbackURL(_bundle.GetFileName()); DownloadFileOptions options = new DownloadFileOptions(int.MaxValue); options.SetURL(mainURL, fallbackURL); diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/internal/LoadWechatAssetBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/internal/LoadWechatAssetBundleOperation.cs index 4d9a06fc..1d5b3676 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/internal/LoadWechatAssetBundleOperation.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/Operation/internal/LoadWechatAssetBundleOperation.cs @@ -70,13 +70,13 @@ namespace YooAsset if (_failedTryAgain > 0) { _steps = ESteps.TryAgain; - YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); + YooLogger.LogWarning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !"); } else { _steps = ESteps.Done; SetError(_unityAssetBundleRequestOp.Error); - YooLogger.Error(Error); + YooLogger.LogError(Error); } } } diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/WechatFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/WechatFileSystem.cs index 81ead3db..c033b50b 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/WechatFileSystem.cs +++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/WechatFileSystem/WechatFileSystem.cs @@ -149,22 +149,22 @@ internal class WechatFileSystem : IFileSystem } public virtual FSDownloadBundleOperation DownloadBundleAsync(PackageBundle bundle, DownloadFileOptions options) { - string mainURL = RemoteService.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteService.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteService.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var operation = new WXFSDownloadBundleOperation(this, bundle, options); return operation; } public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) { - if (bundle.BundleType == (int)EBuildBundleType.AssetBundle) + if (bundle.GetBundleType() == (int)EBuildBundleType.AssetBundle) { var operation = new WXFSLoadBundleOperation(this, bundle); return operation; } else { - string error = $"{nameof(WechatFileSystem)} not support load bundle type : {bundle.BundleType}"; + string error = $"{nameof(WechatFileSystem)} not support load bundle type : {bundle.GetBundleType()}"; var operation = new FSLoadBundleCompleteOperation(error); return operation; } @@ -186,7 +186,7 @@ internal class WechatFileSystem : IFileSystem } else { - YooLogger.Warning($"Invalid parameter : {paramName}"); + YooLogger.LogWarning($"Invalid parameter : {paramName}"); } } public virtual void OnCreate(string packageName, string packageRoot) @@ -202,7 +202,7 @@ internal class WechatFileSystem : IFileSystem // 注意:CDN服务未启用的情况下,使用WEB服务器 if (RemoteService == null) { - string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.Settings.YooFolderName, packageName); + string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetConfiguration.GetSettings().YooFolderName, packageName); RemoteService = new WebRemoteService(webRoot); } @@ -282,10 +282,10 @@ internal class WechatFileSystem : IFileSystem } public string GetCacheFileLoadPath(PackageBundle bundle) { - if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false) + if (_cacheFilePathMapping.TryGetValue(bundle.BundleGuid, out string filePath) == false) { - filePath = PathUtility.Combine(_wxCacheRoot, bundle.FileName); - _cacheFilePathMapping.Add(bundle.BundleGUID, filePath); + filePath = PathUtility.Combine(_wxCacheRoot, bundle.GetFileName()); + _cacheFilePathMapping.Add(bundle.BundleGuid, filePath); } return filePath; } diff --git a/Assets/YooAsset/Samples~/Test Sample/Runtime/CryptoSample/TestFileEncryption.cs b/Assets/YooAsset/Samples~/Test Sample/Runtime/CryptoSample/TestFileEncryption.cs index 317b7c75..4b10b947 100644 --- a/Assets/YooAsset/Samples~/Test Sample/Runtime/CryptoSample/TestFileEncryption.cs +++ b/Assets/YooAsset/Samples~/Test Sample/Runtime/CryptoSample/TestFileEncryption.cs @@ -35,16 +35,11 @@ public class TestFileStreamEncryption : IBundleEncryptor fileData[i] ^= BundleStream.KEY; } - BundleEncryptResult result = new BundleEncryptResult(); - result.Encrypted = true; - result.EncryptedFileData = fileData; - return result; + return new BundleEncryptResult(true, fileData); } else { - BundleEncryptResult result = new BundleEncryptResult(); - result.Encrypted = false; - return result; + return new BundleEncryptResult(false, null); } } } @@ -60,16 +55,11 @@ public class TestFileOffsetEncryption : IBundleEncryptor var encryptedData = new byte[fileData.Length + offset]; Buffer.BlockCopy(fileData, 0, encryptedData, offset, fileData.Length); - BundleEncryptResult result = new BundleEncryptResult(); - result.Encrypted = true; - result.EncryptedFileData = encryptedData; - return result; + return new BundleEncryptResult(true, encryptedData); } else { - BundleEncryptResult result = new BundleEncryptResult(); - result.Encrypted = false; - return result; + return new BundleEncryptResult(false, null); } } } diff --git a/Assets/YooAsset/Samples~/Test Sample/Runtime/T2_TestBuldinFileSystem/TestBundleEncryption.cs b/Assets/YooAsset/Samples~/Test Sample/Runtime/T2_TestBuldinFileSystem/TestBundleEncryption.cs index 6a88b743..1a11d116 100644 --- a/Assets/YooAsset/Samples~/Test Sample/Runtime/T2_TestBuldinFileSystem/TestBundleEncryption.cs +++ b/Assets/YooAsset/Samples~/Test Sample/Runtime/T2_TestBuldinFileSystem/TestBundleEncryption.cs @@ -68,8 +68,8 @@ UnpackFileSystem::DownloadBundleAsync() if (string.IsNullOrEmpty(options.ImportFilePath)) { //RemoteService返回内置文件路径 - string mainURL = RemoteServices.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteServices.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var downloader = new DownloadPackageBundleOperation(bundle, options); return downloader; diff --git a/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleDownloader.cs b/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleDownloader.cs index e371a528..beffce3a 100644 --- a/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleDownloader.cs +++ b/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleDownloader.cs @@ -37,8 +37,8 @@ CacheFileSystem::DownloadBundleAsync() if (string.IsNullOrEmpty(options.ImportFilePath)) { //RemoteService返回CDN文件路径 - string mainURL = RemoteServices.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteServices.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var downloader = new DownloadPackageBundleOperation(bundle, options); return downloader; diff --git a/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleImporter.cs b/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleImporter.cs index 1ec2de22..311cb78d 100644 --- a/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleImporter.cs +++ b/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundleImporter.cs @@ -20,13 +20,15 @@ public class TestBundleImporter DirectoryInfo packageDir = new DirectoryInfo(packageRoot); string fileRoot = $"{packageDir.Parent.FullName}/OutputCache"; - ImportBundleInfo fileInfoA = new ImportBundleInfo(); - fileInfoA.FilePath = $"{fileRoot}/assets_samples_test_sample_testres3_import_prefab_importa.bundle.encrypt"; - fileInfoA.BundleName = "assets_samples_test_sample_testres3_import_prefab_importa.bundle"; + var fileInfoA = new ImportBundleInfo( + filePath: $"{fileRoot}/assets_samples_test_sample_testres3_import_prefab_importa.bundle.encrypt", + bundleName: "assets_samples_test_sample_testres3_import_prefab_importa.bundle", + bundleGuid: null); - ImportBundleInfo fileInfoB = new ImportBundleInfo(); - fileInfoB.FilePath = $"{fileRoot}/assets_samples_test_sample_testres3_import_prefab_importb.bundle.encrypt"; - fileInfoB.BundleName = "assets_samples_test_sample_testres3_import_prefab_importb.bundle"; + var fileInfoB = new ImportBundleInfo( + filePath: $"{fileRoot}/assets_samples_test_sample_testres3_import_prefab_importb.bundle.encrypt", + bundleName: "assets_samples_test_sample_testres3_import_prefab_importb.bundle", + bundleGuid: null); ImportBundleInfo[] importInfos = { fileInfoA, fileInfoB }; var options = new BundleImporterOptions(importInfos, 10, 1); diff --git a/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundlePlaying.cs b/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundlePlaying.cs index cdd01428..6637c3f7 100644 --- a/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundlePlaying.cs +++ b/Assets/YooAsset/Samples~/Test Sample/Runtime/T3_TestCacheFileSystem/TestBundlePlaying.cs @@ -74,8 +74,8 @@ CacheFileSystem::DownloadBundleAsync() if (string.IsNullOrEmpty(options.ImportFilePath)) { //RemoteService返回CDN文件路径 - string mainURL = RemoteServices.GetRemoteMainURL(bundle.FileName); - string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName); + string mainURL = RemoteServices.GetRemoteMainURL(bundle.GetFileName()); + string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.GetFileName()); options.SetURL(mainURL, fallbackURL); var downloader = new DownloadPackageBundleOperation(bundle, options); return downloader; diff --git a/Assets/YooAsset/Samples~/Test Sample/Runtime/TestLoadAsset/TestDestroyPackage.cs b/Assets/YooAsset/Samples~/Test Sample/Runtime/TestLoadAsset/TestDestroyPackage.cs index bccd6612..0057139b 100644 --- a/Assets/YooAsset/Samples~/Test Sample/Runtime/TestLoadAsset/TestDestroyPackage.cs +++ b/Assets/YooAsset/Samples~/Test Sample/Runtime/TestLoadAsset/TestDestroyPackage.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Text; using System.Collections; @@ -22,8 +22,7 @@ public class TestDestroyPackage Debug.LogError(destroyOp.Error); Assert.AreEqual(EOperationStatus.Succeeded, destroyOp.Status); - bool result = YooAssets.RemovePackage(TestDefine.AssetBundlePackageName); - Assert.IsTrue(result); + YooAssets.RemovePackage(TestDefine.AssetBundlePackageName); } // 销毁旧资源包 RAW_BUNDLE @@ -36,8 +35,7 @@ public class TestDestroyPackage Debug.LogError(destroyOp.Error); Assert.AreEqual(EOperationStatus.Succeeded, destroyOp.Status); - bool result = YooAssets.RemovePackage(TestDefine.RawBundlePackageName); - Assert.IsTrue(result); + YooAssets.RemovePackage(TestDefine.RawBundlePackageName); } } } \ No newline at end of file