一、介绍
Asset Bundle 作为资源模块化工具,允许开发者按照项目需求将贴图、脚本、场景等资源划分在多个 Asset Bundle 中,然后在游戏运行过程中,按照需求去加载不同的 Asset Bundle,以减少启动时需要加载的资源数量,从而减少首次下载和加载游戏时所需的时间。
二、放置位置
可以放在远程服务器、本地、或者小游戏平台的分包中。
v3.8 开始,Bundle 的配置方案被转移到 项目设置 -> Bundle 配置 分页内。您可以点击 属性检查器 上的 编辑按钮 或者通过 项目 菜单打开 项目设置 对 Bundle 进行配置。
注意:
- Creator 有 4 个 内置 Asset Bundle,包括 internal、resources、main、start-scene,在设置 Bundle 名称 时请不要使用这几个名称。
三、Asset Bundle的构建
1、处理方式:
- 代码:文件夹中的所有代码会根据发布平台合并成一个
index.js
或game.js
的入口脚本文件。 - 资源:文件夹中的所有资源以及文件夹外的相关依赖资源都会放到
import
或native
目录下。 - 资源配置:所有资源的配置信息包括路径、类型、版本信息都会被合并成一个
config.json
文件。
2、bd类型:
-
普通的 Asset Bundle 文件夹会被打包到对应平台发布包目录下的 assets 文件夹中。
- 配置 Asset Bundle 时,若勾选了 配置为远程包,则这个 Asset Bundle 文件夹会被打包到对应平台发布包目录下的 remote 文件夹中。
- 配置 Asset Bundle 时,若设置了 压缩类型 为 小游戏分包,则这个 Asset Bundle 文件夹会被打包到对应平台发布包目录下的 subpackages 文件夹中。
四、处理- Asset Bundle
1、加载AssetBundle
引擎提供了一个统一的 API ‘assetManager.loadBundle
’ 来加载 Asset Bundle,加载时需要传入 Asset Bundle 配置面板中的 Bundle 名称 或者 Asset Bundle 的 url。但当你复用其他项目的 Asset Bundle 时,则只能通过 url 进行加载。
assetManager.loadBundle('01_graphics', (err, bundle) => {
bundle.load('xxx');
});
// 当复用其他项目的 Asset Bundle 时
assetManager.loadBundle('https://othergame.com/remote/01_graphics', (err, bundle) => {
bundle.load('xxx');
});
2、加载Asset Bundle的资源
在 Asset Bundle 加载完成后,返回了一个 AssetManager.Bundle
类的实例。我们可以通过实例上的 load
方法来加载 Asset Bundle 中的资源,此方法的参数与 resources.load
相同,只需要传入资源相对 Asset Bundle 的路径即可。但需要注意的是,路径的结尾处 不能 包含文件扩展名。
// 加载 Prefab
bundle.load(`prefab`, Prefab, function (err, prefab) {
let newNode = instantiate(prefab);
director.getScene().addChild(newNode);
});
// 加载 Texture
bundle.load(`image/texture`, Texture2D, function (err, texture) {
console.log(texture)
});
// 加载 SpriteFrame
bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {
console.log(spriteFrame);
});
3、批量下载资源
Asset Bundle 提供了 loadDir
方法来批量加载相同目录下的多个资源。此方法的参数与 resources.loadDir
相似,只需要传入该目录相对 Asset Bundle 的路径即可。
// 加载 textures 目录下的所有资源
bundle.loadDir("textures", function (err, assets) {
// ...
});
// 加载 textures 目录下的所有 Texture 资源
bundle.loadDir("textures", Texture2D, function (err, assets) {
// ...
});
4、加载场景
Asset Bundle 提供了 ‘loadScene
’方法用于加载指定 bundle 中的场景,你只需要传入 场景名 即可。 ‘loadScene’
与 ‘director.loadScene
’不同的地方在于 loadScene
只会加载指定 bundle 中的场景,而不会运行场景,你还需要使用 ‘director.runScene
’来运行场景。
bundle.loadScene('test', function (err, scene) {
director.runScene(scene);
});
5、获取Asset Bundle 资源
当 Asset Bundle 被加载过之后,会被缓存下来,此时开发者可以使用 Asset Bundle 名称来获取该 bundle。
let bundle = assetManager.getBundle('01_graphics');
6、释放 Asset Bundle 中的资源
在资源加载完成后,所有的资源都会被临时缓存到 assetManager
中,以避免重复加载。当然,缓存中的资源也会占用内存,有些资源如果不再需要用到,可以通过以下三种方式进行释放:
-
使用常规的
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(); });
7、移除 Asset Bundle
在加载了 Asset Bundle 之后,此 bundle 会一直存在整个游戏过程中,除非开发者手动移除。当手动移除了某个不需要的 bundle,那么此 bundle 的缓存也会被移除,如果需要再次使用,则必须再重新加载一次。
let bundle = assetManager.getBundle('bundle1');
assetManager.removeBundle(bundle);
注意:在移除 Asset Bundle 时,并不会释放该 bundle 中被加载过的资源。如果需要释放,请先使用 Asset Bundle 的 release
/ releaseAll
方法:
let bundle = assetManager.getBundle('bundle1');
// 释放在 Asset Bundle 中的单个资源
bundle.release(`image`, SpriteFrame);
assetManager.removeBundle(bundle);
let bundle = assetManager.getBundle('bundle1');
// 释放所有属于 Asset Bundle 的资源
bundle.releaseAll();
assetManager.removeBundle(bundle);