【框架系统】Unity读取Json文件做游戏配置表

看一个小游戏源码的时候,发现他是使用Json作为游戏的配置表,但是在读取配置时,使用的是string作为配置表的key,index作为配置表的id,如图:

个人认为这样极为不方便。一是没有遵循面向对象编程的开闭原则,不利于配置的扩展;二是用string做key,比较麻烦并且可能出错。

所以想重构一个配置表框架实现以下功能:

1、不同的配置表创建不同的类,实例化对应的对象,方便调用。

2、运行游戏时加载所有配置表到字典,使用是从字典里面读取。

3、统一的获取配置表接口。

4、优化:自动生成配置序列化代码。

一、首先创建一个TestConfig类,添加变量、序列化代码。


public class TestConfig : Config
{
    public string name;
    public int baseHP;
    public int baseMP;
    public int baseStr;
    public int baseMag;
    public int baseDef;

        #region GinerateByTool!!
    //-----------------------
    //该部分代码由工具生成!!!
    //不要在本段代码中做修改!!!
    //重新生成会覆盖该代码段!!!
    //-----------------------
    public TestConfig(){}

    public override void Serialize(JSONObject jo)
    {
        base.Serialize(jo);
        jo.GetField(ref name,"name");
        jo.GetField(ref baseHP,"baseHP");
        jo.GetField(ref baseMP,"baseMP");
        jo.GetField(ref baseStr,"baseStr");
        jo.GetField(ref baseMag,"baseMag");
        jo.GetField(ref baseDef,"baseDef");
    }

       
    #endregion GinerateByTool!!
    }

 二、在游戏运行时通过反射初始化配置表,将对应的数据实例化到配置表,再将配置表存到字典,方便读取。

 public void Init(string json)
    {
        JSONObject JSONO = new JSONObject(json);
        for (int i = 0; i < JSONO.Count; i++)
        {
            string _className = JSONO.keys[i];
            Type type = Type.GetType(_className);
            if (type == null)
            {
                continue;
            }
            Config _config = type.Assembly.CreateInstance(type.FullName) as Config;
            if (_config == null)
            {
                continue;
            }
            JSONObject jo = JSONO.GetField(_className);
            for (int j = 0; j < jo.Count; j++)
            {
                _config.Serialize(jo[j]);
                AddConfig(type, _config);
            }
        }
    }

    private void AddConfig(Type type, Config config)
    {
        string _configName = type.ToString();
        if (!m_configDic.ContainsKey(_configName))
        {
            m_configDic.Add(_configName, new Dictionary<long, Config>());
        }
        m_configDic[_configName][config.id] = config;
    }

三、添加获取配置表API,通过配置表类型和id获取到对应的配置表。

 public T GetConfigFromDic<T>(long id) where T : Config
    {
        Type t = typeof(T);
        return (T)GetConfigFromDic(t, id);
    }

    public Config GetConfigFromDic(Type type, long id)
    {
        if (type == null)
        {
            return null;
        }
        string _configName = type.ToString();
        if (!m_configDic.ContainsKey(_configName))
        {
            return null;
        }
        if (!m_configDic[_configName].ContainsKey(id))
        {
            return null;
        }
        return m_configDic[_configName][id];
    }

四、测试:

添加Main代码,挂载在游戏物体上,当游戏运行 执行Awake时 初始化配置表 。通过获取配置表API就能获取到对应的配置表。

public class Main: MonoBehaviour
{
    private void Awake()
    {
        TextAsset dataFile = Resources.Load("Test") as TextAsset;
       
        ConfigManager.Inst.Init(dataFile.text);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            TestConfig _config = ConfigManager.Inst.GetConfigFromDic<TestConfig>(1);
            Debug.Log(_config.name);
        }
    }
}

五、优化:

因为配置表Serialize序列化的时候代码类似,所以用T4生成该段代码。

具体T4代码如下:

 public virtual string TransformText()
        {
            this.Write("    #region GinerateByTool!!\r\n    //-----------------------\r\n    //该部分代码由工具生成" +
                    "!!!\r\n    //不要在本段代码中做修改!!!\r\n    //重新生成会覆盖该代码段!!!\r\n    //-------------" +
                    "----------\r\n    public ");
            
            #line 17 "C:\Works\int5\T4Template\ConfigTemplates\ConfigTemplate.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(this.TargetType.Name));
            
            #line default
            #line hidden
            this.Write("(){}\r\n\r\n");
           
            #line default
            #line hidden
            this.Write("    public override void Serialize(JSONObject jo)" +
                    "\r\n    {\r\n        base.Serialize(jo);\r\n");
            
            #line 23 "C:\Works\int5\T4Template\ConfigTemplates\ConfigTemplate.tt"
 foreach (var item in this.FieldInfos)
{
            #line default
            #line hidden
            this.Write("        jo.GetField(ref ");

            #line 25 "C:\Works\int5\T4Template\ConfigTemplates\ConfigTemplate.tt"
            this.Write(item.Name);
            this.Write(",\"");
            this.Write(item.Name);
            this.Write("\")");

            #line default
            #line hidden
            this.Write(";\r\n");
}
            
            #line default
            #line hidden
            this.Write("    }\r\n\r\n       ");
            
            #line default
            #line hidden
            this.Write("\r\n    #endregion GinerateByTool!!");
            return this.GenerationEnvironment.ToString();
        }

六、Demo

完整资源路径

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值