引擎中的资源及文件系统

资源及文件系统

游戏引擎架构 第六章

涉及载入、管理多种资源 因此涉及到 资源管理器

封装引擎私有API的原因:

1.跨平台需求时 对文件系统API的隔离 隐藏不同目标平台间的区别。

2.提供一切所需但文件系统未提供的功能 例如streaming 等等。

文件系统

通常功能

操作文件名和路径

路径:一般是由卷盘指示符和路径成分组成 其之间以分隔符分隔 不同操作系统之间的分隔符使用是有差异的。

C:\Program Files\Unity\Hub\Editor
操作系统间的区别

例如UNIX使用‘/’ DOS和早期Windows采用‘\’ 后期的Windows支持了正反斜线符来做分隔路径。

UNIX系不支持以卷盘分开目录层次。整个文件系统都是以单一庞大的层次所组成的。像是一棵树行关系,所以UNIX路径不会出现卷盘指示符的。

绝对路径与相对路径

所有路径都对应文件系统中的某个位置

当路径相对于根目录,称其为绝对路径

当路径相对于文件系统中的其他目录时,称其为相对路径

UNIX的绝对路径是以分隔符/起始

搜寻路径

搜寻路径是包含一串路径的字符串,各路径间以特殊符号分隔 在找文件时会从这些路径进行搜寻。PATH环境变量

路径API设计

常见的如 路径分离目录/文件名/扩展名、路径规范化、绝对路径与相对路径间转换、各平台间目录差异包装等

文件I/O

standard C library 提供两组API以开启、读取和写入文件内容。

其中一组有缓冲buffered 另一组无缓冲unbuffered。

每次调用输入输出时 都需要成为缓冲区的数据区块 来提供程序和磁盘之间传送来源或目的字节。

对于有I/O缓冲功能的函数有时候会成为Stream I/O 这时会把磁盘文件抽象成字节流。

同步IO

程序发出IO请求后 必须等待读写数据完毕后 程序再继续运行。

异步IO

streaming

利用另一线程处理I/O 请求。主线程调用异步函数时,会把请求放入一个队列,并且立即传回。

同时,I/O线程从队列中取出请求,并阻塞I/O函数如read()处理这些请求。

在请求工作完成后,就会调用主线程之前提供的回调函数,来通知操作完成。

若主线程选择等待完成I/O请求,会使用信号量 semaphore 来同步状态

(每个请求对弈一个semaphore 主线程把自身处于休眠,等待IO线程完成工作后的新号通知)。

asynchronous 通过回调函数 处理读写完成后的连续操作

需要注意异步加载时 资源加载的优先权 对于优先级更高的资源做优先加载处理 可能情况还需要暂停较低优先权的请求。

资源管理器

两个部分组成

1.负责管理离线工具链,用来创建资产以及把他们转换成引擎可用的形式。

2.在执行期间管理资源,确保资源在使用之前已载入内存,并在不需要时从内存卸下。

离线资源管理及工具链

资源的版本控制

​ 版本控制工具 资产 数据量

资源数据库

​ 对于大部分资产来说 引擎并不会直接使用期原本的格式。会对资产做相应的调节转换为引擎所需格式 及 资产调节通道 asset conditioning pipeline。

​ 此时 每个资源都需要有元数据metadata描述如何对资源进行处理。

​ 例如 压缩纹理的压缩类型 动画clip的帧信息处理 模型软件导出的网格信息处理

​ 所以需要这种由各种元数据组成的资源数据库 或者是资源处理配置。记录着如何处理对应的资源。也可以理解为是一种描述文件。

无论资源数据库采用什么形式 必须提供以下功能:

能处理多种类型资源。

能创建新资源。

能删除资源。

能查看及修改现存资源。

能把修改资源的目录位置。

能让资源交叉引用其他资源。交叉引用通常同时驱动资源管理生成过程及运行时的载入过程。

能维持数据库内所有交叉引用的引用完整性。执行所有常见操作后,如删除或移动资源后,仍能保持引用完整性。

能保存版本历史,并含完整日志记录改动人员和事由。

支持不同形式的搜寻和查询。例如资源建引用关系。

需要考虑的常见问题:

对同一时间相同资产的修改,存在合并问题和上锁问题。以及资源的粒度划分。

源文件映射,让用户很容易得出该资源是由那些资产而来。

资产调节通道

asset conditioning pipeline ACP

resource conditioning pipeline RCP

tool chain

每个资源管道的开端都是DCC原生格式的源文件(如Maya .ma PS .psd)

这些资产通常会经过3个处理阶段 再到达游戏引擎。

1.导出器 exporter

常是为DCC撰写自定义插件, 功能是把DCC工具里的数据导出为某种中间格式,供后续阶段使用。

2.资源编译器 resource compiler

对上一阶段的数据做一下格式处理。 例如把网格三角形重新排列成三角形带门或是要压缩纹理 。 目的是让数据在导出后可直接被引擎所使用。

3.资源链接器 resource linker

有时 多个资源需要先结合成单个有用的包再载入到引擎(存在依赖关系)。 例如模型 需要把网格材质骨骼贴图动画等等整合好后结合为模型资源。

叫做资源链接 但也是并非素有资源都需要链接 单一素材则不需要了(无依赖)。

每个ACP都需要一组规则来描述资产之间的依赖关系。当某资产作出改动后,有些生成工具可以利用这些依赖关系信息,确保以正确次序为自查进行生成。

运行时资源管理

功能责任

1.确保任何时候,同一资源在内存中只有一份副本。

维护一个资源注册表,来确保每个资源只有一份副本。可以用字典键值对来记录加载过的资源 guid,内存中资源指针。

2.管理每个资源的生命周期,载入需要的资源,不需要时卸载。

引用计数

3.处理复合类型资源,复合资源是由多个资源组成的资源。

4.维护引用完整性,正确维护资源依赖关系。包括内部引用完整性(单个资源内的交叉引用)及外部引用完整性(资源间的交叉引用)。

有向图 全局资源查找表 指针修正 指针偏移表

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

6.允许按资源类型,载入资源后执行自定义处理。资源载入初始化。

7.常常提供单一同一接口管理。且应该易扩展。

8.支持异步加载 streaming

9.游戏中所有资源都必须有某种全局唯一标识符 GUID 文件路径或是文件把资源层次结构组织起来。

资源所需的内存管理
基于堆的资源分配

​ 忽略内存碎片问题,仅使用通用的对分配器分配资源所需内存。由系统自行做内存碎片整理和内存分配。

基于堆栈的资源分配

​ 堆栈分配器不会有内存碎片问题,因为内存是连续分配的。释放内存时则根据分配的反方向进行。

​ 需要资源加载是线性且可控。

​ 游戏启动后 ,先分配给常驻留资源。标记栈顶位置,之后便可以通过该标志位做资源释放。载入关卡时在栈顶分配内存,关卡完成后,移回栈顶位置到原标记位。

双端堆栈分配器

​ 两个栈定义在一大块内存里。其中一个由内存底端向上 一个从顶端向下。例如:顶端栈做临时分配内存 底端栈做持久数据。

基于池的资源分配

池分配器,把资源数据以同等大小的块载入,因为全部大小相同,资源卸下时不会造成内存碎片。

资源切块 同等大小 一般会存在空间浪费问题。通常不能充分利用资源最后一个块。

载入后初始化

​ 某些资源在载入后 需要执行某些特殊操作 以及注意销毁时做特定动作。 多态 构造 析构

​ 载入时同时包含相关和不想管数据的资源时,相关数据会复制到内存最终目的地,不相关数据进行弃置。避免浪费内存。

​ 直接载入到最终内存位置 或者载入到临时内存区域。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值