在游戏的开发过程中,需要使用到大量的图片、音频等资源来,从而带来管理上的困难。 Asset Manager 资源管理模块具备加载资源、查找资源、销毁资源、缓存资源、Asset Bundle 等功能,帮助开发者管理其资源的使用。
一、资源的加载
1、动态加载资源
Asset Manager 提供了以下两种的方式:
- 将资源放在 resources 目录下,配合
resources.load
等 API 来实现动态加载。 - 将资源制作为 Asset Bundle,再通过 Asset Bundle 的
load
系列 API 进行资源的加载。
(1)、加载预制体
resources.load("test/prefab", Prefab, (err, prefab) => {
const newNode = instantiate(prefab);
this.node.addChild(newNode);
});
(2)、 加载 AnimationClip
resources.load("test/anim", AnimationClip, (err, clip) => {s
this.node.getComponent(Animation).addClip(clip, "anim");
});
(3)、 加载 SpriteFrame
加载SpriteFrame image是ImageAsset spriteFrame
是image/spriteFrame texture是image/texture
resources.load("test/image/spriteFrame", SpriteFrame, (err, spriteFrame) => {
this.node.getComponent(Sprite).spriteFrame = spriteFrame;
});
(4)、 加载 Texture2D
resources.load("test/image/texture", Texture2D, (err: any, texture: Texture2D) => {
const spriteFrame = new SpriteFrame();
spriteFrame.texture = texture;
this.node.getComponent(Sprite).spriteFrame = spriteFrame;
});
(5)、 加载图集中的 SpriteFrame
resources.load("test/SpriteAtlas", SpriteAtlas, (err, atlas) => {
const frame = atlas.getSpriteFrame('name');
sprite.spriteFrame = frame;
});
(6)、 资源批量加载
resources.loadDir
可以加载相同路径下的多个资源:
//加载 test目录下所有资源
resources.loadDir("test", function (err, assets) {
// ...
});
//加载 test目录下所有 SpriteFrame,并且获取它们的路径
resources.loadDir("test", SpriteFrame, function (err, assets) {
// ...
});
(7)、加载远程资源
// 远程 url 带图片后缀名
let remoteUrl = "http://test.com/image.png";
assetManager.loadRemote<ImageAsset>(remoteUrl, function (err, imageAsset) {
const spriteFrame = new SpriteFrame();
const texture = new Texture2D();
texture.image = imageAsset;
spriteFrame.texture = texture;
// ...
});
// 远程 url 不带图片后缀名,此时必须指定远程图片文件的类型
remoteUrl = "http://test.com/emoji?id=123456";
assetManager.loadRemote<ImageAsset>(remoteUrl, {ext: '.png'}, function (err, imageAsset) {
const spriteFrame = new SpriteFrame();
const texture = new Texture2D();
texture.image = imageAsset;
spriteFrame.texture = texture;
// ...
});
// 远程音频
remoteUrl = "http://test.com/sound.mp3";
assetManager.loadRemote(remoteUrl, function (err, audioClip) {
// play audio
});
// 远程文本
remoteUrl = "http://unknown.org/skill.txt";
assetManager.loadRemote(remoteUrl, function (err, textAsset) {
// use string to do something
});
(8)、加载设备资源
用绝对路径加载设备存储内的资源
const absolutePath = "/dara/data/some/path/to/image.png";
assetManager.loadRemote<ImageAsset>(absolutePath, function (err, imageAsset) {
const spriteFrame = new SpriteFrame();
const texture = new Texture2D();
texture.image = imageAsset;
spriteFrame.texture = texture;
});
(9)、加载Asset Bundle
关于 Asset Bundle 的介绍,资源加载及使用,请查看下一篇文章。
(10)、资源预加载
为了减少下载的延迟,assetManager
和 Asset Bundle 提供了对应的预加载接口。
预加载只会下载必要的资源,不会进行反序列化和初始化工作,性能消耗小,适合在游戏过程中使用。
Asset Manager 中的大部分加载接口包括 load
、loadDir
、loadScene
都有其对应的预加载版本,如下表:
类型 | 支持 | 加载 | 释放 | 预加载 | 获取 | 查询资源信息 |
单个资源 | Asset Bundle | load | release | preload | get | getInfoWithPath |
文件夹 | Asset Bundle | loadDir | releaseAsset | preloadDir | N/A | getDirWithPath |
场景 | Asset Bundle | loadScene | N/A | preloadScene | N/A | getSceneInfo |
单个资源 |
| load | release | preload | get | getInfoWithPath |
文件夹 |
| loadDir | releaseAsset | preloadDir | N/A | getDirWithPath |
远程 | Asset Manager | loadRemote | releaseAsset | N/A | N/A | N/A |
资源加载接口与预加载接口所用参数完全一样,区别在于:
- 预加载只会下载资源,不会对资源进行解析和初始化操作
- 预加载在加载过程中会受到更多限制,例如最大下载并发数会更小
- 预加载的下载优先级更低,当多个资源在等待下载时,预加载的资源会放在最后下载
- 因为预加载没有做任何解析操作,所以当所有的预加载完成时,不会返回任何可用资源
由于预加载没有解析资源,所以需要在预加载完成后,再配合加载接口进行资源的解析和初始化。
例如:
resources.preload('images/background/spriteFrame', SpriteFrame);
// wait for while
resources.load('images/background/spriteFrame', SpriteFrame, function (err, spriteFrame) {
spriteFrame.addRef();
self.getComponent(Sprite).spriteFrame = spriteFrame;
});
注意:加载不需要等到预加载完成后再调用,开发者可以在任何时候进行加载。
正常加载接口会直接复用预加载过程中已经下载好的内容,缩短加载时间。
二、资源的释放
Asset Manager对依赖资源根据引用数量进行释放。
例如:
resources.load('prefabs/test', Prefab, function (err, asset) {
assetManager.releaseAsset(asset);
});
Creator 还提供了引用计数机制来控制资源的引用和释放:
- 当需要持有资源时,调用
addRef
来增加引用,确保该资源不会被其他引用到的地方自动释放。
resources.load('test/texture/image', Texture2D, function (err, texture) {
texture.addRef();
this.texture = texture;
});
- 当不再需要持有该资源时,调用
decRef
来减少引用,decRef
还将根据引用计数尝试自动释放。
this.texture.decRef();
this.texture = null;