跳转到内容

LayaAir引擎的资源加载方法详解

Author: Charley

资源加载是游戏引擎的核心模块,是必须要使用的功能,LayaAir引擎提供了Loader类用于加载文本、JSON、二进制、图像等资源。

下面我们在本篇文档中彻底掌握各种资源加载的使用。

通常,采用Laya.loader.load("资源路径")方法加载单个资源,通过.then("回调方法")来处理加载后的逻辑。

Laya.loader.load(url).then((res)=> {/** 不带类型,用于常规的资源 */});

完整的脚本示例如下:

const { regClass, property } = Laya;
@regClass()
export class LoaderDemo extends Laya.Script {
onAwake(): void {
this.loadTexture("resources/image/monkey2.png", 500);//需要在resources/image放入相应的资源
this.loadTexture("https://layaair.com/3.x/demo/resources/res/apes/monkey2.png");
}
/**加载并显示图片 */
loadTexture(url: string, x: number = 0, y: number = 0): void {
Laya.loader.load(url).then((res: Laya.Texture) => {
let img = new Laya.Image();
img.texture = res;
// img.skin = url; //ui组件直接设置skin也可以
img.pos(x, y);
this.owner.addChild(img);
});
}
}

有的时候,网络资源没有后缀名,又或者,图片xxx.png并非是当成Texture使用,需要被定义为TextureCube。所以,这些时候需要通过类型进行区分。

使用方式与不带类型的基本相同,只是增加load第二个参数:类型标识字符串。

Laya.loader.load(url, type).then((res)=> {
//带类型,用于区别无后缀,或同一后缀不同作用的资源。
//例如,图片xxx.png被定义为TextureCube,使用load("xxx.png", Laya.Loader.TEXTURECUBE)。得到的是TextureCube。
});

完整的脚本示例如下:

const { regClass, property } = Laya;
@regClass()
export class LoaderDemo extends Laya.Script {
onAwake(): void {
//下面的URL未来可能会失效,仅用于示例参考
this.loadHTMLImage("https://layaair.com/3.x/demo/resources/res/apes/monkey2.png");
}
/** 加载URL无后缀资源 */
loadHTMLImage(url: string): void {
Laya.loader.load(url, Laya.Loader.IMAGE).then((res: Laya.Texture) => {
let sp = new Laya.Sprite();
sp.texture = res;
this.owner.addChild(sp);
});
}
}

常用类型如下:

引擎全局变量类型标识字符串类型说明
Laya.Loader.TEXTtext文本类型
Laya.Loader.JSONjsonJSON类型
Laya.Loader.XMLxmlXML类型
Laya.Loader.BUFFERarraybuffer二进制类型
Laya.Loader.IMAGEimage纹理类型
Laya.Loader.SOUNDsound声音类型
Laya.Loader.VIDEOvideo视频类型
Laya.Loader.ATLASatlas图集类型,加载完成后返回图集json信息(并创建图集内小图Texture)
Laya.Loader.HIERARCHYHIERARCHY层级资源,比如:场景ls文件与预制体lh文件
Laya.Loader.FONTfont位图字体类型
Laya.Loader.TTFttfTTF字体类型
Laya.Loader.MESHMESHMesh资源
Laya.Loader.MATERIALMATERIALMaterial资源
Laya.Loader.TEXTURE2DTEXTURE2DTexture2D资源
Laya.Loader.TEXTURECUBETEXTURE2DTextureCube资源
Laya.Loader.SPINESPINESpine资源

有很多时候,我们需要把大量的资源在Loading界面进行预加载,这样走完加载进度条再进游戏,就会直接显示资源,不会产生资源空白的加载等待现象。

此时,我们就需要用到多个资源加载的方式。

如果我们只是加载比较常用的资源,通过文件后缀就可以识别出来,那么省略类型的方式,肯定更为简洁。

加载多个的API和加载单个基本相同,只是加载多个时,第一个参数是资源地址数组

Laya.loader.load([url1, url2]).then((res:Array<any>)=> { /** 加载多个,不带类型,用于常规的资源 */ });

完整的脚本示例如下:

const { regClass, property } = Laya;
@regClass()
export class LoaderDemo extends Laya.Script {
onAwake(): void {
let resArr: Array<string> = [
"image/bird.jpg",
"image/cloud.png",
"https://layaair.com/3.x/demo/resources/res/apes/monkey2.png"
];
this.loadTextures(resArr);
}
/** 加载多个资源
* @param url 资源数组
*/
loadTextures(url: Array<string>): void {
Laya.loader.load(url).then((res: Array<Laya.Texture>) => {
let sp: Laya.Sprite = new Laya.Sprite();
this.owner.addChild(sp);
let i: number = 0;
//每秒重画一次
Laya.timer.loop(1000, this, () => {
i == res.length && (i = 0);
//清除sp节点的所有绘图(不含子节点)
sp.graphics.clear();
//在sp节点上重绘纹理
sp.graphics.drawTexture(res[i]);
i++;
});
});
}
}

假如,多数资源不需要带类型,有的资源又需要用类型区别,该如何使用加载方法呢?

在资源数组里,为需要带类型的传入类型,不需要的传类型的,仍然可以省略。

Laya.loader.load([url1, { url:url2, type: type }]).then((res:Array<any>)=> { /** 加载多个,按需设置类型,满足各种需要 */ });

完整的脚本示例如下:

const { regClass, property } = Laya;
@regClass()
export class LoaderDemo extends Laya.Script {
onAwake(): void {
let resArr: Array<any> = [
"image/bird.jpg",
"image/cloud.png",
{
url: "https://layaair.com/3.x/demo/resources/res/apes/monkey2.png",
type: "image"
},
{
url: "https://layaair.com/3.x/demo/resources/res/apes/monkey1.png",
type: Laya.Loader.IMAGE
}
];
this.loadTextures(resArr);
}
/** 加载多个资源
* @param url 资源数组
*/
loadTextures(url: Array<string>): void {
//加载回调返回的类型,如果是多样的,最好是any
Laya.loader.load(url).then((res: Array<any>) => {
let sp: Laya.Sprite = new Laya.Sprite();
this.owner.addChild(sp);
let i: number = 0;
//每秒重画一次
Laya.timer.loop(1000, this, () => {
i == res.length && (i = 0);
//清除sp节点的所有绘图(不含子节点)
sp.graphics.clear();
//在sp节点上重绘纹理
sp.graphics.drawTexture(res[i]);
i++;
});
});
}
}

示例上的类型,故意采用了字符串标识和引擎全局变量标识两种方式。开发者用哪一种都可以。具体参照1.2的类型标识表格。

也有的时候,加载的多资源,都需要使用类型标识,而这些类型都是同一种类型,例如,加载的全都是无后缀的URL资源。

这时,我们可以统一设置类型标识。

Laya.loader.load([url1, url2], type).then((res:Array<any>)=> { /** 加载多个,统一类型,简洁实用 */ });

完整的脚本示例如下:

const { regClass, property } = Laya;
@regClass()
export class LoaderDemo extends Laya.Script {
onAwake(): void {
let resArr: Array<any> = [
"image/bird.jpg",
"https://layaair.com/3.x/demo/resources/res/apes/monkey2.png",
"image/cloud.png",
"https://layaair.com/3.x/demo/resources/res/apes/monkey2.png",
];
this.loadTextures(resArr);
}
/** 加载多个资源
* @param url 资源数组
*/
loadTextures(url: Array<string>): void {
//加载回调返回的类型,如果不确定就any
Laya.loader.load(url, Laya.Loader.IMAGE).then((res: Array<Laya.Texture>) => {
let sp: Laya.Sprite = new Laya.Sprite();
this.owner.addChild(sp);
let i: number = 0;
//每秒重画一次
Laya.timer.loop(1000, this, () => {
i == res.length && (i = 0);
//清除sp节点的所有绘图(不含子节点)
sp.graphics.clear();
//在sp节点上重绘纹理
sp.graphics.drawTexture(res[i]);
i++;
});
});
}
}

引擎提供的load()方法加载资源,可能会在解析后做一些封装。

比如我们用load()方法加载一个json数据,需要在data里才能取到json文件里的数据。

使用load()方法,示例如下:

onEnable(): void {
const jsonPath: string = "json/bagList.json";
Laya.loader.load(jsonPath).then((json) => {
let _json = json.data;
if (_json.bagList && _json.bagList.length > 0) {
//把json数据传递给list组件的数据源属性array
this.bagList.array = _json.bagList;
}
});
}

而我们使用fetch()方法,则可以直接取到json文件里的数据。但需要注意的是,采用fetch加载的资源不会缓存,只能在加载完成的回调里使用,无法通过getRes读取加载缓存。

使用fetch()方法,示例如下:

onEnable(): void {
const jsonPath: string = "json/bagList.json";
//fetch取到的是原始数据,但没有缓存,无法用getRes获取
Laya.loader.fetch(jsonPath, "json").then((_json) => {
if (_json.bagList && _json.bagList.length > 0) {
//把json数据传递给list组件的数据源属性array
this.bagList.array = _json.bagList;
}
});
}

fetch的加载限定为以下类型

类型标识字符串资源类型
textstring
jsonany
xmlXML
arraybufferArrayBuffer
imageHTMLImageElement \ImageBitmap
soundHTMLAudioElement

在使用的时候,第二个参数那里填写对应的类型标识字符串即可。

更多fetch加载代码示例请参考《使用二进制图片》文档

Tips

除非是明确理解fetch的使用用途,否则不推荐开发者使用。

当使用load()方法或者fetch()方法加载资源时,可以使用到Option参数,例如代码:

//创建Option
let option:any = {};
option.blob = this.imgBlob;
//通过传递blob对象获得HTMLImageElement
Laya.loader.fetch("" ,"image", null, option).then((res)=>{
});

通过Option参数指定fetch()方法,传递blob对象获得HTMLImageElement

目前支持的Option参数:

export interface ILoadOptions {
type?: string; //资源类型。比如:Loader.IMAGE。
priority?: number; //(default = 0)加载的优先级,数字越大优先级越高,优先级高的优先加载。
group?: string; //分组,方便对资源进行管理。
cache?: boolean; //是否缓存
noRetry?: boolean; //是否重新尝试加载
silent?: boolean; //是否提示加载失败
useWorkerLoader?: boolean; //(default = false)是否使用worker加载(只针对IMAGE类型和ATLAS类型,并且浏览器支持的情况下生效)
constructParams?: TextureConstructParams; //图片属性,参考如下
propertyParams?: TexturePropertyParams; //纹理属性,参考如下
blob?: ArrayBuffer; //传递blob对象获得HTMLImageElement
[key: string]: any;
}
//TextureConstructParams 是 Texture2D 的构造参数元组(按位置传入,非对象字面量)
//type TextureConstructParams = ConstructorParameters<typeof Texture2D>;
TextureConstructParams = [
width: number,
height: number,
format: TextureFormat,
mipmap?: boolean,
canRead: boolean,
sRGB?: boolean,
premultiplyAlpha?: boolean,
]
TexturePropertyParams {
wrapModeU?: number,
wrapModeV?: number,
filterMode?: FilterMode,
anisoLevel?: number,
premultiplyAlpha?: boolean,
hdrEncodeFormat?: HDREncodeFormat,
}