# 资源加载

纹理、材质、模型等游戏资源,在游戏项目中,它们是一系列静态文件;在游戏运行时,它们被实例化为一系列资源实例,被 UISprite、MeshRender 等 Component 依赖,参与渲染。

资源系统做了两件事:

  1. 在游戏项目构建时,打包资源文件。
  2. 在游戏运行时,加载资源文件,并创建资源实例。

先来了解资源是如何加载的。首先需要在 project 窗口内将想要加载的资源通过 inspector 下的import setting配置为入口资源。开发者不需要在代码中处理依赖关系,更无须处理资源文件的读取,只需调用 Loader.prototype.load(),就可以获取加载并实例化后的资源。Loader 是用来加载资源的加载器 Class。资源系统的核心 API、也是 Loader 的核心 API,只有 2 个:

  • Loader.prototype.load() 用来异步加载资源。
  • Loader.prototype.getAsset() 用来同步获取已下载的资源。

Loader.prototype.load() 会返回一个 LoadTask,可以监听加载任务的结果,也可以中断它。Loader.load()的第一个参数为资源相对于游戏根目录/assets/的路径。

假设 SpriteFrame 的绝对路径为 游戏根目录/assets/Assets/image.spriteframe,那么它相对于 游戏根目录/assets/ 的路径为 Assets/image.spriteframe

// 加载一个prefab
const task = engine.loader.load("resource/Aircraft.prefab");
task.promise.then((prefab) => {
  console.log(prefab)
}).catch((error) => {
  console.error(error);
})
// 中断任务,task.promise 的 catch 会执行
task.abort();

资源加载成功后,如果想要以同步调用的方式获取资源实例,可以调用 Loader.prototype.getAsset()。

// 如果尚未加载、加载未完成,会抛出错误
try {
  const spriteFrame = engine.loader.getAsset("resource/Aircraft.prefab");
}
catch (e) {
  console.error(e)
}

# LoadTask

engine.loader.load返回的是一个 LoadTask 实例,LoadTask 是返回给业务层的下载任务类,是一个“一次性”的类。从实例化到所依赖的 资源包 全部完成加载(成功或失败),状态不再改变。

比如可以使用 LoadTask.progress 来获取进度,通过abort()来终止任务。

# 加载器的额外选项

在使用Loader.load()加载资源时,可以在第二个参数处,传入额外的下载选项。

常用选项 类型 描述
httpRetryCount number 下载失败后的重试次数。
httpPriority number 下载优先级。
preload boolean 预加载,下载完毕后不读取文件。
raw boolean 加载原始文件内容。
engine.loader.load("resource/Aircraft.prefab", {
  httpRetryCount: 2,
  priority: 10
}).promise.then((spriteFrame) => {
  console.log(spriteFrame)
})

# 全局重试次数

如果不想每次load()都传递额外参数,可以直接在全局配置里设定全局重试次数。

在工具中打开Project Setting标签 >> 游戏配置 >> globalSetting >> globalHTTPRetry

# 资源下载优化

为了让用户能更快的进入游戏,开发者也可以通过以下几种方式优化自己的游戏逻辑。

提前下载:对于首次进入游戏的用户,一般会先进入 loading 界面,那么可以在 loading 界面就可以提前开始下载游戏资源,下载会在多线程 worker 中运行,不会对主进程造成过多影响。

按需下载:对于用户不即时需要的游戏资源没有必要立刻下载好,可以在用到的时候再下载,这里需要开发者针对自己的场景做优化。

烘培流式加载场景:小游戏针对大型场景实现的按距离逐步下载场景资源的能力,实现超大地图秒开。可以查看文档了解详情。