Bundle
ABundle 是抽象基类,Bundle 是其实现类,它们基于 Unity 自带的 AssetBundle 类实现了资源的加载与管理逻辑。
| 类名 | 职责 |
|---|---|
ABundle | 抽象定义一个 AssetBundle 的生命周期管理器,包括加载、卸载、资源获取、引用计数、依赖等逻辑。 |
Bundle | 具体实现 ABundle,利用 UnityEngine.AssetBundle 执行加载/卸载等操作。 |
AssetBundle(Unity 原生) | 实际负责读取 AssetBundle 文件、从中加载资源(例如 Prefab、Texture、AudioClip 等)。 |
+-------------------+
| ABundle (抽象类)|
|-------------------|
| + Load() | <- 定义加载接口
| + UnLoad() | <- 定义卸载接口
| + LoadAsset() | <- 同步加载资源
| + LoadAssetAsync()| <- 异步加载资源
| + 引用计数管理 |
| + 依赖关系预设字段 |
+-------------------+
↑
| 继承
+-------------------+
| Bundle(实现类)|
|-------------------|
| 使用 Unity 的 |
| AssetBundle 加载 |
| 本地资源文件 |
| 具体实现四个抽象方法 |
+-------------------+
↓
+--------------------------+
| UnityEngine.AssetBundle |
+--------------------------+
BundleAsync
BundleAsync是在 ABundle 框架上扩展出的异步资源加载模块,通过 AssetBundleCreateRequest 实现非阻塞加载,并配合 Update() 轮询机制、依赖控制、引用计数等功能,构建了一个高性能、可控的异步加载系统,适用于运行时大量资源动态加载场景。
与类Bundle的函数Load()不同的是,当你调用类BunldeAsync的函数Load()时,并不会立刻返回 AssetBundle 实例,而是返回一个异步请求对象m_AssetBundleCreateRequest。由于异步加载的完成时机是不确定的,所以需要函数Update()来不断轮询异步请求对象的值isDone来判断是否加载完成,完成时,提取出它的assetBundle实例。
异步请求对象AssetBundleCreateRequest
AssetBundleCreateRequest 是 Unity 提供的一个类,继承自 AsyncOperation,用于表示正在进行中的 AssetBundle 加载操作。它是异步加载的结果句柄,我们通过isDone来判断是否加载完成,并且从assetBundle中获得成果。可以用函数Update()輪询它的状态,或者用协程等待完成。
它的设计目标是 避免阻塞主线程。
当你使用异步加载方法:
AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path);
Unity 不会立即返回 AssetBundle,而是返回一个 AssetBundleCreateRequest。你可以等待它完成:
yield return request; // 在协程中等待完成
AssetBundle bundle = request.assetBundle;
主要成员:
| 成员 | 类型 | 说明 |
|---|---|---|
assetBundle | AssetBundle | 获取加载完成后的 AssetBundle 实例。如果请求尚未完成,返回 null。 |
isDone | bool | 继承自 AsyncOperation,表示是否加载完成。 |
progress | float | 加载进度,范围 [0, 1]。 |
allowSceneActivation | bool | 控制是否允许激活场景(主要用于场景异步加载)。 |
对比:
| 特性 | Bundle(同步) | BundleAsync(异步) |
|---|---|---|
| 加载方式 | LoadFromFile | LoadFromFileAsync |
| 主线程阻塞 | 是 | 否(非阻塞) |
| 状态检查 | 自动完成 | 需手动调用 Update() |
| 卸载方式 | 显式调用 UnLoad() | Update() 时若无人引用则自动卸载 |
| 使用场景 | 小资源、本地测试、初始化 | 大资源、场景资源、运行时热加载 |
同步加载 vs 异步加载
- 同步加载(Synchronous Loading)
定义:函数调用会阻塞主线程,直到加载完成,程序才会继续往下执行。
特点:
- 简单易用;
- 会造成 卡顿或掉帧,特别是加载大文件或大量资源时;
- 不适合在游戏运行时动态加载,尤其是移动端。
AssetBundle bundle = AssetBundle.LoadFromFile("path/to/assetbundle");
2. 异步加载(Asynchronous Loading)
定义:函数调用立即返回一个 AsyncOperation 或类似结构,加载在后台进行,加载完成后触发回调或状态变更。
特点:
- 不会阻塞主线程,适合运行时加载;
- 更复杂,需要监听完成状态;
- 更适合商业级或优化性能的项目。
AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync("path/to/assetbundle");
yield return request;
AssetBundle bundle = request.assetBundle;
| 使用场景 | 推荐加载方式 | 理由 |
|---|---|---|
| 启动加载主UI | 同步 (LoadFromFile) | 避免复杂异步逻辑,UI资源体积小 |
| 战斗场景中加载敌人资源 | 异步 (LoadFromFileAsync) | 避免卡顿 |
| 地图过渡加载下一区域 | 异步 | 玩家尚未进入时加载,体验更流畅 |
| 编辑器下打包验证 | 同步 | 调试简单,能及时看到错误 |
同步加载快但会卡顿;异步加载慢但流畅。大文件/运行时加载用异步,小文件/初始化用同步。
Asset和AssetBundle的区别
| 名称 | 含义 | 举例 |
|---|---|---|
| Asset | 资源。是最终被使用的对象 | 一个 .prefab、.png 图片、.mp3 音乐、.mat 材质球等 |
| AssetBundle | 资源包,是一组打包好的 Assets,通常从磁盘或网络加载进来 | Characters.ab、Level01.ab、UICommon.ab 等 |
AssetBundle(资源包)
├── Player.prefab → Asset
├── Gun.png → Asset
└── Explosion.wav → Asset
BunldeManager
BundleManager是单例模式,它是面向AssetBundle加载与管理的核心管理类,主要负责:
- 资源路径映射
- 加载AssetBundle
- 自动卸载无用资源
- 管理依赖关系
- 管理异步加载生命周期
- 延迟卸载逻辑
BundleManager是一个高效、通用、可扩展的AssetBundle异步加载框架,通过缓存、泛型、安全封装和自动管理,简化了Unity热更新资源的访问与维护流程,是商业项目中资源系统的重要组成部分。
核心类和方法:
| 类/方法 | 说明 |
|---|---|
BundleManager | 管理所有加载的 AssetBundle,缓存它们,并提供加载、卸载与资源获取接口。 |
LoadAsset<T>(string url) | 泛型接口,传入资源路径 url,异步加载并返回 T 类型资源。 |
LoadAssetAsync(string url) | 协程方法,真正执行异步加载 AssetBundle 及资源的逻辑。 |
Unload(string url) | 手动卸载某个已加载的资源。 |
AssetRequest | 封装一个资源的加载状态与引用,支持自动从 AssetBundle 中加载、卸载资源。 |
AssetRequest.GetAsset<T>() | 获取某个已加载资源的实例,带类型安全检查和自动替换逻辑。 |
资源加载流程图:
外部调用:LoadAsset<Sprite>("characters/hero")
↓
查找缓存:
- 如果已缓存,直接返回
↓
如果未加载过:
- 启动协程:LoadAssetAsync("characters/hero")
↓
使用 WWW 或 UnityWebRequest 异步加载 .bundle 文件
↓
加载完成后:bundle.LoadAsset("characters/hero", typeof(Sprite))
↓
创建 AssetRequest 并缓存到字典中
↓
调用 AssetRequest.GetAsset<T>() 返回资源引用
Resource
Resource
Resource是同步加载的资源类,通过加载指定 AssetBundle 并从中同步提取出资源对象,提供访问和实例化,并支持回调与引用管理。
在整个框架的架构中,Resource对应的是某一个具体的资源对象(如一个 Prefab、一张贴图、一段音效等)——而不是打包的 AssetBundle 本身。
ResourceManager
[游戏启动]
↓
[ResourceManager.Initialize()]
↓
[BundleManager.Initialize()]
↓
[加载 manifestAssetBundle]
↓
[解析 AssetBundleManifest]
↓
[加载目标资源A]
↓
[先找资源A所在的Bundle]
↓
[根据Manifest查依赖,先加载依赖Bundles]
↓
[加载资源A所在Bundle]
↓
[从中加载出 Resource A(Prefab、Texture等)]
Build打包过程
(1)类BuildItem
用于配置某一类资源如何打成AssetBundle的参数模型,在整个打包流程中非常关键。
BuildItem是 打包配置表中的一行规则项,它告诉打包工具:
- 要打哪个路径;
- 如何过滤(按后缀);
- 如何打包(按文件、目录、合并);
- 是否参与依赖;
- 忽略哪些路径。
⚠️ 它本身不会做任何打包行为,只是数据模型,供打包器(如 BuildProcessor)使用。
(2)类BuildSetting
BuildSetting是整个打包系统的规则总控器,负责:资源筛选、规则匹配、Bundle 命名和路径处理,是打包系统的大脑。
BuildSetting和BuildItem的关系
BuildSetting是统一配置和组织者,BuildItem是每个包的具体打包计划,它们一起构成了定制化的打包系统。
BuildSetting(打包总管)
│
├── BuildItem A(打包 Login.prefab)
├── BuildItem B(打包所有声音)
└── BuildItem C(打包所有怪物贴图)
↓
Builder 执行打包
↓
构建 AssetBundleBuild[]
↓
调用 Unity 官方打包 API
↓
输出 AB 文件和 manifest 文件
额外问题
(1)什么是manifestAssetBundle?
Unity 在打包 AssetBundle 时,会额外生成一个特殊的 AssetBundle,它的名字和你指定的输出目录名一致(比如你打包到目录叫 AssetBundles,就会生成一个同名的 bundle),它就是所谓的:
manifestAssetBundle—— 里面包含了一个AssetBundleManifest对象
这个对象里记录了:
- 所有 AssetBundle 的名字
- 每个 AssetBundle 的直接依赖关系(哪些 Bundle 是它依赖的)
- 是否有循环依赖
- Bundle 的 Hash 值(用于版本控制)
- Bundle 是否是压缩过的(chunked/compressed)
你可以把它理解为:
📜 AssetBundle 的“总目录”/“依赖清单”

Leave a comment