# 资源系统
纹理、材质、模型等游戏资源,在游戏项目中,它们是一系列静态文件;在游戏运行时,它们被实例化为一系列资源实例,被 UISprite、MeshRender 等 Component 依赖,参与渲染。
资源系统做了两件事:
- 在游戏项目构建时,打包资源文件。
- 在游戏运行时,加载资源文件,并创建资源实例。
先来了解资源是如何加载的。Loader 是用来加载资源的加载器 Class。资源系统的核心 API、也是 Loader 的核心 API,只有 2 个:
- Loader.prototype.load() 用来异步加载资源。
- Loader.prototype.getAsset() 用来同步获取资源。
engine.loader 是 Loader 在 engine 上的单例对象,你需要在在 engine.loader 上调用 .load() 和 .getAsset()。
Loader.prototype.load() 会返回一个 LoadTask,可以监听加载任务的结果,也可以中断它。
// 假设 SpriteFrame 的资源 id 是 1c8d38F-df4ac6I-01e81fL-345ee9E
const task = engine.loader.load("1c8d38F-df4ac6I-01e81fL-345ee9E");
task.promise.then((spriteFrame) => {
console.log(spriteFrame)
}).catch((error) => {
console.error(error);
})
// 中断任务,task.promise 的 catch 会执行
task.abort();
httpRetryCount 可以指定下载资源文件重试次数,priority 可以指定下载资源文件的优先级。
在 Loader 内部对并发的下载数量有限制,priority 更高的资源加载涉及到的文件下载会被优先发起下载。
engine.loader.load("1c8d38F-df4ac6I-01e81fL-345ee9E", {
httpRetryCount: 2,
priority: 10
}).promise.then((spriteFrame) => {
console.log(spriteFrame)
})
资源加载成功后,如果想要以同步调用的方式获取资源实例,可以调用 Loader.prototype.getAsset()。
// 如果尚未加载、加载未完成,会抛出错误
try {
const spriteFrame = engine.loader.getAsset("1c8d38F-df4ac6I-01e81fL-345ee9E");
}
catch (e) {
console.error(e)
}
资源系统有 16 种资源:
类型 | 说明 |
---|---|
Scene | 场景 |
Prefab | 预制 |
Texture2D | 2d 纹理 |
TextureCube | 立方体纹理 |
RenderTexture | 可渲染纹理 |
SpriteFrame | 精灵帧 |
Mesh | 网格 |
Material | 材质 |
Effect | 特效 |
Font | 字体 |
BitmapFont | 位图字体 |
AnimationClip | 动画片段 |
AnimatorController | 动画状态机 |
Avatar | 骨骼 |
Variant | shader 代码。包含 vertex 代码和 fragment 代码,在渲染用到该 shader 时,shader 代码会被编译成 shader 对象并参与渲染。 |
Raw | 纯文件。不被资源系统理解,而是游戏自定义的资源。比如游戏关卡的配置表等。 |
Script | .js 文件。加载时会通过 require() 方法被执行。 |
资源是一个抽象概念,一个资源可能涉及一个或者多个文件。在运行时,资源系统根据这一个或者多个文件的内容,创建资源实例。
以 Texture2D 为例,一个 Texture2D 涉及两个文件:
- 包含 pixelFormat、wrapU、wrapV 等 Texture2D 配置信息的描述文件 .texture2d,格式为 JSON。
- 图片文件,可能是 .png,或者是压缩纹理 .astc .etc2。
.texture2d 文件依赖图片文件。在 .texture2d 的配置信息中,file.src 字段记录了对图片文件的引用,这个引用是一个唯一的 id。在资源系统中,每个文件和资源都有一个 id。
文件之间存在依赖关系,资源之间也存在依赖关系。比如一张 2048x2048 的图片上可以切出多个 SpriteFrame,那么这多个 SpriteFrame 就都依赖一个 2048x2048 的 Texture2D。
SpriteFrame 有着如下的依赖链路:SpriteFrame -> Texture2D -> Texture2D 描述文件 -> 图片文件,在加载 SpriteFrame 时会依照同样的顺序加载依赖。
开发者不需要在代码中处理依赖关系,更无须处理资源文件的读取,只需调用 Loader.prototype.load(),就可以获取加载并实例化后的资源。