2026-07-07 18:36:15 +08:00
|
|
|
|
# 资源管理
|
|
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
## 目的
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
资源管理负责 AssetBundle、依赖、语言资源、SpriteAtlas、内存卸载、启动代码更新和普通资源分包下载。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
## 源码边界
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
| 类型 | 路径 | 说明 |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| ESF AssetBundle 源码 | `Assets/StrayFog/Editor/CopyToX/CopyToHF/AssetBundle/` | 框架修改源头 |
|
|
|
|
|
|
| HF AssetBundle 代码 | `Assets/Game/GameHFScripte/CopyToHF/AssetBundle/` | CopyToX 生成,禁止手改 |
|
|
|
|
|
|
| V2 公共运行时 | `Assets/StrayFog/Core/SFSubPackageV2.cs` | 非热更层与热更层共享下载状态 |
|
|
|
|
|
|
| V2 编辑器构建 | `Assets/StrayFog/Editor/Tools/AssestBundle/` | 包配置、校验、清单和枚举生成 |
|
|
|
|
|
|
| 热更业务门面 | `Assets/Game/GameHFScripte/GameFunction/HFDownLoadSubPackage/` | 普通资源下载 API |
|
|
|
|
|
|
| 启动代码入口 | `Assets/Game/GameMono/Scripts/GameDllManager.cs` | Bootstrap 校验、下载和加载 |
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
修改 `ESF_` 后执行 CopyToX,再检查生成的 `HF_` 差异和 `GameHF` 编译结果。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
## AssetBundle 加载
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
```text
|
|
|
|
|
|
HFFunCatalogue.Asset / HFABMgr.LoadInMemory
|
|
|
|
|
|
-> 读取 AssetBundleManifest
|
|
|
|
|
|
-> 语言与路径修正
|
|
|
|
|
|
-> 创建或复用 HFAssetLoader
|
|
|
|
|
|
-> 加载依赖 Bundle
|
|
|
|
|
|
-> 加载主 Bundle
|
|
|
|
|
|
-> HFAssetResponse.GetAsset<T>()
|
|
|
|
|
|
```
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
`HFABMgr` 继续作为统一入口,并使用 partial 文件组织 Manifest、Loader、GC、路径和模式逻辑。内部职责可以封装,但业务入口不拆散。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
### Manifest 与来源顺序
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
Editor 模式直接读取工程资源。Player 本地模式按以下顺序初始化 Manifest:
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
```text
|
|
|
|
|
|
PersistentData Manifest
|
|
|
|
|
|
-> 不存在或无效时读取 StreamingAssets Manifest
|
|
|
|
|
|
-> 两处都不可用且已配置 CDN 时读取 CDN Manifest
|
|
|
|
|
|
```
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- PersistentData 保存热更新后的可写资源,优先于母包资源。
|
|
|
|
|
|
- StreamingAssets 是只读随包资源;Android、WebGL 等 URL 路径通过 UnityWebRequest 协程读取。
|
|
|
|
|
|
- CDN 是本地 Manifest 都不可用或资源需要更新时的远端来源。
|
|
|
|
|
|
- 显式 CDN/小游戏模式按平台适配层和缓存回调工作,不假设普通文件系统可用。
|
|
|
|
|
|
- `Application.dataPath` 只用于 `UNITY_EDITOR` 下的资源定位和分析。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
PersistentData 普通文件优先使用 `AssetBundle.LoadFromFileAsync`。StreamingAssets URL、CDN byte[]、小游戏缓存和需要解密的数据继续使用 `LoadFromMemoryAsync`。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
### CDN 落盘
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
`SetCdnSaveRootPath(string)` 允许平台层传入保存根目录。有效外部路径优先;未设置时使用 `SFGlobalData.assetBundleRoot`,即项目 PersistentData 资源根目录。保存时保留相对目录结构。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
## 内存与卸载
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- GC 与主动卸载共用 loader 释放流程。
|
|
|
|
|
|
- 释放时调用 `AssetBundle.Unload(false)`,销毁 loader,并同步清理 loader 映射、生命周期池和内存统计。
|
|
|
|
|
|
- 按资源名卸载只在唯一匹配且 loader 可卸载时成功;未找到、重名、加载未完成或仍有请求时返回 `false`。
|
|
|
|
|
|
- 内存大小使用 loader 统计或本地文件长度估算,只用于运行时观察,不替代 Unity Profiler。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
公开使用方式见 [资源管理使用指南](使用指南.md)。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
## 分包 V2
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
V2 将编辑器构建清单与设备下载状态分离。运行时只消费编辑器生成的 V2 清单,不识别旧 `SPI_*` 结构。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
### 编辑器阶段
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
资源包通过 Unity 编辑器自由配置,XML 只负责持久化。每个 Package 包含:
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- `Id`、`DisplayName`、`Priority`、`BuiltIn`
|
|
|
|
|
|
- `RootPaths[]`
|
|
|
|
|
|
- `DependencyPackageIds[]`
|
|
|
|
|
|
|
|
|
|
|
|
保存和构建会校验空/重复 ID、无效路径、自依赖、缺失依赖和循环依赖。根路径使用标准化小写路径与目录边界前缀匹配;重叠目录警告但允许构建。
|
|
|
|
|
|
|
|
|
|
|
|
构建顺序:
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
|
|
|
|
|
```text
|
2026-07-10 17:50:20 +08:00
|
|
|
|
普通 AssetBundle
|
|
|
|
|
|
-> AOT 与 HotUpdate DLL 产物
|
|
|
|
|
|
-> 收集最终文件
|
|
|
|
|
|
-> 生成 V2 subpackage.json
|
|
|
|
|
|
-> 复制 BuiltIn 文件并生成分析结果
|
2026-07-07 18:36:15 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
生成清单的同时生成 `enHFSubPackageId.cs`。枚举成员由 PackageId 转换,XML 注释使用 DisplayName;业务通过映射恢复原始 PackageId,生成文件禁止手改。
|
|
|
|
|
|
|
|
|
|
|
|
### V2 清单
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
|
|
|
|
|
```text
|
2026-07-10 17:50:20 +08:00
|
|
|
|
Version / Platform / BuildId
|
|
|
|
|
|
BootstrapFiles[] AOT 与 HotUpdate 启动代码
|
|
|
|
|
|
Files[] 普通 AB 的 Path、MD5、Size、Dependencies
|
|
|
|
|
|
Packages[] 包配置、FilePaths 和 Size
|
2026-07-07 18:36:15 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- `BootstrapFiles` 按 `CodeKind` 和 `LoadOrder` 控制 AOT、HotUpdate 加载顺序。
|
|
|
|
|
|
- `Files` 以标准化 Path 全局唯一,依赖来自 Unity AssetBundleManifest。
|
|
|
|
|
|
- `Packages` 没有固定业务类型;PackageId 的业务意义由调用方决定。
|
|
|
|
|
|
- Package 显式依赖和 AB 文件依赖是两套关系,运行时都会递归展开。
|
|
|
|
|
|
|
|
|
|
|
|
### 运行时顺序
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
|
|
|
|
|
```text
|
2026-07-10 17:50:20 +08:00
|
|
|
|
下载并校验远端 V2 清单
|
|
|
|
|
|
-> 比对 BootstrapFiles
|
|
|
|
|
|
-> PersistentData 命中则复用
|
|
|
|
|
|
-> 否则检查 StreamingAssets
|
|
|
|
|
|
-> 仍不匹配则从 CDN 下载到临时文件并校验 MD5
|
|
|
|
|
|
-> AOT 加载成功
|
|
|
|
|
|
-> HotUpdate 加载与入口执行成功
|
|
|
|
|
|
-> CommitBootstrapCodeLoaded 提交清单和状态
|
|
|
|
|
|
-> 普通资源比对与下载开放
|
2026-07-07 18:36:15 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
Bootstrap 是普通资源的硬门禁。清单、下载、MD5、AOT、HotUpdate 或入口任一步失败都不会开放普通资源阶段。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
CDN URL 使用:
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
|
|
|
|
|
```text
|
2026-07-10 17:50:20 +08:00
|
|
|
|
{BaseUrl}/{AppPartner}/{AppVersion}/{Platform}/{FilePath}
|
2026-07-07 18:36:15 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
BaseUrl 按配置顺序尝试,使用 `/` 进行 URI 拼接。Bootstrap 文件最多三轮,每轮尝试全部有效 BaseUrl;普通文件一次请求按顺序尝试有效地址。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
### 普通资源更新范围
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
`CheckAndDownloadAllFiles` 不会无条件下载整个 `Files[]`,它处理:
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- 未归属任何 Package 的基础文件。
|
|
|
|
|
|
- `BuiltIn = true` 的 Package 及依赖包。
|
|
|
|
|
|
- `DownloadedPackageIds` 中历史成功下载的 Package 及依赖包。
|
|
|
|
|
|
- 上述文件的完整 AB 依赖闭包。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
从未下载、非 BuiltIn 的可选 Package 不会被全量更新误下载。业务可按 PackageId 主动下载,资源加载缺文件时也可按 `Files[]` 下载目标文件依赖闭包。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
### 状态与去重
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
`subpackage_state.json` 当前保存:
|
2026-07-07 19:07:27 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- `BuildId`
|
|
|
|
|
|
- `DownloadedFiles` 的 Path 与 MD5
|
|
|
|
|
|
- `DownloadedPackageIds`
|
2026-07-07 19:07:27 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
Package 完整成功后才记录请求包和依赖包。查询 Package 是否完成时会同时检查当前清单、PackageId 状态、依赖包状态和所有文件 MD5。
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
去重分为三层:清单 Path 唯一、进行中任务按 `Path + MD5` 合并、本地文件和状态校验通过后复用。文件只有完整写入并通过 MD5 后才更新状态和进度计数。
|
|
|
|
|
|
|
|
|
|
|
|
## 验证重点
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
- PersistentData、StreamingAssets 和 CDN 的 Manifest 回退不会卡住主线程。
|
|
|
|
|
|
- 本地文件使用正确加载策略,平台 URL 使用协程。
|
|
|
|
|
|
- GC/主动卸载后能重新加载,loader 映射和内存统计正确。
|
|
|
|
|
|
- V2 差异结果在下载前回调,失败信息包含 Path、期望 MD5 和尝试 URL。
|
|
|
|
|
|
- 冷启动会从状态继续按文件校验,已完成文件不重复下载。
|
|
|
|
|
|
- 已下载 Package 在远端 MD5、依赖或 FilePaths 变化后参与更新。
|
|
|
|
|
|
|
|
|
|
|
|
## 文档关联
|
2026-07-07 18:36:15 +08:00
|
|
|
|
|
|
|
|
|
|
| 文档 | 关联原因 |
|
|
|
|
|
|
|---|---|
|
2026-07-10 17:50:20 +08:00
|
|
|
|
| [资源管理使用指南](使用指南.md) | 业务调用、卸载、内存和分包 API |
|
|
|
|
|
|
| [模块索引](../../模块索引.md) | 模块入口和状态 |
|
|
|
|
|
|
| [UI 窗口系统](../UI窗口系统/README.md) | UI Prefab 加载与卸载 |
|
|
|
|
|
|
| [Hotfix 启动](../Hotfix启动.md) | Bootstrap 代码加载入口 |
|
|
|
|
|
|
| [架构说明](../../../rules/10-架构说明.md) | ESF/HF 源码边界 |
|
|
|
|
|
|
| [工作流清单](../../../rules/40-工作流清单.md) | 生成和平台验证流程 |
|