欢迎光临散文网 会员登陆 & 注册

BlockOS开发日志(三)设计资源管理系统

2023-03-30 11:23 作者:Zerous  | 我要投稿

为什么要设计资源管理系统?

从总体上概括的话,是因为Unity引擎本身提供的资源管理系统过于简单,不能满足项目的定制化需求。所以需要另外开发一个资源管理系统用于本项目。

具体到开发过程里来说,是因为我在开发区块及其渲染系统的过程中意识到,方块的模型文件以及材质贴图都因为其需要合批渲染的需求需要做特殊的定制。因此决定先完成资源管理系统的设计与实现。

需要管理哪些资源?

由于我对BlockOS定下的第一个规划首先就是完成区块及其渲染系统的开发,因此目前暂时只能明确区块和区块渲染系统所需求的资源。

首先在前面的开发日志中已经提到过,由于方块众多,区块需要使用合批的方式进行渲染。我对此的实现思路参考了著名的Marching Cubes算法。Marching Cubes算法是将一个单元格的8个顶点的有无情况作为比特位写入到一个字节中,根据这个字节去查询网格表,确定最终该单元格的网格。而要做到能绘制出多种多样方块的网格,则需要做的事比Marching Cubes算法更多一些:本方块在上下左右前后六个方向的遮挡位标志、方块元数据(如摆放方向,特殊状态等)、方块纹理数据和方块模型数据。

它们的数据结构?

在Marching Cubes算法中,顶点位标志和模型间的关系可以看作是以位标志为自变量而单元格模型为因变量的函数关系:

Model%3Df(VertexFlags)

而BlockOS中,则是遮挡位标志、元数据和纹理数据为自变量:

Model%3Df(OcclusionFlags%2CMetadata%2CTexture)

那么方块模型本质上就可以看作是一个函数。遮挡位标志由实时计算得出,元数据通过读取区块数据得到,而纹理数据则通过查询纹理管理器得到。

由上面的分析可以得出,方块模型还依赖一个纹理管理器。因此还需要对纹理管理器进行设计。

结合前面开发日志的方案可以得到,由于合批渲染的需要,纹理被读取后,将在内存中被合并为一张大纹理。而小纹理将会被存储为一个在大纹理的相对位置的“引用”。和2D游戏开发中精灵(Sprite)的概念很像。那么后面就叫它方块精灵吧。

纹理管理器会读取纹理包中指定文件夹中的所有方块精灵文件。读取完成后,以文件名为键,相对位置为值生成键值对以便方块模型查询。

参考链接器,这个过程可以继续优化。方块模型可以不必存储对应模型的名字,而是直接持有其相对位置,这样就可以在渲染过程中减少计算字符串哈希的时间。

资源加载流水线

根据上面的分析以及对渲染API的参考,我认为可以提出一个资源加载流水线的概念。

这段可以用函数式的思路来看,方块模型是一个函数,而区块资源加载流水线则是可以生产这个方块模型函数的高阶函数。纹理名称-相对位置哈希表则是中途生成的临时数据。

区块资源加载流水线再往细了说,按照图片所示,可以有方块模型定义、方块纹理精灵、大纹理和方块模型几个组成部分。其中最终存储在内存中的,只有大纹理和方块模型。方块模型定义也是一个高阶函数,输入纹理精灵,输出方块模型函数。方块纹理精灵则将最终作为方块模型中的一个字段存储于方块模型中。

区块资源加载流水线

资源存储

探讨完了资源加载,还有一个话题是如何查询到目标资源。大纹理全局唯一,可以直接硬编码来获取。而方块模型数据则需要以方块id来查询,因此需要用哈希表来存储。这里也可以进行优化来避免反复计算方块id的哈希值。这个留到后面的区块建造流水线中再讨论吧。

最后解释下这么久没更新的原因:作为一个学习不努力的懒狗,终于还是在春招的尾巴上找到了一家可以转正的Unity3D实习岗,这半个月都在适应新的生活节奏= =。所以一直很少能腾出时间来做开发日志,现在终于开始有些适应了,可喜可贺。这半个月以来的很多点子想出来都没能好好记录一下挺可惜的,那么现在就立刻开始记录吧。

BlockOS开发日志(三)设计资源管理系统的评论 (共 条)

分享到微博请遵守国家法律