在资源管理模块中有一个很重要的功能: Asset Bundle,那什么是Asset Bundle ?有什么作用?怎么使用 Asset Bundle呢 ?
一、什么是Asset Bundle ?有什么作用?
在日常游戏开发过程中,为了减少游戏启动时,资源首次下载和加载的时间,我们可以只下载和加载需要的资源模块。
而CocosCreator 中的 Asset Bundle 就是这样的模块化工具,允许我们按照项目需求,将图片、脚本、场景 等资源划分在多个不同的 Asset Bundle 中。
例如:一个大厅中集成了很多小游戏,我们都可以把 大厅以及不同的小游戏分别划分成不同的 Asset Bundle来管理。
Asset Bundle 可以放在不同的地方,比如远程服务器上,本地、或者小游戏平台的分包里。
二、CocosCreator 内置 Asset Bundle
内置 Asset Bundle | 功能说明 | 配置 | 优先级 |
---|---|---|---|
main | 存放所有在 构建发布 面板的 参与构建场景 中勾选的场景以及其依赖资源 | 通过配置 构建发布 面板的 主包压缩类型 和 配置主包为远程包 两项 | 7 |
resources | 存放 resources 目录下的所有资源以及其依赖资源 | 通过配置 资源管理器 中的 assets -> resources 文件夹 | 8 |
start-scene | 如果在 构建发布 面板中勾选了 初始场景分包,则首场景将会被构建到 start-scene 中。 | 无法进行配置 | 20 |
internal | 引擎模块内置的一些默认资源 | 无法进行配置 | 21 |
三、Asset Bundle 的基本使用
1、Asset Bundle 配置
自定义 Asset Bundle 以 文件夹 为单位进行配置,可以点击 属性检查器 上的 编辑按钮 或者通过 项目 菜单打开 项目设置 对 Bundle 进行配置。
配置项说明
配置项 | 功能说明 |
---|---|
Bundle 名称 | Asset Bundle 构建后的名称,默认会使用这个文件夹的名字,可根据需要修改。 |
Bundle 优先级 | Creator 开放了 20 个可供配置的优先级,构建时将会按照优先级 从大到小 的顺序对 Asset Bundle 依次进行构建。 |
目标平台 | 不同平台可使用不同的配置,构建时将根据对应平台的设置来构建 Asset Bundle。支持通过下拉框选择不同的平台配置,目前为默认配置。开发者可以通过 项目设置 -> Bundle 配置 自定义自己的配置方案。 |
压缩类型 | 决定 Asset Bundle 最后的输出形式,包括 合并依赖、无压缩、合并所有 JSON、小游戏分包、Zip 5 种压缩类型。 |
配置为远程包 | 是否将 Asset Bundle 配置为远程包,不支持 Web 平台。 若勾选了该项,则 Asset Bundle 在构建后会被放到 remote 文件夹,你需要将整个 remote 文件夹放到远程服务器上。 构建 OPPO、vivo、华为等小游戏平台时,若勾选了该项,则不会将 Asset Bundle 打包到 rpk 中。 |
Bundle 资源过滤 | 资源过滤可以过滤掉 Bundle 内的某些资源,通过下方的 预览 按钮,可以查看 Bundle 最终会的资源列表,Bundle 过滤分为包含和排除两部分。 |
构建 Bundle | 构建 Bundle 可以针对当前选中的 Bundle 进行构建。 |
(1)、Bundle 优先级规则说明
-
当同个资源被 不同优先级 的多个 Asset Bundle 引用时,资源会优先放在优先级高的 Asset Bundle 中,低优先级的 Asset Bundle 只会存储一条记录信息。此时低优先级的 Asset Bundle 会依赖高优先级的 Asset Bundle。
如果想在低优先级的 Asset Bundle 中加载此共享资源,必须在加载低优先级的 Asset Bundle 之前 先加载高优先级的 Asset Bundle。
-
当同个资源被 相同优先级 的多个 Asset Bundle 引用时,资源会在每个 Asset Bundle 中都复制一份。此时不同的 Asset Bundle 之间没有依赖关系,可按任意顺序加载。
所以需尽量确保共享的资源(例如Texture
、SpriteFrame
、Audio
等)所在的 Asset Bundle 优先级更高,以便让更多低优先级的 Asset Bundle 共享资源,从而最小化包体。
-
自定义的 Asset Bundle 优先级 不要高于 内置的 Asset Bundle,以便尽可能共享内置 Asset Bundle 中的资源。
(2)、压缩类型说明
Asset Bundle 默认使用 合并依赖 压缩类型,开可重新设置包括内置 Asset Bundle 在内的所有 Asset Bundle 的压缩类型。
压缩类型 | 功能说明 |
---|---|
合并依赖 | 构建 Asset Bundle 时会将相互依赖的资源的 JSON 文件合并在一起,从而减少运行时的加载请求次数 |
无压缩 | 构建 Asset Bundle 时没有任何压缩操作 |
合并所有 JSON | 构建 Asset Bundle 时会将所有资源的 JSON 文件合并为一个,从而最大化减少请求数量,但可能会增加单个资源的加载时间 |
小游戏分包 | 在提供了分包功能的小游戏平台,会将 Asset Bundle 设置为对应平台上的分包。 |
Zip | 在部分小游戏平台,构建 Asset Bundle 时会将资源文件压缩成一个 Zip 文件,从而减少运行时的加载请求数量 |
(3)、Bundle 资源过滤
资源过滤可以将选中的 Bundle 内的某些资源包括或者排除在 Bundle 内。
过滤类型
过滤类型目前有两种,Asset 资源以及 URL。默认为 URL。
2、Asset Bundle 的构建
在构建时,配置为 Asset Bundle 的文件夹中的资源(包含场景、代码和其他资源)以及文件夹外的相关依赖资源都会被合并到同一个 Asset Bundle 文件夹中。
配置为 Asset Bundle 的文件夹中的所有 代码 和 资源,会进行以下处理:
-
代码:文件夹中的所有代码会根据发布平台合并成一个
index.js
或game.js
的入口脚本文件。 -
资源:文件夹中的所有资源以及文件夹外的相关依赖资源都会放到
import
或native
目录下。 -
资源配置:所有资源的配置信息包括路径、类型、版本信息都会被合并成一个
config.json
文件。
例如:
3、 Asset Bundle 加载
(1)、通过名称加载
CocosCreator 提供了一个统一的 API assetManager.loadBundle
来加载 Asset Bundle,加载时需要传入 Asset Bundle 配置面板中的 Bundle 名称或者 Asset Bundle 的 url。
assetManager.loadBundle('name', (err, bundle) => {bundle.load('xxx');
});
(2)、通过url加载
复用其他项目的 Asset Bundle 时,只能通过 url 进行加载:
assetManager.loadBundle('https://test.com/remote/name', (err, bundle) => {bundle.load('xxx');
});
(3)、通过户空间路径加载
assetManager.loadBundle
还支持传入用户空间中的路径来加载 Asset Bundle。
我们可以通过对应平台提供的下载接口将 Asset Bundle 提前下载到用户空间中,然后再使用 loadBundle
进行加载,这样就可以完全自己管理 Asset Bundle 的下载与缓存过程,使用更灵活。
// 原生平台
assetManager.loadBundle(jsb.fileUtils.getWritablePath() + '/path/bundleName', (err, bundle) => {// ...
});// 微信小游戏平台
assetManager.loadBundle(wx.env.USER_DATA_PATH + '/path/bundleName', (err, bundle) => {// ...
});
4、加载 Asset Bundle 中的资源
(1)、普通加载
Asset Bundle 加载完成后,会返回一个 AssetManager.Bundle
类的实例。
我们可以通过实例上的 load
方法来加载 Asset Bundle 中的资源,此方法的参数与 resources.load
相同,只需要传入资源相对 Asset Bundle 的路径即可。
需要注意:路径的结尾处 不能 包含文件扩展名。
// 加载 Texture
bundle.load(`image/texture`, Texture2D, function (err, texture) {console.log(texture)
});
(2)、批量加载资源
批量加载资源与 resources.loadDir
相似,只需要传入该目录相对 Asset Bundle 的路径即可。
bundle.loadDir("textures", function (err, assets) {// ...
});
(3)、加载场景
加载场景 Asset Bundle 提供了 loadScene
方法用于加载指定 bundle 中的场景,你只需要传入 场景名 即可。
loadScene
与 director.loadScene
不同的地方在于 loadScene
只会加载指定 bundle 中的场景,而不会运行场景,还需要使用 director.runScene
来运行场景:
bundle.loadScene('test', function (err, scene) {director.runScene(scene);
});
(4)、预加载资源
Asset Bundle 中提供了 preload
和 preloadDir
接口用于预加载 Asset Bundle 中的资源。具体的使用方式和 assetManager
一致。
5、获取 Asset Bundle
当 Asset Bundle 被加载过之后,会被缓存下来,可以使用 Asset Bundle 名称来获取该 bundle。例如:
let bundle = assetManager.getBundle('name');
6、释放 Asset Bundle 中的资源
可以通过以下三种方式进行释放:
- 使用常规的
assetManager.releaseAsset
方法进行释放。
bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {assetManager.releaseAsset(spriteFrame);});
- 使用 Asset Bundle 提供的
release
方法,通过传入路径和类型进行释放,只能释放在 Asset Bundle 中的单个资源。参数可以与 Asset Bundle 的load
方法中使用的参数一致。
bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {bundle.release(`image`, SpriteFrame);});
- 使用 Asset Bundle 提供的
releaseAll
方法,此方法与assetManager.releaseAll
相似,releaseAll
方法会释放所有属于该 bundle 的资源(包括在 Asset Bundle 中的资源以及其外部的相关依赖资源),请慎重使用。
bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {bundle.releaseAll();});