配置文件基类与配置设置

配置系统

配置系统基于Scriptable Object和Odin插件,使得游戏数据的配置文件可视化呈现在Inspector面板上,便于对游戏数据进行设置,UML类图如下。

alt

ConfigManager类是配置系统的核心管理类,持有ConfigSetting的对象,使用GetConfig方法获取下层configSetting对象中的配置。

ConfigBase是配置基类,游戏内的角色配置、武器配置等都继承自此类,其继承自序列化的ScriptableObject类,支持字典序列化。ConfigSetting类容纳了所有游戏配置,其包含有字典作为值类型的configDic,使用string类型作为不同类型配置文件的索引,内含字典列表容纳同一类型的所有配置文件,以int作为列表索引,并通过GetConfig方法获取某类配置中的一个具体的配置。

GameSetting类是框架层面的游戏配置,继承ConfigBase类,结合Unity编译前运行在游戏运行前扫描自定义的一些属性,其存在的意义在于完善其他功能系统的初始化过程并将状态可视化呈现在面板上,包括对象池的缓存设置、UI的设置。相关方法有InitForEditor,调用PoolAttributeOnEditor方法和UIElementAttributeOnEditor方法,通过在GameRoot中的编译前部分进行调用执行PoolAttributeOnEditor方法负责将带有Pool特性的类型加入缓存池字典,UIElementAttributeOnEditor方法负责遍历程序集下的每个类型找出带有UI属性的类并按照属性内的配置进行UI资源的加载和分层。

系统的配置

ConfigManager类供外部逻辑获取配置,包含GetConfig方法根据配置类型和列表ID获取持有的configSetting内的某个配置。

     public T GetConfig<T>(string configTypeName, int id = 0) where T : ConfigBase
      	{
            return configSetting.GetConfig<T>(configTypeName, id);
        }

ConfigBase类中无内容,其使用Sirenix.OdinInspector命名空间,继承序列化脚本可视化类,相当于中转,所有继承ConfigBase类的配置子类都可以使用CreateAssetMenu属性创建自定义的配置脚本文件,并在面板上可视化操作。

[CreateAssetMenu(fileName = "ConfigSetting", menuName = " ConfigSetting")]
public class ConfigBase : SerializedScriptableObject
{}

ConfigSetting是一类特殊的配置,其在游戏运行时全局唯一,通过面板拖拽装载所有游戏配置,并储存进字典,对ConfigManager提供GetConfig方法获取配置,经过配置类型和列表ID两层检验。

        public T GetConfig<T>(string configTypeName, int id) where T : ConfigBase
        {
            // 检查类型
            if (!configDic.ContainsKey(configTypeName))
            {
                throw new System.Exception("配置设置中不包含这个Key:" + configTypeN
   		  ame);
            }
            // 检查ID
            if (!configDic[configTypeName].ContainsKey(id))
            {
                throw new System.Exception($"配置设置中{configTypeName}不包含这个                  ID:{id}");
            }
            // 说明一切正常
            return configDic[configTypeName][id] as T;
        }

GameSetting是一类框架层面的特殊配置,其并不存储游戏数据,而是持有对象池和UI的配置数据,在Unity编译前通过反射遍历所有程序集下的每一个类型,识别所有属性标记,并根据属性将需要受对象池管理的类型录入对象池缓存字典并将UI预制体进行加载、缓存、分层,以对象池为例。

   	        System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssembl            ies();
            // 遍历程序集
            foreach (System.Reflection.Assembly assembly in asms)
            {
                // 遍历程序集下的每一个类型
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    // 获取pool特性
                    PoolAttribute pool = type.GetCustomAttribute<PoolAttribute>();
                    if (pool != null)
                    {
                        cacheDic.Add(type, true);
                    }
                }
            }

装备、角色、NPC的配置