一鍵讀取Txt、Excel等表格配置

廢話不多說,先上地址:
源碼:https://github.com/RickJiangShu/ConfigManager
范例工程:https://github.com/RickJiangShu/ConfigManager-Example

引言
1、您是否需要在項(xiàng)目中使用Txt、Excel等表格配置?
2、您是否還在一行行寫配置解析代碼?
3、您是否擔(dān)心運(yùn)行時(shí)解析速度?


使用方法
1、新建一個(gè)txt文件并用電子表格軟件打開編輯,最后也要保存成txt格式的哦。
2、編輯器:
點(diǎn)擊菜單欄"Window/Config Manager";
設(shè)置對(duì)應(yīng)的輸入/輸出路徑;
點(diǎn)擊Output。
image.png

其對(duì)應(yīng)的路徑:
Source Folder:存放配置文件
Config Output:存放根據(jù)配置文件自動(dòng)編碼的腳本
Asset Output:存放asset格式的配置文件
3、運(yùn)行時(shí):
調(diào)用反序列化接口;
使用配置文件。
SerializableSet set = Resources.Load<SerializableSet>("SerializableSet");
Deserializer.Deserialize(set);

 /* 與加載解耦,不依賴加載方式
AssetBundle bundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/config.ab");
set = bundle.LoadAsset<SerializableSet>("SerializableSet");
Deserializer.Deserialize(set);
 */
MonsterConfig monsterCfg = MonsterConfig.Get(210102)
print(monsterCfg.name);

例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test : MonoBehaviour {
    //自動(dòng)生成的序列化設(shè)置類
    SerializableSet set;
    // Use this for initialization
    void Start () {
    set = Resources.Load<SerializableSet> ("SerializableSet");
    Deserializer.Deserialize (set); //自動(dòng)生成的資源解析類
        Resources.UnloadUnusedAssets ();//卸載限制資源


        float startTime = Time.realtimeSinceStartup;
        Debug.Log (Time.realtimeSinceStartup - startTime+"s");
        careerAttrConfig carrer1 = careerAttrConfig.Get (1);
        Debug.Log ("配置文件:"+carrer1.name+"  力量"+carrer1.force); 
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}

設(shè)計(jì)思路
1、自動(dòng)生成解析類
項(xiàng)目中經(jīng)常需要用到策劃配置,而一個(gè)策劃配置需要寫一個(gè)解析類去解析,這樣浪費(fèi)了大量的時(shí)間且容易出錯(cuò)。
因此,我覺得可以寫一個(gè)自動(dòng)生成解析類的工具。
2、編輯器下解析
通常解析工作是放在運(yùn)行時(shí),即加載一個(gè)文本文件之后再進(jìn)行解析這個(gè)文本。這樣在數(shù)據(jù)量巨大的時(shí)候,解析速度堪憂。
因此,我想把大量的解析工作放在編輯器下去處理。
**流程圖

p1.jpg

整個(gè)流程如上圖所示,所以整個(gè)思路可以分為以下四個(gè)部分:解析、反射、序列化和反序列化
解析

  1. 按“分隔符”與“換行符”將表格切割成“行x列”的字符串矩陣,關(guān)鍵代碼如下:
public static string[,] Content2Matrix(string config, string sv, string lf, out int row, out int col)
{
    config = config.Trim();//清空末尾的空白
 
    //分割
    string[] lines = Regex.Split(config, lf);
    string[] firstLine = Regex.Split(lines[0], sv, RegexOptions.Compiled);
             
    row = lines.Length;
    col = firstLine.Length;
    string[,] matrix = new string[row, col];
    //為第一行賦值
    for (int i = 0, l = firstLine.Length; i < l; i++)
    {
        matrix[0, i] = firstLine[i];
    }
    //為其他行賦值
    for (int i = 1, l = lines.Length; i < l; i++)
    {
        string[] line = Regex.Split(lines[i], sv);
        for (int j = 0, k = line.Length; j < k; j++)
        {
            matrix[i, j] = line[j];
        }
    }
    return matrix;
}

2.從矩陣中取出相應(yīng)的字符,替換自定義模板中的變量并寫入文件,關(guān)鍵代碼如下:

string idType = ConfigTools.SourceType2CSharpType(src.matrix[1, 0]);
string idField = src.matrix[2, 0];
 
//屬性聲明
string declareProperties = "";
for (int x = 0; x < src.column; x++)
{
    string comment = src.matrix[0, x];
    string csType = ConfigTools.SourceType2CSharpType(src.matrix[1, x]);
    string field = src.matrix[2, x];
    string declare = string.Format(templete2, comment, csType, field);
    declareProperties += declare;
}
 
//替換
content = content.Replace("/*ClassName*/", src.configName);
content = content.Replace("/*DeclareProperties*/", declareProperties);
content = content.Replace("/*IDType*/", idType);
content = content.Replace("/*IDField*/", idField);
 
//寫入
ConfigTools.WriteFile(outputPath, content);

反射
上面解析出了C#文件和一個(gè)SerializableSet.cs,接下來將通過反射特性實(shí)例化一個(gè)SerializableSet對(duì)象,關(guān)鍵代碼如下:

public static object Serialize(List<Source> sources)
{
    Type t = FindType("SerializableSet");
    if (t == null)
    {
        UnityEngine.Debug.LogError("找不到SerializableSet類!");
        return null;
    }
 
    object set = UnityEngine.ScriptableObject.CreateInstance(t);
 
    foreach(Source source in sources)
    {
        string fieldName = source.sourceName + "s";
        Array configs = Source2Configs(source);
        FieldInfo fieldInfo = t.GetField(fieldName);
        fieldInfo.SetValue(set,configs);
    }
    return set;
}

序列化

最后就是使用Unity API創(chuàng)建Asset文件,關(guān)鍵代碼如下:

UnityEngine.Object set = (UnityEngine.Object)Serializer.Serialize(sources);
string o = cache.assetOutputFolder + "/" + assetName;
AssetDatabase.CreateAsset(set, o);

生成的文件如下:

生成的文件.jpg

反序列化
因?yàn)橐谶\(yùn)行時(shí)使用,所以反序列化的代碼沒有使用反射(效率低)。而是在解析的過程中解析出一個(gè)反序列化文件,生成的代碼如下:

public class Deserializer
{
    public static void Deserialize(SerializableSet set)
    {
        for (int i = 0, l = set.Equips.Length; i < l; i++)
        {
            EquipConfig.GetDictionary().Add(set.Equips[i].EquipId, set.Equips[i]);
        }
 
        for (int i = 0, l = set.EquipCSVs.Length; i < l; i++)
        {
            EquipCSVConfig.GetDictionary().Add(set.EquipCSVs[i].EquipId, set.EquipCSVs[i]);
        }
    }
}

最后,直接調(diào)用相應(yīng)的Config.Get(id)即可,效果如下:

Asset.jpg

轉(zhuǎn)自:http://www.manew.com/thread-105598-1-1.html
作者:RickJiangShu

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,933評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評(píng)論 18 399
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)。 張土汪:刷leetcod...
    土汪閱讀 12,771評(píng)論 0 33
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 6,523評(píng)論 0 17
  • 這個(gè)地方 你和我來過 如今你在哪里 只剩下我如孤云閑鶴 這個(gè)地方 我們?cè)?dòng)得 如初看節(jié)日的焰火 那一天透明的心像...
    Julien陸主歡閱讀 297評(píng)論 2 2