GameFramework解析:全局配置(Config)
前言
首先要明白的一点是GF里面的全局配置并不是指的一般意义上的数据表,全局配置表的格式不能随便自定义,它的格式必须与当前的ConfigHelper里面写定的解析格式保持一致,否则无法解析。而它是用来存储一些全局性质的只读配置,如玩家初始速度、游戏初始音量等。
全局配置模块结构图
从结构上就可以看出几个点:- ConfigManager和DataProvider存在许多个相同的接口,是因为ConfigManager主要是对DataProvider里面的方法进行封装,模块的核心逻辑位于DataProvider。
- DataProvider和DefaultConfigHelper的核心功能方法名称相同,是因为真正的对配置文件的读取,解析功能位于DefaultConfigHelper。
这样做的好处是不仅实现了解耦,而且方便功能的修改和拓展,ConfigManager存储解析好的配置数据,并提供给外界功能接口;模块核心逻辑位于DataProvider;读取和解析的逻辑位于ConfigHelper。使用者可以使用默认的DefaultConfigHelper来加载对应格式的配置文件,也可以根据自己项目的需求,去书写自己的ConfigHelper来实现自定义的配置格式和对应的解析逻辑。
读取解析存储全局配置流程
整个流程为:读取————>解析————>存储。根据资源的名称,读取相对应的文件,然后根据定义的解析规则,解析成对应的配置数据,最后存储到ConfigManager里面。其中也支持二进制文件,并设置了相对应的缓存步骤对此格式的配置文件进行处理。ConfigManager
ConfigManager主要是对DataProvider里面的方法进行封装,提供给外部功能接口实现配置的读取,解析,并且会存储解析好的全局配置数据,供外界使用。
类内信息
- m_configData:存储解析好的全局配置数据,提供给外界调用。根据其Value的ConfigData类型,可以得知支持的数据类型包括 int、float、string以及bool这四类。
- m_DataProvider:模块的核心逻辑,用来读取配置文件。
- m_configHelper:ConfigHelper的实例,用来解析配置文件。
DataProvider
Config模块的核心逻辑书写处,主要是通过获取的资源模块接口去读取配置文件,然后放入ConfigHelper里面进行解析。
类内信息
- BlockSize: 缓存块大小,用来缓存配置文件的二进制流。
- s_CachedBytes: 用于存储缓存的二进制流。之所以专门在此定义一下是为了避免频繁的内存分配,提高效率的同时降低内存碎片的可能性。
- m_Owner: 当前DataProvider的拥有者,也就是ConfigManager。DataProvider是GF的基础模块,这里是ConfigManager在使用,这样做自然也是为了方便使用者修改和拓展。
- m_ResourceManager: 资源管理器接口,用来读取配置文件。
- m_DataProviderHelper:DataProviderHelper的实例,用来解析配置文件。这里的话其实就是DefaultConfigHelper的实例。
功能接口的也是支持对于文件(包含二进制文件)的读取,解析,存储。通过结构图和流程图已经能够直观了解到,这里不再赘述。
二进制流的缓存与释放
1 | /// <summary> |
DefaultConfigHelper
这是GF默认的全局配置解析器,看到这里,可以了解到因为每个部分都是功能分明,相对独立的,整个模块都便于支持使用者根据自己的需求和功能去修改和拓展的。
这里简单举例说明一下DefaultConfigHelper的的解析规则。
比如,接下来我们存在如下的全局配置文件,其配置内容如下:
我们调用模块接口进行读取:
1 | GameEntry.Config.ReadData(configAssetName, this); |
来到DefaultConfigHelper的解析方法:
1 | private static readonly string[] ColumnSplitSeparator = new string[] { "\t" }; |
可以看到通过以制表符为分割,将配置文件的每一行内容分割成四个字段(ColumnCount),获取到了第一个和第四个配置信息,并将其添加到ConfigManager里面。
使用的情况:
1 | GameEntry.Config.GetInt("Scene.Menu") |
这样,我们就实现了全局配置的定义,读取,解析,存储以及使用。