Laya.Loader 使用说明

目录

  1. 概述
  2. 资源类型
  3. 核心方法
  4. 属性配置
  5. 加载流程
  6. 使用示例
  7. 最佳实践
  8. 常见问题
  9. 总结

概述

Laya.Loader 是 LayaAir 引擎的资源加载管理类,负责加载和管理各类游戏资源,包括图片、音频、JSON、XML、二进制数据、图集、3D 模型等。

核心特点

  • 单例模式:通过 Laya.loader 单例访问,不要手动实例化
  • 统一接口:提供统一的资源加载接口,支持多种资源类型
  • 自动缓存:加载的资源自动缓存,便于后续使用
  • 分组管理:支持资源分组,便于批量管理和释放
  • 进度回调:支持加载进度监听
  • 错误处理:支持加载失败重试和错误回调

基本用法

// 加载单个资源
Laya.loader.load("res/image.png").then(() => {
    const texture = Laya.loader.getRes("res/image.png");
    console.log("资源加载完成");
});

// 加载多个资源
Laya.loader.load([
    "res/image1.png",
    "res/image2.png",
    "res/data.json"
]).then(() => {
    console.log("所有资源加载完成");
});

资源类型

类型常量对照表

常量 说明 返回类型 使用场景
Laya.Loader.IMAGE 图片资源 Texture 精灵图片、UI 图标
Laya.Loader.TEXTURE2D 2D 纹理 Texture2D 3D 材质纹理、天空盒
Laya.Loader.TEXTURECUBE 立方体纹理 TextureCube 天空盒、环境反射
Laya.Loader.ATLAS 图集资源 AtlasResource 精灵图集、UI 图集
Laya.Loader.JSON JSON 数据 Object 配置文件、游戏数据
Laya.Loader.XML XML 数据 XMLDocument 配置文件
Laya.Loader.TEXT 纯文本 string 脚本文件、文本数据
Laya.Loader.BUFFER 二进制数据 ArrayBuffer 自定义二进制格式
Laya.Loader.SOUND 音频资源 Sound 背景音乐、音效
Laya.Loader.VIDEO 视频资源 VideoTexture 视频播放
Laya.Loader.FONT 位图字体 BitmapFont 艺术字体
Laya.Loader.TTF TTF 字体 Object 矢量字体
Laya.Loader.SPINE Spine 骨骼动画 SpineTemplet Spine 动画
Laya.Loader.MATERIAL 材质资源 Material 3D 材质
Laya.Loader.MESH 网格资源 Mesh 3D 模型网格
Laya.Loader.HIERARCHY 场景/预设 Node 3D 场景、预制体
Laya.Loader.ANIMATIONCLIP 动画剪辑 AnimationClip 3D 动画

类型选择建议

// 2D 精灵 - 使用 IMAGE
Laya.loader.load("res/sprite.png", Laya.Loader.IMAGE);

// 3D 材质纹理 - 使用 TEXTURE2D
Laya.loader.load("res/texture.jpg", Laya.Loader.TEXTURE2D);

// 天空盒 - 使用 TEXTURECUBE
Laya.loader.load("res/skybox.jpg", Laya.Loader.TEXTURECUBE);

// 图集 - 使用 ATLAS
Laya.loader.load("res/ui.atlas", Laya.Loader.ATLAS);

// 配置文件 - 使用 JSON
Laya.loader.load("res/config.json", Laya.Loader.JSON);

// 音频 - 使用 SOUND
Laya.loader.load("res/bgm.mp3", Laya.Loader.SOUND);

// 3D 场景 - 使用 HIERARCHY
Laya.loader.load("res/scene.lh", Laya.Loader.HIERARCHY);

核心方法

重要说明

  • 静态方法:使用 Laya.Loader.methodName() 调用
  • 实例方法:使用 Laya.loader.methodName() 调用(Laya.loader 是单例对象)

实例方法

load()

加载资源(支持单个或批量)。这是最常用的资源加载方法。

load(
    url: string | ILoadURL | ILoadURL[],
    type?: string | ILoadOptions,
    complete?: Handler,
    progress?: ProgressCallback
): Promise<any>
参数 类型 说明
url string | ILoadURL | ILoadURL[] 资源 URL 或资源数组
type string | ILoadOptions 资源类型或加载配置
complete Handler 完成回调(可选)
progress ProgressCallback 进度回调(可选)

返回: Promise<any> - 加载完成后 resolve

示例:

// 方式1: Promise 方式
Laya.loader.load("res/image.png").then(() => {
    console.log("加载完成");
});

// 方式2: 回调方式
Laya.loader.load(
    "res/image.png",
    Laya.Handler.create(this, this.onComplete),
    Laya.Handler.create(this, this.onProgress, null, false)
);

// 方式3: 批量加载
Laya.loader.load([
    "res/image1.png",
    "res/image2.png",
    { url: "res/data.json", type: Laya.Loader.JSON }
]).then(() => {
    console.log("批量加载完成");
});

// 方式4: 使用配置对象
Laya.loader.load(
    "res/image.png",
    { type: Laya.Loader.IMAGE, group: "scene1" }
);

getRes()

获取已加载的资源(实例方法)。

getRes(url: string, type?: string): any
参数 类型 说明
url string 资源 URL
type string 资源类型(可选)

返回: any - 资源对象,未加载则返回 null

示例:

// 获取图片纹理
const texture = Laya.loader.getRes("res/image.png");

// 获取 JSON 数据
const jsonData = Laya.loader.getRes("res/data.json");

// 获取图集
const atlas = Laya.loader.getRes("res/ui.atlas");

clearRes()

清除指定资源缓存(实例方法)。

clearRes(url: string): void

示例:

// 清除单个资源
Laya.loader.clearRes("res/image.png");

cacheRes()

手动缓存资源(实例方法)。

cacheRes(url: string, data: any, type?: string): void

示例:

// 手动缓存自定义数据
const playerData = { name: "Player", hp: 100, mp: 50 };
Laya.loader.cacheRes("data/player.json", playerData, Laya.Loader.JSON);

// 之后可以通过 getRes 获取
const data = Laya.loader.getRes("data/player.json");

cancelLoadByUrl()

取消指定 URL 的加载。

cancelLoadByUrl(url: string): void

示例:

// 取消加载
Laya.loader.cancelLoadByUrl("res/large-file.png");

clearUnLoaded()

清除所有未完成的加载任务。

clearUnLoaded(): void

示例:

// 取消所有待加载任务
Laya.loader.clearUnLoaded();

cancelLoadByUrls()

根据地址集合取消多个资源的加载。

cancelLoadByUrls(urls: string[]): void

示例:

Laya.loader.cancelLoadByUrls([
    "res/image1.png",
    "res/image2.png"
]);

clearTextureRes()

销毁纹理使用的图片资源,保留 Texture 壳。

clearTextureRes(url: string): void

说明:相比 clearResclearTextureRes 只清理纹理内的图片资源,不销毁 Texture 对象,再次使用时会自动恢复。

示例:

// 只清理纹理图片资源
Laya.loader.clearTextureRes("res/large-texture.png");

fetch()

从指定 URL 下载底层资源(不解析,不缓存)。

fetch<K extends keyof ContentTypeMap>(
    url: string,
    contentType: K,
    onProgress?: ProgressCallback,
    options?: Readonly<ILoadOptions>
): Promise<ContentTypeMap[K]>

示例:

// 下载文本(不缓存)
Laya.loader.fetch("res/data.txt", "text").then((text: string) => {
    console.log(text);
});

// 下载二进制数据(不缓存)
Laya.loader.fetch("res/data.bin", "arraybuffer").then((buffer: ArrayBuffer) => {
    console.log(buffer);
});

loadPackage()

加载小游戏子包。

loadPackage(path: string, onProgress?: ProgressCallback): Promise<boolean>
参数 类型 说明
path string 子包路径
onProgress ProgressCallback 进度回调(可选)

返回: Promise<boolean> - 加载成功返回 true

示例:

// 加载子包
Laya.loader.loadPackage("subpackage1").then((success) => {
    if (success) {
        console.log("子包加载成功");
    }
});

// 带进度回调
Laya.loader.loadPackage("subpackage1", (progress: number) => {
    console.log("子包加载进度:", progress);
}).then((success) => {
    console.log("加载完成");
});

静态方法

createNodes()

从资源创建节点树(主要用于 3D 场景)。

static createNodes<T extends Node>(url: string): T

示例:

// 创建 3D 场景节点
const scene = Laya.Loader.createNodes<Laya.Scene3D>("res/scene.lh");
Laya.stage.addChild(scene);

// 创建 3D 相机
const camera = Laya.Loader.createNodes<Laya.Camera>("res/camera.lh");
scene.addChild(camera);

getRes()

获取已加载的资源(静态方法)。

static getRes(url: string, type?: string): any

示例:

// 使用静态方法获取资源
const texture = Laya.Loader.getRes("res/image.png");

clearRes()

清除指定资源缓存(静态方法)。

static clearRes(url: string, checkObj?: any): void

示例:

// 使用静态方法清除资源
Laya.Loader.clearRes("res/image.png");

clearResByGroup()

按分组清除资源。

static clearResByGroup(group: string): void

示例:

// 清除场景1的所有资源
Laya.Loader.clearResByGroup("scene1");

setGroup()

设置资源分组。

static setGroup(url: string, group: string): void

示例:

// 设置资源分组
Laya.Loader.setGroup("res/scene1/bg.png", "scene1");
Laya.Loader.setGroup("res/scene1/enemy.png", "scene1");

// 清理时可以按组释放
Laya.Loader.clearResByGroup("scene1");

cacheRes()

手动缓存资源(静态方法)。

static cacheRes(url: string, data: any, type?: string): void

示例:

// 使用静态方法缓存数据
const playerData = { name: "Player", hp: 100, mp: 50 };
Laya.Loader.cacheRes("data/player.json", playerData, Laya.Loader.JSON);

getAtlas()

获取指定资源地址的图集资源。

static getAtlas(url: string): AtlasResource

示例:

const atlas = Laya.Loader.getAtlas("res/ui.atlas");

getTexture2D()

获取 Texture2D 资源。

static getTexture2D(url: string): Texture2D

示例:

const texture2D = Laya.Loader.getTexture2D("res/texture.png");

getBaseTexture()

获取基础纹理资源。

static getBaseTexture<T extends BaseTexture>(url: string): T

示例:

const baseTexture = Laya.Loader.getBaseTexture<Laya.Texture2D>("res/texture.png");

getURLInfo()

根据 URL 获取 URL 信息。

static getURLInfo(url: string, type?: string, maybeType?: string): URLInfo

示例:

const urlInfo = Laya.Loader.getURLInfo("res/image.png", Laya.Loader.IMAGE);

registerLoader()

注册自定义资源加载器。

static registerLoader(
    exts: string[],
    cls: new () => IResourceLoader,
    type?: string,
    hotReloadable?: boolean
): void

示例:

// 注册自定义格式加载器
Laya.Loader.registerLoader(
    ["custom"],
    CustomResourceLoader,
    Laya.Loader.TEXT,
    true
);

warn()

输出警告信息。

static warn(msg: string, err?: any): void

warnFailed()

警告加载失败。

static warnFailed(url: string, err?: any, initiatorUrl?: string): void

属性配置

加载配置属性

属性 类型 默认值 说明
maxLoader number 5 最大并发加载数
retryNum number 1 加载失败重试次数
retryDelay number 0 重试延迟时间(毫秒)
loading boolean false 是否有加载任务正在进行

示例:

// 设置最大并发数为 10
Laya.loader.maxLoader = 10;

// 设置重试 3 次
Laya.loader.retryNum = 3;

// 设置重试延迟 1 秒
Laya.loader.retryDelay = 1000;

// 检查是否有加载任务
if (Laya.loader.loading) {
    console.log("资源加载中...");
}

加载流程

完整加载流程

// 执行顺序:
// 1. 开始加载资源
// 2. 进度回调(可选)
// 3. 资源解析和缓存
// 4. 完成回调 / Promise resolve

Laya.loader.load(
    "res/image.png",
    Laya.Handler.create(this, () => {
        console.log("4. 加载完成");
    }),
    Laya.Handler.create(this, (progress: number) => {
        console.log("2. 进度:", progress);
    }, null, false)
).then(() => {
    console.log("4. Promise resolve");
});

推荐的加载模式

export class ResourceManager {
    private resources: string[] = [
        "res/ui/common.atlas",
        "res/character/player.png",
        "res/audio/bgm.mp3"
    ];

    // 模式1: Promise 链式调用
    loadResources(): Promise<void> {
        return Laya.loader.load(this.resources).then(() => {
            console.log("资源加载完成");
            this.onResourcesLoaded();
        });
    }

    // 模式2: async/await
    async loadResourcesAsync(): Promise<void> {
        await Laya.loader.load(this.resources);
        console.log("资源加载完成");
        this.onResourcesLoaded();
    }

    // 模式3: 进度回调
    loadWithProgress(onProgress: (progress: number) => void): void {
        Laya.loader.load(
            this.resources,
            Laya.Handler.create(this, () => {
                console.log("加载完成");
                this.onResourcesLoaded();
            }),
            Laya.Handler.create(this, (progress: number) => {
                onProgress(progress);
            }, null, false)
        );
    }

    private onResourcesLoaded(): void {
        // 资源已缓存,可以使用
        const atlas = Laya.loader.getRes("res/ui/common.atlas");
        console.log("图集:", atlas);
    }
}

使用示例

示例1: 加载图片并显示

export class LoadImageExample {
    constructor() {
        this.loadAndShow();
    }

    private loadAndShow(): void {
        Laya.loader.load("res/apes/monkey2.png", Laya.Loader.IMAGE).then(() => {
            const texture = Laya.loader.getRes("res/apes/monkey2.png");
            const sprite = new Laya.Sprite();
            sprite.graphics.drawTexture(texture, 0, 0);
            sprite.pos(
                (Laya.stage.width - texture.width) / 2,
                (Laya.stage.height - texture.height) / 2
            );
            Laya.stage.addChild(sprite);
        });
    }
}

示例2: 批量预加载与进度显示

export class PreloadExample {
    private progressText: Laya.Text;

    constructor() {
        this.createProgressUI();
        this.preloadResources();
    }

    private createProgressUI(): void {
        this.progressText = new Laya.Text();
        this.progressText.fontSize = 24;
        this.progressText.color = "#FFFFFF";
        this.progressText.pos(
            Laya.stage.width / 2,
            Laya.stage.height / 2
        );
        this.progressText.text = "加载中: 0%";
        Laya.stage.addChild(this.progressText);
    }

    private preloadResources(): void {
        const resources = [
            "res/scene/bg.png",
            "res/character/player.png",
            "res/ui/button.png",
            "res/audio/bgm.mp3"
        ];

        Laya.loader.load(
            resources,
            Laya.Handler.create(this, this.onComplete),
            Laya.Handler.create(this, this.onProgress, null, false)
        );
    }

    private onProgress(progress: number): void {
        this.progressText.text = `加载中: ${Math.round(progress * 100)}%`;
    }

    private onComplete(): void {
        this.progressText.text = "加载完成!";
        Laya.timer.once(1000, this, () => {
            this.progressText.removeSelf();
            this.startGame();
        });
    }

    private startGame(): void {
        // 资源已缓存
        const bgTexture = Laya.loader.getRes("res/scene/bg.png");
        console.log("游戏开始,资源已就绪");
    }
}

示例3: 图集动画

export class AtlasAnimationExample {
    constructor() {
        Laya.loader.load("res/fighter/fighter.json", Laya.Loader.ATLAS).then(() => {
            this.createAnimation();
        });
    }

    private createAnimation(): void {
        const animation = new Laya.Animation();
        animation.loadAtlas("res/fighter/fighter.json");
        animation.interval = 30;
        animation.index = 1;
        animation.play();

        const bounds = animation.getGraphicBounds();
        animation.pivot(bounds.width / 2, bounds.height / 2);
        animation.pos(Laya.stage.width / 2, Laya.stage.height / 2);

        Laya.stage.addChild(animation);
    }
}

示例4: 资源分组管理

export class ResourceGroupExample {
    private sceneResources: Record<string, string[]> = {
        scene1: ["res/scene1/bg.png", "res/scene1/enemy.png"],
        scene2: ["res/scene2/bg.png", "res/scene2/enemy.png"]
    };

    constructor() {
        this.setupGroups();
    }

    private setupGroups(): void {
        // 设置场景1资源分组(静态方法)
        Laya.Loader.setGroup("res/scene1/bg.png", "scene1");
        Laya.Loader.setGroup("res/scene1/enemy.png", "scene1");

        // 设置场景2资源分组
        Laya.Loader.setGroup("res/scene2/bg.png", "scene2");
        Laya.Loader.setGroup("res/scene2/enemy.png", "scene2");

        // 加载场景1
        this.loadScene("scene1");
    }

    private loadScene(sceneName: string): void {
        Laya.loader.load(this.sceneResources[sceneName]).then(() => {
            console.log(`${sceneName} 加载完成`);
        });
    }

    public changeScene(fromScene: string, toScene: string): void {
        // 清理旧场景资源(静态方法)
        Laya.Loader.clearResByGroup(fromScene);
        // 加载新场景
        this.loadScene(toScene);
    }
}

示例5: 加载 3D 场景

export class Load3DSceneExample {
    constructor() {
        Laya.init(0, 0).then(() => {
            this.load3DResources();
        });
    }

    private load3DResources(): void {
        const resources = [
            "res/threeDimen/scene/ground.lh",
            "res/threeDimen/scene/camera.lh"
        ];

        Laya.loader.load(resources).then(() => {
            this.createScene();
        });
    }

    private createScene(): void {
        const scene = new Laya.Scene3D();
        Laya.stage.addChild(scene);

        const ground = Laya.Loader.createNodes<Laya.MeshSprite3D>("res/threeDimen/scene/ground.lh");
        scene.addChild(ground);

        const camera = Laya.Loader.createNodes<Laya.Camera>("res/threeDimen/scene/camera.lh");
        scene.addChild(camera);
    }
}

示例6: 手动缓存资源

export class ManualCacheExample {
    constructor() {
        this.cacheCustomData();
    }

    private cacheCustomData(): void {
        // 从其他方式获取的数据(WebSocket、LocalStorage 等)
        const playerData = {
            name: "Player",
            level: 10,
            hp: 1000,
            mp: 500
        };

        // 手动缓存到 Loader
        Laya.loader.cacheRes("data/player.json", playerData, Laya.Loader.JSON);

        // 之后可以通过 getRes 获取
        const data = Laya.loader.getRes("data/player.json");
        console.log(data); // { name: "Player", level: 10, hp: 1000, mp: 500 }
    }
}

示例7: 错误处理

export class ErrorHandleExample {
    constructor() {
        // 配置重试策略
        Laya.loader.retryNum = 3;
        Laya.loader.retryDelay = 1000;

        // 监听错误事件
        Laya.loader.on(Laya.Event.ERROR, this, this.onError);

        this.loadWithError();
    }

    private loadWithError(): void {
        const urls = [
            "res/exists.png",
            "res/not-exist.png"
        ];

        Laya.loader.load(urls).then(() => {
            console.log("加载完成");
        });
    }

    private onError(err: string): void {
        console.error("加载失败:", err);

        // 显示错误提示
        const tip = new Laya.Text();
        tip.text = "资源加载失败,请检查网络";
        tip.fontSize = 20;
        tip.color = "#FF0000";
        tip.pos(Laya.stage.width / 2, Laya.stage.height / 2);
        Laya.stage.addChild(tip);
    }

    public destroy(): void {
        Laya.loader.off(Laya.Event.ERROR, this, this.onError);
    }
}

最佳实践

1. 使用单例访问

推荐:

// 使用单例
Laya.loader.load("res/image.png");
const tex = Laya.loader.getRes("res/image.png");

不推荐:

// 不要手动实例化
const loader = new Laya.Loader(); // 会导致问题

2. 批量加载

推荐:

// 批量加载,减少请求次数
Laya.loader.load([
    "res/ui/common.atlas",
    "res/character/player.png",
    "res/audio/bgm.mp3"
]);

不推荐:

// 逐个加载,效率低
Laya.loader.load("res/ui/common.atlas").then(() => {
    Laya.loader.load("res/character/player.png").then(() => {
        Laya.loader.load("res/audio/bgm.mp3");
    });
});

3. 资源分组

推荐:

// 按场景分组,便于管理(静态方法)
Laya.Loader.setGroup("res/scene1/bg.png", "scene1");
Laya.Loader.setGroup("res/scene1/enemy.png", "scene1");

// 切换场景时清理
Laya.Loader.clearResByGroup("scene1");

4. 指定资源类型

推荐:

// 明确指定类型,提高解析效率
Laya.loader.load("res/data.json", Laya.Loader.JSON);

⚠️ 可以:

// 不指定类型,引擎自动识别(可能稍慢)
Laya.loader.load("res/data.json");

5. 进度回调

推荐:

// 使用 Promise 配合 Handler
Laya.loader.load(
    resources,
    Laya.Handler.create(this, this.onComplete),
    Laya.Handler.create(this, this.onProgress, null, false)
);

6. 资源释放

推荐:

// 及时释放不需要的资源(实例方法)
Laya.loader.clearRes("res/old-scene/bg.png");

// 或按组释放(静态方法)
Laya.Loader.clearResByGroup("old-scene");

常见问题

Q1: 如何判断资源已加载?

A: 使用 getRes() 检查返回值。

const texture = Laya.loader.getRes("res/image.png");
if (texture) {
    console.log("资源已加载");
} else {
    console.log("资源未加载");
}

Q2: 如何取消加载?

A: 使用 cancelLoadByUrl()clearUnLoaded()

// 取消单个资源
Laya.loader.cancelLoadByUrl("res/large-file.png");

// 取消所有待加载
Laya.loader.clearUnLoaded();

Q3: IMAGE 和 TEXTURE2D 有什么区别?

A:

  • IMAGE: 用于 2D 精灵,返回 Texture 对象
  • TEXTURE2D: 用于 3D 材质,返回 Texture2D 对象
// 2D 精灵
Laya.loader.load("res/sprite.png", Laya.Loader.IMAGE);

// 3D 材质
Laya.loader.load("res/texture.jpg", Laya.Loader.TEXTURE2D);

Q4: 如何实现重试机制?

A: 设置 retryNumretryDelay

Laya.loader.retryNum = 3;       // 重试 3 次
Laya.loader.retryDelay = 1000;   // 延迟 1 秒

Laya.loader.load("res/unstable.png");

Q5: 如何监控所有资源加载完成?

A: 使用 loading 属性或 Promise。

// 方式1: 检查 loading 属性
if (!Laya.loader.loading) {
    console.log("所有加载完成");
}

// 方式2: 使用 Promise
Laya.loader.load(resources).then(() => {
    console.log("所有加载完成");
});

Q6: 图集加载后如何使用?

A: 使用 getAtlas() 或直接通过 URL 获取子纹理。

Laya.loader.load("res/ui.atlas", Laya.Loader.ATLAS).then(() => {
    // 获取图集
    const atlas = Laya.loader.getRes("res/ui.atlas");

    // 获取子纹理
    const buttonTexture = Laya.loader.getRes("res/ui/button.png");
});

Q7: 如何预加载资源但不立即使用?

A: 加载后资源会自动缓存,需要时调用 getRes()

// 启动时预加载
Laya.loader.load(["res/ui.atlas", "res/audio/bgm.mp3"]);

// 后续使用
const atlas = Laya.loader.getRes("res/ui.atlas");
const bgm = Laya.loader.getRes("res/audio/bgm.mp3");

总结

关键要点:

  1. 使用单例: 通过 Laya.loader 访问
  2. 批量加载: 合并资源请求,提高效率
  3. 资源分组: 按场景/功能分组,便于管理
  4. 指定类型: 明确指定资源类型,提高解析效率
  5. 及时释放: 不用的资源及时清理,避免内存泄漏
  6. 错误处理: 配置重试机制,监听错误事件
  7. 进度监听: 使用进度回调,提升用户体验
  8. 预加载策略: 关键资源预加载,非关键资源按需加载
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐