Cocos Creator | 资源管理:资源的动态加载/远程加载/缓存/预加载/同步加载/远程加载spine

更好的阅读体验请访问公众号:
 

 

// resources 目录 //

 

所有需要通过脚本动态加载的资源,都必须放置在 resources 文件夹或它的子文件夹下

resources 文件夹需要在 assets 根目录下手动创建

 

 

 

resources 文件夹中的资源,可以引用文件夹外部的其它资源,同样也可以被外部场景或资源所引用

项目构建时,除了在 构建发布 面板中勾选的场景外,resources 文件夹中的所有资源,包括它们关联依赖的 resources 文件夹外部的资源,都会被导出

如果一份资源仅仅是被 resources 中的其它资源所依赖,而不需要直接被 cc.resources.load 调用,那么 请不要 放在 resources 文件夹中,否则会增大 config.json 的大小,并且项目中无用的资源,将无法在构建的过程中自动剔除,同时在构建过程中,JSON 的自动合并策略也将受到影响,无法尽可能合并零碎的 JSON

 

· 加载 SpriteFrame

 

图片设置为 Sprite 后,将会在 资源管理器 中生成一个对应的 SpriteFrame

 

如果直接加载 HelloWorld,得到的类型将会是 cc.Texture2D

  •  
  •  
  •  
  •  
// 加载 Texture2Dcc.resources.load("HelloWorld", (error: Error, assets: cc.Texture2D) => {    this.sprite.spriteFrame = new cc.SpriteFrame(assets);});

 

必须指定第二个参数为资源的类型,才能加载到图片生成的 cc.SpriteFrame

  •  
  •  
  •  
  •  
// 加载 SpriteFramecc.resources.load("HelloWorld", cc.SpriteFrame, (error: Error, assets: cc.SpriteFrame) => {    this.sprite.spriteFrame = assets;});

 

如果指定了类型参数,就会在路径下查找指定类型的资源

当在同一个路径下同时包含了多个同名资源(例如同时包含 player.png 和 player.mp3),或者需要获取子资源(例如获取 Texture2D 生成的 SpriteFrame),就需要声明类型

 

 

Texture 和 SpriteFrame 资源类型

 

在 资源管理器 中,图像资源的左边会显示一个和文件夹类似的三角图标,点击就可以展开看到它的子资源(sub asset),每个图像资源导入后编辑器会自动在它下面创建同名的 SpriteFrame 资源

 

SpriteFrame 是核心渲染组件 Sprite 所使用的资源,设置或替换 Sprite 组件中的 spriteFrame 属性,就可以切换显示的图像

 

为什么会有 SpriteFrame 这种资源?Texture 是保存在 GPU 缓冲中的一张纹理,是原始的图像资源。而 SpriteFrame 包含两部分内容:记录了 Texture 及其相关属性的 Texture2D 对象和纹理的矩形区域,对于相同的 Texture 可以进行不同的纹理矩形区域设置,然后根据 Sprite 的填充类型,如 SIMPLE、SLICED、TILED 等进行不同的顶点数据填充,从而满足 Texture 填充图像精灵的多样化需求。而 SpriteFrame 记录的纹理矩形区域数据又可以在资源的属性检查器中根据需求自由定义,这样的设置让资源的开发更为高效和便利。除了每个文件会产生一个 SpriteFrame 的图像资源(Texture)之外,我们还有包含多个 SpriteFrame 的图集资源(Atlas)类型

 

· 加载图集中的 SpriteFrame

  •  
  •  
  •  
  •  
  •  
// sheep 目录下的 sheep.plist 文件cc.resources.load("sheep/sheep", cc.SpriteAtlas, (error: Error, assets: cc.SpriteAtlas) => {    let frame = assets.getSpriteFrame("sheep_down_0");    this.sprite.spriteFrame = frame;});

 

· 加载 spine

  •  
  •  
  •  
  •  
// spineboy 目录下的 spineboy.json 文件cc.resources.load("spineboy/spineboy", sp.SkeletonData, (error: Error, assets: sp.SkeletonData) => {    this.spine.skeletonData = assets;});

 

· 资源批量加载

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 加载 test assets 目录下所有资源cc.resources.loadDir("test assets", (err, assets)=> {    // ...});
// 加载 test assets 目录下所有 SpriteFramecc.resources.loadDir("test assets", cc.SpriteFrame, (err, assets)=> {    // ...});

 

 

// Asset Bundle 目录 //

 

对 Asset Bundle 的详细解读,请查阅笔记:

Creator | 资源管理:Asset Bundle 全解析

 

Asset Bundle 提供的加载资源的 API 和 cc.resources 基本一致

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
cc.assetManager.loadBundle("MyBundle", (err: Error, bundle: cc.AssetManager.Bundle) => {    bundle.load();    bundle.loadDir();    bundle.loadScene();    bundle.preload();    bundle.preloadDir();    bundle.preloadScene();});

 

// 远程服务器和设备目录 //

 

API:cc.assetManager.loadRemote

这种加载方式只支持图片、声音、文本等原生资源类型,不支持 SpriteFrame、SpriteAtlas、Tilemap 等(继承自 cc.Asset)资源的直接加载和解析,如需远程加载所有资源,可使用 Asset Bundle

 

1远程服务器

· 远程 url 带图片后缀名

  •  
  •  
  •  
  •  
let remoteUrl = "http://unknown.org/someres.png";cc.assetManager.loadRemote(remoteUrl, function (err, texture) {    // Use texture to create sprite frame});

 

· 远程 url 不带图片后缀名,此时必须指定远程图片文件的类型

  •  
  •  
  •  
  •  
let remoteUrl = "http://unknown.org/emoji?id=124982374";cc.assetManager.loadRemote(remoteUrl, {ext: '.png'}, function () {    // Use texture to create sprite frame});

 

· 加载远程 spine

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
let imageUrl = "http://xxx/spineboy.png";let atlasUrl = "http://xxx/spineboy.atlas";let skeletonUrl = "http://xxx/spineboy.json";cc.assetManager.loadRemote(imageUrl, (err: Error, texture: cc.Texture2D) => {    cc.assetManager.loadRemote(atlasUrl, (error: Error, atlasText: cc.TextAsset) => {        cc.assetManager.loadRemote(skeletonUrl, (error: Error, skeletonJson: cc.JsonAsset) => {            let asset = new sp.SkeletonData();            asset.skeletonJson = skeletonJson.json;            asset.atlasText = atlasText.text;            asset.textures = [texture];            asset.textureNames = ["texture.png"];            this.spine.skeletonData = asset;            this.spine.animation = "animation";        });    });});

 

· 远程音频

  •  
  •  
  •  
  •  
let remoteUrl = "http://unknown.org/sound.mp3";cc.assetManager.loadRemote(remoteUrl, function (err, audioClip) {    // play audio clip});

 

· 远程文本

  •  
  •  
  •  
  •  
let remoteUrl = "http://unknown.org/skill.txt";cc.assetManager.loadRemote(remoteUrl, function (err, textAsset) {    // use string to do something});

 

2设备目录

用绝对路径加载设备存储内的资源,比如相册

  •  
  •  
  •  
  •  
let absolutePath = "/dara/data/some/path/to/image.png"cc.assetManager.loadRemote(absolutePath, function () {    // Use texture to create sprite frame});

 

在 原生平台 通过 jsb.Downloader 下载资源并将其保存在设备可写目录(jsb.fileUtils.getWritablePath)后,可通过保存路径直接加载

  •  
  •  
  •  
let storagePath = jsb.fileUtils.getWritablePath() + '/test.png';cc.assetManager.loadRemote(storagePath, (err: Error, texture: cc.Texture2D) => {});

 

// 资源缓存 //

 

在 Web 平台,资源下载完成之后,缓存是由浏览器进行管理的

而在其他具备文件系统的平台上, Creator 提供了缓存管理器,以便对缓存进行增删改查操作

 

cc.assetManager.cacheManager

缓存管理器是一个模块,在非 WEB 平台上,用于管理所有从服务器上下载下来的缓存

 

cc.assetManager.cacheManager.getCache(originUrl)

通过原始 url 获取缓存后的路径

 

cc.assetManager.cacheManager.cachedFiles

所有缓存文件列表

 

远程资源(包括远程AB包)加载成功后会将该资源文件存放到本地缓存目录中,如 win32 模拟器:

 

通过 url 加载AB包,在 loadBundle 后,只是将该AB包中的 资源清单 和 脚本文件 缓存到本地,只有在 bundle 调用 load 或者 preload 时,才会缓存对应的资源

 

cacheList.json 文件中以 { url:  object } 的形式记录远程资源信息,以后再次加载该远程资源时则直接使用缓存中的资源文件

 

// 资源预加载 //

 

为了尽可能缩短下载时间,我们可以使用预加载

Asset Manager 中的大部分加载接口包括 load、loadDir、loadScene 都有其对应的预加载版本

 

  •  
cc.resources.preload("HelloWorld", cc.SpriteFrame);

 

  •  
  •  
  •  
cc.assetManager.loadBundle("MyBundle", (err: Error, bundle: cc.AssetManager.Bundle) => {    bundle.preload("HelloWorld", cc.SpriteFrame);});

 

加载接口与预加载接口所用的参数是完全一样的,两者的区别在于:

  1. 预加载只会下载资源,不会对资源进行解析和初始化操作

  2. 预加载在加载过程中会受到更多限制,例如最大下载并发数会更小

  3. 预加载的下载优先级更低,当多个资源在等待下载时,预加载的资源会放在最后下载

  4. 因为 预加载没有做任何解析操作,所以当所有的预加载完成时,不会返回任何可用资源

 

以上优化手段充分 降低了预加载的性能损耗确保了游戏体验顺畅,开发者可以充分利用游戏过程中的网络带宽缩短后续资源的加载时间

因为预加载没有去解析资源,所以需要在预加载完成后配合加载接口进行资源的解析和初始化,来完成资源加载

 

注意:

加载不需要等到预加载完成后再调用,开发者可以在任何时候进行加载。正常加载接口会直接复用预加载过程中已经下载好的内容,缩短加载时间

 

预加载只会去 下载 必要的资源,并 不会进行资源的反序列化和初始化工作,也就不会将资源放入内存(cc.assetManager.assets)中,所以性能消耗更小,确保了游戏体验流畅

 

// 同步加载 //

 

Creator 提供的资源加载相关的 API 均为异步加载,有时候为了保持代码整洁,避免多层回调的嵌套,我们可以使用 async/await 配合 Promise 实现同步加载效果

 

加载资源:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static loadResSync(url: string, type: typeof cc.Asset) {    return new Promise((reovle, reject) => {        cc.resources.load(url, type, (error: Error, resource: cc.Asset) => {            if (error) {                reject(error);            } else {                reovle(resource);            }        });    });}

 

同步加载:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
async createSprite(url: string) {    let node = new cc.Node();    let sprite = node.addComponent(cc.Sprite);    let resource = await utils.loadResSync(url, cc.SpriteFrame) as cc.SpriteFrame;    sprite.spriteFrame = resource;
    return sprite;}
  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值