游戏引擎需要读取大量数据,数据形式包括游戏资产、配置文件、脚本等;资产管道将描述数据如何从制作原始资产的工具一直流到游戏引擎本身;
-
资产管道的第一环:游戏本质是多媒体应用,所以游戏引擎的输入数据形式非常广泛,所有源数据都是使用数字内容制作(digital content creation)DCC软件制作;DCC软件都是为制作某一类数据而设,而且都会有其特有的数据格式,这些数据并不会直接用于游戏的;
DCC软件在内存中的数据模型,通常比游戏所需的复杂,因为这些DCC软件的数据并不只是为游戏制作的,而只是适用于游戏而已;例如,Maya的场景节点以有向非循环图(DAG)存储,而且maya还会存储该文件的所有编辑历史记录(类似PSD会存储所有的操作步骤),Maya场景中每个顶点的位置、方向等都会有非常完整的三维变换数据,但是游戏引擎并不需要这么多信息,将其加载到内存中也是对性能和内存的极大浪费;
而且在游戏运行时中读取DCC软件格式,速度会比较慢,并且有些格式更是闭源的;
所以为了解决以上问题,DCC软件制作的数据不能以其原生的格式导出,而是需要导出为容易读取的标准格式或自定义格式,以便在游戏中使用;
当数据从DCC软件导出时,有时需要再处理,才能放在游戏引擎里使用,在unity里,我们通常会对要导入的资源设置各种选项,然后对这些资源进行再处理;如我们从3dmax里面导出FBX类型的模型文件,在导入到引擎时,引擎仍然要进行各种处理最后才能用于游戏运行时;
这个从DCC制作到游戏引擎可用的管道,就是资产调节管道;
-
资源管理器
游戏的资源管理主要包含两方面,一是建立离线的资源工具,用于创建资产并将它们转换成引擎可用的方式,另一方面负责在执行期管理资源,确保资源在使用前已经载入运行内存,并且在不需要的时候将其从内存卸下;
-
离线资源管理及工具链
资源数据库:我们已经知道,对于大部分的资产,游戏引擎并不会使用原本的格式,资产需要经过一些资产调节管道(Asset Conditioning Pipeline,ACP),用来把资产转换为引擎所需的格式,可同比想到Unity的AssetDataBase,它会包含各种类型的Importer;当导入一个资源时,也就是资产流经资产调节管道时,每个资源都需要有些元数据,描述如何对资源进行处理,在Unity中,就会在导入时为每一个资产生成一个相应的meta文件用于存储各种导入配置信息,而最终AssetDataBase就是用于管理这些meta文件的;
资源数据库的一些基本功能,概括来说就是一个数据库的增删改查以及相应扩展:
-
能处理多种类型的资源,理想地(但不是必要)是以一致的方式处理;如Unity,它支持非常多格式的资源类型,针对每种资源类型都会有一些特有的处理方式;
-
能创建新资源
-
能删除资源
-
能查看及修改现有的资源
-
能把资源从一个位置移至磁盘另一位置
-
资源的交叉引用(如网格引用材质等)
-
能维持数据库内所有交叉引用的引用完整性,执行所有常见操作后,如删除或移动资源,仍能保持引用完整性;
-
能保存版本历史,并含完整日志记录改动者及事由
-
资源数据库若能支持不同搞形式的搜索(Unity的资源管理器中支持根据名称进行模糊搜索,还可以设置一些标签进行过滤限定搜索范围)
-
-
资产调节管道(ACP)
每个资源管道的开端都是DCC原生格式的源文件,这些资产通常要经过3个处理阶段,才能到达游戏引擎
-
导出器
-
资源编译器,对数据进行重新处理,如压缩纹理等
-
资源链接器,有时多个资源需要结合为单个有用的包才能载入游戏引擎
-
-
-
运行时资源管理
关注资产怎样从资源数据库载入、管理并卸载
-
运行时资源管理器的责任
-
确保任何时候,同一个资源在内存中只有一份副本;
-
管理每个资源的生命期
-
处理复合资源的载入
-
维护引用的完整性,包括内部引用的完整性(单个资源内的交叉引用)和外部引用的完整性(资源间的交叉引用)
-
管理资源载入后的内存用量,确保资源存储在内存合适的地方
-
处理串流,支持异步资源载入
-
-
资源全局统一标识符
游戏中所有资源都必须有某种全局唯一标识符,GUID;
-
资源注册表
为了保证在任何时间,载入内存的每个资源只会有一份副本,大部分资源管理器都含某种形式的资源注册表,记录已载入的资源。最简单的实现模式就是使用字典,即键值对的几何,其中键为资源的唯一标识符,而值通常就是指向内存中资源的指针;资源载入内存时,就会以GUID为键,加入到资源注册表中,卸下资源时,就从字典中删除即可;游戏请求资源时,资源管理器就会先根据GUID查找资源注册表字典,如果可以获取就直接传回资源指针;否则,就会自动载入相应资源;
从磁盘载入资源到内存中缓慢操作,如果在游戏运行时执行读取,可能会对游戏帧率造成明显影响;所以,引擎可采取一下两个手法
-
在游戏进行中,完全禁止加载资源,所有的资源都在游戏进行前全部加载(进度条期间完成加载);缺点在于,有些加载请求是受玩家控制的,如果玩家不进去请求,就可能加载很多无用的资源;
-
资源以异步形式加载(即数据采用串流),当玩家在玩关卡A时,关卡B就会在背景加载,这种方式可以让玩家享受无载入画面的游戏体验;
-
-
资源生命期
每个资源对生命期有各种不同的需求(几种不同资源的载入类型)
-
有些资源在游戏开始时必须载入,并驻留在内存直至整个游戏结束。换言之,其生命期实际上时无限的。这些资源有时候称为载入并驻留资源(Load-and-staty-resident LSR),典型例子包括:玩家角色的网格、材质、纹理及核心动画,抬头显示器(HUD)的纹理及字型,整个游戏斗湖用到的所有常规武器的资源,在整个游戏过程中,玩家一直听到或看到的任何资源(包括不能按需载入的资源),都应该归位LSR资源;它的特点就是,非按需载入,生命期为整个游戏过程;
-
有些资源的生命期对应某游戏关卡,在玩家首次看到关卡时,对应的资源便留在内存,直至玩家永久离开关卡,资源被卸载;
-
资源的生命期短语其所在关卡的事件,如游戏中的过场动画及音频短片;
-
有些资源如背景音乐、环境音效或全屏电影,可以在播放时即时串流,因为每字节只短暂留在内存中,但整首音乐却会持续很长时间,这类资源通常以特定大小的区块载入,区块大小根据硬件需求而定。
资源何时载入不是难题,难题是何时卸载资源释放内存,可用引用计数的方式;
资源所需的内存管理
资源管理和内存管理密切相关,载入资源时不可避免要决定如何将资源加载至哪一块内存地址。首先,某些资源必须驻留在显存,包括纹理、顶点缓冲与索引缓冲、着色器等,大部分其它资源可能会驻留在主内存,但不同的资源可能要置于不同的地址范围,如载入并驻留资源(LSR)可能会载入某内存区域,经常载入卸下的资源可能会载入其它内存区域
-
-