游戏引擎架构-资源及文件系统

本篇知识点来源于《游戏引擎架构》第六章,主要讨论现代三维游戏引擎中典型资源管理器的运作方式。

资源数据库

对于大部分资产来说,游戏引擎并不会使用其原本的格式。资产需要经过一些资产调节管道,把资产转换为引擎所需的格式。当流经资产调节管道时,每个资源都需要用一些元数据描述如何对资源进行处理,比如贴图要用哪种压缩方法,导出animation的时候需要导出哪个范围的帧。为了管理所有这类元数据,需要有某种形式的数据库。

在各游戏引擎中,资源数据库的形式有巨大差异。无论资源数据库采用什么形式,它都必须提供以下功能:

  • 能处理多种类型的资源,期望能用一致的方式处理这些资源

  • 能创建新资源

  • 能删除资源

  • 能查看及修改现存的资源

  • 能把资源从一个位置移动到另一个位置

  • 能让资源交叉引用其他资源

  • 能维持数据库内所有交叉引用的引用完整性。比如删除/移动资源,仍能保持引用完整性

  • 能保存版本历史,并完成记录改动者及事由的日志

  • 支持不同形式的查询。比如想知道模型引用了什么纹理,什么骨骼;或者通过名字、类型搜索资源

运行时资源管理

运行时资源管理指的是引擎运行时,资源是怎样从资源数据库载入、管理并卸载的。

运行时资源管理器的人物全部都和其主要功能“载入资源至内存”有关:

  • 确保任何时候,同一个资源在内存中只有一份实例

  • 管理每个资源的生命周期,在必要时载入需要的资源,不需要的时候需要卸载资源

  • 处理复合资源的载入。比如三维模型,需要载入网格、多个材质、多个纹理

  • 维护引用完整性。当载入复合资源时,资源管理器必须确保所有子资源也被载入,并正确地修补所有交叉引用。比如三维模型在被导入的时候需要确保所有引用的材质、纹理都被正确导入

  • 管理资源载入后的内存用量,确保资源存储在内存中合适的地方

  • 允许载入资源后做自定义处理

  • 通常提供统一接口管理多种资源类型。理想情况下可以要容易扩展,以满足团队新增资源类型的扩展需求

  • 理想情况下可以支持异步资源载入

资源注册表

为了保证在任何时间,载入内存的每个资源只会有一份副本,大部分资源管理器都含某种形式的资源注册表记录已载入的资源。最简单的实现模式就是使用字典,通常以其GUID为键。卸载资源时删除注册表记录,请求某资源时先通过guid查找资源注册表字典,能搜索到则返回资源指针,否则自动载入资源或者返回失败码。

没找到请求的资源时最直接的处理方法是自动载入该资源,但此举会对游戏帧率造成非常明显的影响。因此引擎有两种取代方法:

  1. 在游戏运行时完全禁止加载资源。这就会有“读条”现象,即玩家在进入新的游戏关卡之前需要观看载入画面或者载入进度栏。

  2. 以异步形式加载(即串流)。玩家在关卡A时提前加载关卡B的资源数据。

资源的生命期

资源的生命期被定义为该资源被载入到被卸载的时间。

资源管理器的职责之一就是管理资源的生命期,每个资源对生命期有不同的需求:

  • 有些资源在游戏开始时便需要被载入。这类资源被称为载入或驻留资源(LSR)。比如玩家角色的网格、材质、纹理,整个游戏都会被用到的所有常规武器的资源。

  • 有些资源对应某些特定的场景或者游戏关卡。比如这个资源只会在A关卡出现,直到玩家去到下个关卡时资源才会被卸载。

  • 有些资源生命期短于所在关卡的时间。比如游戏的过场动画用到的资源。

  • 有些资源(bgm、环境音效或者全屏电影)可以在播放时即时串流,内存中某一时刻只需两区块的数据,分别是目前播放中的区块,及载入中、紧接前者的缓存区块。这类资源的生命期很难定义,比如bgm的每个字节短暂停留在内存中,但是整首音乐会持续很长一段时间。

何时载入资源不是难题,只要是玩家第一次看见该资源的时候载入就行,问题是何时需要卸载资源。解决方式就是引用计数,在需要引用某个资源的时候将其引用数+1,即将卸载某个资源的时候引用数-1,当引用数为0时真正卸载这个资源,由0变成1时重新载入这个资源即可。

你可能感兴趣的:(游戏引擎,unity,游戏,架构)