cocosCreator 之 resources(一)

版本: v3.4.0

参考: resources资源加载


简介

项目中所有需要通过脚本动态加载的资源可以使用resources.load接口进行加载,且资源相关一定要放在assets\resources的目录或子目录下。

assets\resources目录下的资源要注意: 如果只是依赖于外部的资源,而不需要被resources.load接口调用,就不要放在该目录下。

这样会导致问题:

  • 增大config.json的大小
  • 项目中无用的资源,无法在构建的过程中自动剔除
  • 构建过程中,JSON的自动合并策略将受到影响,无法尽可能的合并零碎的JSON。

关于resource.load动态加载资源,它支持多种类型的添加:

  • 加载Prefab预制体资源
// 加载prefab某个UI页面
resources.load("prefab/shopLayer", Prefab, (err, prefab) => {
    
    
    if(err) {
    
    
      console.log("resource load failed:" + err.message);
      return;
    }
  	const node = instantiate(prefab);
  	node.parent = this.node;
});
  • 加载AnimationClip动画资源
// 加载 AnimationClip
resources.load("test assets/anim", AnimationClip, (err, clip) => {
    
    
    this.node.getComponent(Animation).addClip(clip, "anim");
});
  • 加载图片的SpriteFrameTexture2DSpriteAtlas图集资源
/*
* 图片相关,在creator中它的格式为ImageAsset,它一般会生成格式:SpriteFrame和Texture
* 动态加载要在路径的后方去增加SpriteFrame或Texture的格式,否则将默认为ImageAsset格式
*/

// 通过加载SpriteFrame改变图片
const path = "textures/gold/spriteFrame";
resources.load(path, SpriteFrame, (err, spriteFrame) => {
    
    
  	const sprite = this.node.getComponent(Sprite);
    sprite.spriteFrame = spriteFrame;
});
// 通过加载Texture2D来改变图片
const path = "textures/gold/texture";
resources.load(path, Texture2D, (err: any, texture: Texture2D) => {
    
    
    const spriteFrame = new SpriteFrame();
    spriteFrame.texture = texture;
  	const sprite = this.node.getComponent(Sprite);
    sprite.spriteFrame = spriteFrame;
});
// 通过图集来改变改变图片
const path = "textures/fruit"
resources.load(path, SpriteAtlas, (err, atlas) => {
    
    
  	// 获取精灵帧
    const frame = atlas.getSpriteFrame('fruit_0');
    sprite.spriteFrame = frame;
});
  • 加载模型的MeshMeterialSkeleton资源
// 加载模型中的网格资源
resources.load("Monster/monster", Mesh, (err, mesh) => {
    
    
    this.node.getComponent(MeshRenderer).mesh = mesh;
});

// 加载模型中的材质资源
resources.load("Monster/monster-effect", Material, (err, material) => {
    
    
    this.node.getComponent(MeshRenderer).material = material;
});

// 加载模型中的骨骼
resources.load("Monster/Armature", Skeleton, (err, skeleton) => {
    
    
    this.node.getComponent(SkinnedMeshRenderer).skeleton = skeleton;
});

reources常用接口

关于reources的接口实现,通过cc.d.ts可以看到:

// resources 是一个 bundle,用于管理所有在 assets/resources 下的资源
export const resources: AssetManager.Bundle;

Bundle可以简单理解为资源模块化,将贴图,脚本,场景等资源划分为一个Bundle。

有助于在游戏运行的过程中,通过加载不同的Bundle 减少启动是需要加载的资源数量。

更多参考:Asset Bundle

关于AssetManager需要注意:

// 通过cc.assetManager调用
export const assetManager: AssetManager;
export class AssetManager {
    
    };
// 使用的命名空间
export namespace AssetManager {
    
    
  // 管线能执行任务达到某个效果
	export class Pipeline {
    
    }
  // 任务用于在管线中运行以达成某种效果
  export class Task {
    
    }
  // 请求的相关信息集合
  export class RequestItem {
    
    }
  // 一个包含一定数量资源(包括场景)的包,你可以加载,预加载,释放此包内的资源 
  export class Bundle {
    
    }
  // 内置 bundle
  export enum BuiltinBundleName {
    
    
    RESOURCES = "resources",
    MAIN = "main",
    START_SCENE = "start-scene"
  }
}

对于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() 释放此包中的所有资源

接口当中所提到的onProgressonComplete是回调接口, 他们对应的主要参数:

/*
onProgress 加载进度改变时的回调
finished: 已完成的加载数目
total: 需要加载的总数目
item: 请求项相关
*/
onProgress: __private.cocos_core_asset_manager_shared_ProgressCallback | null
export type cocos_core_asset_manager_shared_ProgressCallback = (finished: number, total: number, item: AssetManager.RequestItem) => void;
/*
onComplete 加载完成回调
err: 错误信息相关,包含name, message, stack等
data: 对应的item数据
*/

onComplete: __private.cocos_core_asset_manager_shared_CompleteCallbackWithData<T>
export type cocos_core_asset_manager_shared_CompleteCallbackWithData<T = any> = (err: Error | null, data: T) => void;

interface Error {
    
    
    name: string;
    message: string;
    stack?: string;
}

对于load、preload、loadDir、preloadDir、loadScene、preloadScene 等,均提供了多种不同的函数重载的实现, 就不在重复赘述了。


预加载

在项目当中,使用resources.load动态加载资源,某些时候会出现卡顿。

我们可以调用preload、preloadDir等,对内置Bundle下的resources资源进行预加载,它的特点是:

  • 只会下载资源,不会对资源进行解析和初始化操作
  • 预加载的优先度很低,当多个资源等待下载的过程中,预加载相关会放在最后
  • 预加载属于异步加载

需要注意的是:预加载资源,并不影响我们使用正常加载接口。

简单的实例:

// 预加载resources目录下某个子目录
resource.preloadDir("prefab", Prefab, (err, data) => {
    
    });

// 预加载某个资源
resources.preload("music/background", AudioClip, (err, data) => {
    
    });

// 预加载某个SpriteFrame
const url = 'textures/bg_1/spriteFrame'
resources.preload(url, SpriteFrame);
resources.load(url, SpriteFrame, (err, spriteFrame) => {
    
    
    this.node.getComponent(Sprite).spriteFrame = spriteFrame;
});

以Loading页面的加载进度为例,假设我们想加载所有的resources资源,可以:

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 {
    
    
    // 通过cc.assetManager获取内置的resources包
    cosnt bundle = assetManager.resources;
    // 获取resources下的所有资源信息
    const resourcePaths = bundle.getDirWithPath("./");
    // 获取文件最大个数
    const maxLen = resourcePaths.length;
    // 设置进度相关
    this.desc.string = ""
    this.loadBar.progress = 0;

    // 通过资源信息表获取路径,使用preload进行预加载
    let loadCount = 0;
    for(let i = 0; i < maxLen; ++i) {
    
    
      const uuid = resourcePaths[i].uuid;
      const path = resourcePaths[i].path;
      resources.preload(path, (err: Error | null, data: any) => {
    
    
      	if (err) {
    
    
          console.log("preload failed: " + err.message);
          return;
        }
        loadCount++;
        // 通过文本显示加载的文件
        this.desc.string = `加载${
      
      path}`
        // 进度条改变
        this.loadBar.progress = clamp01(loadCount/maxLen);  
      })
    }
  }
}

关于resources Bundle的获取,主要通过cc.assetManager来获取

// 通过变量
let resourceBundle = assetManager.resources;
let mainBundle = assetManager.main;
// 使用getBundle来获取
let resourceBundle = assetManager.getBundle("resources");
// 通过集合来获取
let bundle = assetManager.bundles.get("resources");

简单的写下这个,就当是对代码有个简单的理解吧。


猜你喜欢

转载自blog.csdn.net/qq_24726043/article/details/132125262