版本: 3.4.0
语言: TypeScript
环境: Mac
简介
在cocosCreator中,我们所有的资源都是放在 assets目录下, 只有放在该目录下的资源,编译器才能使用。
该目录下的所有资源均继承于 Assets
,我们简单看下继承结构:
更多参考: cocosCreator 之 通过cc.d.ts了解Assets资源
在 assets 目录下的资源,主要分为两大类:
- 静态引用资源
- 动态加载资源
两者主要的区别在于: 资源是否放在 assets/resources 目录中。
静态引用的资源,编译器会对资源进行序列化操作。引擎会将这类资源记录在序列化数据中,并通过引用计数进行内存管理和释放。
动态加载的资源主要通过resources.load
在代码中动态加载设置到指定的场景组件中。引擎这对于这类资源时不会记录在序列化数据中,也就无法统计引用关系进行内存管理。
注:序列化可理解为将资源对象转为一种可存储或传输的格式。
两者相比较:
- 静态引用不需要关注内存释放相关,动态加载需要进行引用计数管理
- 静态引用资源内存占用很高,动态加载的资源需要才加载,内存占用低
- 静态引用资源没有动态加载资源灵活,可拓展性高
针对于动态加载资源,细分的话又会有两种:
- 放在 resources目录下,通过
resources.load
动态加载资源 - 将某目录设置为Bundle,放在资源服务器,然后进行下载,再通过
Bunddle.load
动态加载资源
在这里,我们看下编译器对resources目录的说明相关:
从图示中,我们可以了解到:
- resources是 Bundle,它有优先级、目标平台、压缩类型和是否配置远程包的设置
- 需要动态加载的资源,也就是必须调用
resources.load
方法的都必须放置在 resources目录中
Bundle 可以理解为"包", 是cocosCreator官方提供的资源模块化工具,它的特点是:
- 将指定的资源、脚本、场景等放在一起,设置名字,优先级,目标平台等
- 可放置在远程服务器或小游戏分包中,用于降低包体大小和减少加载游戏时间
本篇文章将主要讲述下关于resources
的使用相关,主要内容:
- 加载资源
- 预加载资源
- 示例
至于关于Bundle相关将在下篇博客进行分享:
cocosCreator 之 Buddle使用
理解可能有误,请提出您宝贵的建议,感激不尽。
resources加载
resources是官方的内置Bundle,其定义实现如下:
// resources 是一个 bundle,用于管理所有在 assets/resources 下的资源
export const resources: AssetManager.Bundle;
resources 就是 Bundle,但 Bundle会有很多个,他们的使用方法是一样的。
主要接口如下:
名字 | 描述 |
---|---|
name |
bundle的名称 |
base |
bundle的根路径 |
getInfoWithPath(path, type) |
通过路径获取指定资源的配置信息 |
getDirWithPath(path, type, out) |
获取某个指定文件夹下的所有资源信息 |
getAssetInfo(uuid) |
通过uuid获取资源信息 |
getSceneInfo(name) |
通过场景名获取场景信息 |
load(path, type, onPrgress, onComplete) |
通过相对路径加载资源 |
loadDir(dir, type, onProgree, onComplete) |
加载目标文件夹中的所有资源 |
loadScene(name, optins, onProgress, onComplete) |
通过场景名称加载分包中的场景 |
preload(paths,type, onProgress, onComplete) |
通过相对路径预加载分包中的资源 |
preloadDir(dir, type, onProgress, onComplete) |
预加载目标文件夹中的所有资源 |
preloadScene(name, optins, onProgress, onComplete) |
通过场景名称预加载分包中的场景 |
releaseUnusedAssets() |
释放此包中的所有没有用到的资源 |
releaseAll() |
释放此包中的所有资源 |
简要理解就是:
- 支持加载,通过调用
loadXXX
实现加载单一资源、目录、场景等 - 支持预加载,通过调用
preloadXXX
实现预加载资源,目录,场景等 - 支持释放, 通过调用
releaseXXX
进行释放资源
简单的使用:
// 加载背包的prefab页面
resources.load("prefab/bagLayer", Prefab, (err, prefab) => {
if(err) {
return console.err("Load Prefab fail");
}
const node = instantiate(prefab);
bagNode.parent = this.node;
});
// 加载某音效
let path = "prefab/sound/" + name;
resources.load(path, AudioClip, (err, clip) =>{
if(err) {
return console.err("load audioClip failed:" + err);
}
this._audioSource.playOneShot(clip, 1);
});
// 替换图片资源
const url = "textures/common/icon_gold/spriteFrame"
resources.load(url, SpriteFrame, (err, spriteframe)=> {
if (err) {
return console.err("load SpriteFrame failed:" + err);;
}
let sprite = this.node.getComponent(Sprite);
sprite.spriteFrame = spriteframe;
});
resources.load
支持着多种类型的添加,但要注意:
- 为了保证代码的安全性,建议在回调中增加加载失败的处理,即:error的判定
- 资源路径的添加不需要增加后缀名,但图片需要设定
spriteFrame
或texture
相关
关于图片的加载,更多内容可参考:[cocosCreator 之 图片资源动态加载]
预加载
resource目录下的资源有个特点:需要的时候就进行动态加载。
所以会存在一个问题,如果加载的某个资源比较复杂或嵌套很多,就会容易出现一个问题:卡顿。
不仅仅对于resources,对于其他的Bundle 来说,加载卡顿是必然的问题。
因此官方的Bundle
提供了preload
、preloadDir
、preloadScene
等接口,他们的特点是:
- 不会对资源进行解析或初始化操作
- 优先度很低,一般放在最后进行处理
- 不会影响资源的正常加载,即不需要等待预加载结束后再进行调用
const url = 'images/background/spriteFrame';
// 预加载某个资源
resources.preload(url, SpriteFrame);
// 加载某个资源不需要等预加载结束
resources.load(url, SpriteFrame, function (err, spriteFrame) {
spriteFrame.addRef();
self.getComponent(Sprite).spriteFrame = spriteFrame;
});
预加载的资源,cocosCreator会将资源放到一个缓存表中,当使用某些资源的时候,会首先检测缓存表中是否存在,如果存在,则直接使用缓存表中的资源;如果不存在,则会开始查找和加载资源。
注:bundle的加载或预加载接口都是异步的,以避免堵塞主线程
预加载示例
在项目开发中,预加载的主要应用地方是:loading页面,需要显示加载进度甚至要求显示加载的文件相关
因条件限制,本文使用 resources目录进行预加载
注:一般不会专门的对resources目录进行预加载,但如果是单机游戏倒是可以考虑
我们需要准备:一个Layer页面,主要节点: 进度条和描述文本
主要代码实现:
import { _decorator, assetManager, clamp01, Component, director, Label, ProgressBar, resources } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('UI_LoadingLayer')
export class UI_LoadingLayer extends Component {
@property(ProgressBar) loadBar: ProgressBar = null; // 进度条
@property(Label) desc: Label = null; // 描述文本
protected onLoad(): void {
// 获取已加载的分包
let resourceBundle = assetManager.bundles.get("resources");
resourceBundle = assetManager.getBundle("resources");
resourceBundle = assetManager.resources;
// 获取某个指定文件夹下的所有资源信息
const resourcePaths = resourceBundle.getDirWithPath("./");
console.log("resourcePaths", resourcePaths);
const maxLen = resourcePaths.length;
// 设置进度相关
this.desc.string = ""
this.loadBar.progress = 0;
let loadCount = 0;
for(let i = 0; i < maxLen; ++i) {
const path = resourcePaths[i].path;
resources.preload(path,
(completedCount: number, totalCount: number, item) => {
//console.log("progress:", completedCount, totalCount);
},
(err: Error | null, data: any) => {
if (err) {
return console.error("preload failed: " + err.message);
}
// 加载进度改变
loadCount++;
this.desc.string = `加载${path}`
this.loadBar.progress = clamp01(loadCount/maxLen);
console.log(`预加载的资源:${path}, 进度${this.loadBar.progress}`);
if (loadCount >= maxLen) {
setTimeout(() => {
this.desc.string = "加载完成";
// 切换场景,进入主页面
director.loadScene("uiMain");
}, 1000);
}
}
);
}
}
}
效果图如下:
更多详情可参考:cocosCreator 资源管理文章来源:https://www.toymoban.com/news/detail-627628.html
理解可能有误,欢迎大佬指出!感激不尽!文章来源地址https://www.toymoban.com/news/detail-627628.html
到了这里,关于cocosCreator 之 resources(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!