版本: v3.4.0
参考:Asset Bundle
关于Bundle,可以理解为资源模块化,允许开发者按照项目需求将贴图,脚本等资源划分在多个不同的Bundle中。
在项目运行的过程中,根据需求去加载不同的Bundle,以减少启动时加载的资源数量等。
通过AssetManager
下的BuiltinBundleName
可以得知:
export namespace AssetManager {
// 内置 bundle
export enum BuiltinBundleName {
RESOURCES = "resources",
MAIN = "main",
START_SCENE = "start-scene"
}
}
引擎内置的Bundle,主要有:
main
存放所有在构建发布面板的参与构建场景中勾选的场景以及依赖资源,通过主包压缩类型或配置主包为远程包而生成。resources
通过配置资源管理器中的assets目录下生成resources文件夹,更多内容参考:cocosCreator 之 resources(一)start-scene
在构建发布面板上勾选了初始场景分包,则首场景将会被构建到start-scene
中内置的Bundle,在构建发布中设置以后,在打包构建的时候,就会生成。以main和resources为例:
构建以后,在build的android-001下目录下,会生成出来:
Bundle的目录结构都是类似的,主要内容:
index.js
或game.js
的入口脚本文件import
或native
目录下config.json
下Bundle除了官方内置以外,也支持自定义配置。它的配置是以文件夹为单位的,当我们在资源管理器选择某个文件夹时,属性检查器就会出现一个配置为Bundle的选项。
官方给予了很好的提示,其配置参数:
配置参数 | 说明 |
---|---|
Bundle名称 | 构建名称,默认使用文件夹名字,可根据需要修改 |
Bundle优先级 | 构建时按照从大到小的顺序进行构建,优先级的设置可以相同,但要主要尽量保证共享的资源Texture 、SpriteFrame 、Audio 等Bundle的优先级更高 |
目标平台 | 不同平台可使用不同的配置,构建时根据平台来生成Bundle |
压缩类型 | 不同平台有着不同的压缩类型 |
配置为远程包 | 如果勾选,则构建后会放到remote文件夹中,该内容需要放到远程服务器上 |
针对于压缩类型,主要有如下几种:
压缩类型 | 说明 |
---|---|
无压缩 | 没有任何压缩操作 |
合并依赖 | 构建Bundle时,将相互依赖资源的JSON文件合并到一起,减少运行时加载请求的次数 |
合并所有JSON | 构建Bundle时,会将所有的JSON资源合并为一个,在web平台可以最大化减少请求数量,但会增加单个资源的加载时间。在Android平台不推荐使用,它会增加热更新的包体大小 |
小游戏分包 | 在提供了分包功能的小游戏平台,会将Bundle 设置为对应平台上的分包 |
ZIP | 在部分小游戏平台,构建Bundle会将资源文件压缩成Zip文件,以减少运行时的加载请求数量 |
关于优先级相关,内置Bundle的层级个分别为:
Asset Bundle | 优先级 |
---|---|
main |
7 |
resources |
8 |
start-scene |
20 |
注意: 自定义的Bundle优先级不要高于内置的Bundle,避免不能共享内置Bundle的资源。
另外,脚本也是支持Bundle的,如果设置Bundle后,则所有的脚本文件会合并为一个.js
文件,在加载Bundle的时候,就会去加载这个js
文件。
比如, 以assets/scripts为例,在设置Bundle后,通过android构建发布构建:
其中的index.js
文件就包含了所有的脚本文件内容相关。
脚本中使用Bundle,主要通过cc.assetManager
,它的主要方法有:
export const assetManager: AssetManager;
export class AssetManager {
// 获取已加载的bundle集合
bundles: __private.cocos_core_asset_manager_cache_ICache<AssetManager.Bundle>;
// 获取内置main包
get main(): AssetManager.Bundle | null;
// 获取内置resources包
get resources(): AssetManager.Bundle | null;
// 获取已加载的分包
getBundle(name: string): AssetManager.Bundle | null;
// 移除指定的bundle包
removeBundle(bundle: AssetManager.Bundle): void;
// 加载包
loadBundle(name, options, onComplete);
}
简单实例:
// 加载script Bundle
assetManager.loadBundle("DemoBundle", (err: Error, data) => {
console.log("loadBundle data:", data);
});
// 获取已加载的bundle
let scriptBundle = assetManager.getBundle("DemoBundle");
console.log("已加载的scriptBundle:", scriptBundle);
注意:
main
,resources
的Bundle外,其他自定义的Bundle必须在加载完成后,才能通过getBundle
获取到针对于Bundle的使用,大概与resources
的使用是类似的。 具体的方法有:
load
加载资源loadDir
批量加载资源preload
预加载资源preloadDir
预加载目录中资源更多内容可参考上篇博客cocosCreator 之 resources(一) ,简单的实例:
protected onLoad(): void {
// 加载Bundle
assetManager.loadBundle("DemoBundle", (err: Error, bundle) => {
if (err) {
return console.error(err);
}
this.initBundle(bundle);
});
}
private initBundle(bundle: any) {
console.log("bundle名字:", bundle.name);
console.log("bundle的根路径:", bundle.base);
console.log(bundle);
// 预加载bundle资源
bundle.preload("sound/click", (err, data) => {
if (err) {
return console.error(err);
}
console.log("localConfig data:", data);
});
// 预加载目录资源
bundle.preloadDir("spine", (err, data) => {
if (err) {
return console.error(err);
}
})
// 加载资源
bundle.load("sound/click", (err, data) => {
if (err) {
return console.error(err);
}
console.log(data);
});
}