Unity编辑器扩展:导表工具(1)(通用版)

以下均为我个人总结的方案,如果有所不足的地方,请多多包涵

有更好的方案或者有错误之处,敬请留言,谢谢您看了我的博客

最近开始捣弄自己的小项目,想了想怎么开始,我个人的想法也就是从导表工具开始入手。

此文章志在提供思路,以及部分代码,涉及的关键性问题会详细阐述。

目前此工具我已经开发了部分功能,支持Json,ScriptableObject,asset文件,至于java,lua等其他语言,只要理解了思路,都是同样的道理。

因为我的小项目是单机的,所以按照我的思路,一开始原本用json,后面改用scripttableObject以及asset文件。

简单说明下思路:分三个步骤

       1.编辑器扩展,编写界面。

       2.如何读取excel表中数据。

       3.将数据转换成自己想要的格式。

简单来说,就是自己的项目定义好excel表内数据格式,然后读取之后,讲数据转化成自己想要的格式就好了。

我的工具最终效果如图:

一:编辑器扩展界面编写

将工具放入菜单栏中,如图1-1所示

在工作生涯中,每个人的工具库都是慢慢积累的,所以在一开始的时候,我们就要管理好它。

至于编辑器扩展相关知识,我也不是编写过很多,相关知识点等以后我学习更深,总结后再发布到《学习》类别里。

至于编辑器界面编写,有很多种GUI系统,基于我自己项目对于界面自定义需求不高,我使用带自动布局的EditorGUI系统。

        EditorGUILayout.BeginHorizontal();
        _threePackName = EditorGUILayout.TextField("数据类型:", _threePackName);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        _excelPath = EditorGUILayout.TextField("excel目录:", _excelPath);
        if (GUILayout.Button( "Browse",GUILayout.ExpandWidth(false)))
        {
            string path = EditorUtility.OpenFolderPanel("", "", "");
            if (path != null)
            {
                _excelPath = path;
                Debug.LogWarning("Select _excelPath folder =  "+_excelPath);
                EditorPrefs.SetString(SAVE_CLIENT_EXCLE_PATH, _excelPath);
                GetExcelFileInfos();//这里是在选择了excel目录后再读取目录中所有excel文件的操 
                                    //作。在后面会做详细阐述
            }
        }
        EditorGUILayout.EndHorizontal();

简单说明下:

第一个数据类型,是为了以后方便区分不同语言版本。

第二个excel目录,是excel目录文件的路径,这里使用了EditorPrefs来做存储,为了是方便再次打工工具时候使用。

以此类推,编辑器界面除了excel文件展示部分,其余部分都很简单。

接下来是excel文件部分:

首先,需要个excel数据类、MD5数据类

    /// <summary>
    /// excel数据类
    /// </summary>
    public class FileInfoData
    {
        /// <summary>
        /// Excel表的路径
        /// </summary>
        public string filePath;
        public string fileNameWithPostfix;
        /// <summary>
        /// Excel表的名字
        /// </summary>
        public string fileName;
        public string fileNewName;
        /// <summary>
        /// Excel表的MD5存储
        /// </summary>
        public string excelMD5Save;
        /// <summary>
        /// Excel表的新MD5
        /// </summary>
        public string excelMD5New;
        public bool toLua;
        public bool toJson;
        public bool toScript;
        public bool toAsset;
        public bool toJava;
    }

    public class MD5Item
    {
        public MD5Item(string md5, bool tolua, bool tojson, bool toscript, bool toasset, bool tojava)
        {
            MD5 = md5;
            toLua = tolua;
            toJson = tojson;
            toScript = toscript;
            toAsset = toasset;
            toJava = tojava;
        }
        public string MD5;
        public bool toLua;
        public bool toJson;
        public bool toScript;
        public bool toAsset;
        public bool toJava;
    }

有了以上两个数据类,就可以实现GetExcelFileInfos函数,就是在第一个代码块内的函数。

说明下GetExcelFileInfos函数,里面将第一个代码块中,excel目录路径,以及语言拼接,再获取路径里面的所有excel文件,再讲各个文件的MD5进行比较判断,判断出文件是否已经导出过,而后在界面展示中,展示出不同的颜色,以区分已经导出过的文件。

    private Dictionary<string, MD5Item> MD5List = new Dictionary<string, MD5Item>();

    private List<FileInfoData> fileInfos = new List<FileInfoData>();
    /// <summary>
    /// 获取所有的Excel文件
    /// </summary>
    private void GetExcelFileInfos()
    {
        string curExcelFolderLocation = _excelPath + "/" + _threePackName + "/";
        fileInfos.Clear();

        List<string> fileList = new List<string>();

        fileList.AddRange(Directory.GetFiles(curExcelFolderLocation, "*", SearchOption.AllDirectories));
        fileList.Sort();

        for (int i = 0; i < fileList.Count; i++)
        {
            string filePath = fileList[i].Replace("\\", "/");
            string fileName = filePath.Substring(filePath.LastIndexOf("/") + 1);
            if (!(fileName.EndsWith(".xlsx") || fileName.EndsWith(".xlsm") || fileName.EndsWith(".xls")) || fileName.StartsWith("~$") 
                || fileName.IndexOf("name_filter") >= 0 || fileName.IndexOf("chat_filter") >= 0 )
            {
                continue;
            }
            string fileNameWithPostfix = fileName;
            fileName = fileName.Substring(0, fileName.IndexOf("."));

            FileInfoData curFileInfo = new FileInfoData();
            curFileInfo.filePath = filePath;
            curFileInfo.fileNameWithPostfix = fileNameWithPostfix;
            curFileInfo.fileName = fileName;
            curFileInfo.fileNewName = fileName.ToUpper().Substring(0, 1) + fileName.Substring(1);

            MD5Item item = null;
            if (MD5List.TryGetValue(fileName, out item))
            {
                curFileInfo.excelMD5Save = item.MD5;
                curFileInfo.toLua = item.toLua;
                curFileInfo.toJson = item.toJson;
                curFileInfo.toScript = item.toScript;
                curFileInfo.toAsset = item.toAsset;
                curFileInfo.toJava = item.toJava;
            }
            else
            {
                curFileInfo.excelMD5Save = "";
                curFileInfo.toLua = false;
                curFileInfo.toJson = false;
                curFileInfo.toScript = false;
                curFileInfo.toAsset = false;
                curFileInfo.toJava = false;
            }
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            curFileInfo.excelMD5New = MD5Hash.Get(fs);
            if (curFileInfo.excelMD5New != curFileInfo.excelMD5Save)
            {
                curFileInfo.toLua = false;
                curFileInfo.toJson = false;
                curFileInfo.toScript = false;
                curFileInfo.toAsset = false;
                curFileInfo.toJava = false;
            }
            fs.Close();

            fileInfos.Add(curFileInfo);
        }
        fileInfos.Sort(compareFileInfos);
    }

    static int compareFileInfos(FileInfoData a,FileInfoData b)
    {
        return string.Compare(a.fileName, b.fileName);
    }

在获取了所有文件信息,存储在fileInfos里面后,就可以在编辑器最底部做展示,然后根据相应文件的点击,导出所想要的格式。

    void SearchGUI()
    {
        GUI.color = Color.white;
        GUILayout.Label( "提示-------------------------------------------------------------------------:");
        _search = EditorGUILayout.TextField("搜索关键词:", _search);
    }

    private Vector2 _scroll_pos;
    void BottomGUI()
    {
        _scroll_pos = EditorGUILayout.BeginScrollView(_scroll_pos);
        {
            foreach (FileInfoData fi in fileInfos)
            {
                if (!string.IsNullOrEmpty(_search))
                {
                    if (!fi.fileName.Contains(_search))
                    {
                        continue;
                    }
                }

                EditorGUILayout.BeginHorizontal();
                if (fi.toLua) GUI.color = Color.red;
                else GUI.color = Color.green;
                if (GUILayout.Button("导出 " + fi.fileName + " 的lua文件", GUILayout.Height(40), GUILayout.Width(226)))
                {
                    Debug.Log("开始导出 " + fi.filePath + "  的lua文件");
                }

                if (fi.toJson) GUI.color = Color.red;
                else GUI.color = Color.green;
                if (GUILayout.Button("导出 " + fi.fileName + " 的json文件", GUILayout.Height(40), GUILayout.Width(226)))
                {
                    Debug.Log("开始导出 " + fi.filePath + "  的json文件");
                    UpdateClientData(fi,EXPORT_TYPE_JSON);
                }

                if (fi.toScript) GUI.color = Color.red;
                else GUI.color = Color.green;
                if (GUILayout.Button("导出 " + fi.fileName + " 的脚本文件", GUILayout.Height(40), GUILayout.Width(226)))
                {
                    Debug.Log("开始导出 " + fi.filePath + "  的脚本文件");
                    UpdateClientData(fi, EXPORT_TYPE_SCRIPT);
                }

                if (fi.toAsset) GUI.color = Color.red;
                else GUI.color = Color.green;
                if (GUILayout.Button("导出 " + fi.fileName + " 的Asset文件", GUILayout.Height(40), GUILayout.Width(226)))
                {
                    Debug.Log("开始导出 " + fi.filePath + "  的Asset文件");
                    UpdateClientData(fi, EXPORT_TYPE_ASSET);
                }

                if (fi.toJava) GUI.color = Color.red;
                else GUI.color = Color.green;
                if (GUILayout.Button("导出 " + fi.fileName + " 的java文件", GUILayout.Height(40), GUILayout.Width(226)))
                {
                    Debug.Log("开始导出 " + fi.filePath + "  的java文件");
                }
                EditorGUILayout.EndHorizontal();
            }
        }
        EditorGUILayout.EndScrollView();
    }

以上就是编辑器界面的编写,阐述了主要的思路,以及主要的代码部分。

在上面这个代码块中,导出数据的函数为UpdateClientData,此函数将在后面篇章叙述。

篇章根据步骤,分为三个篇章。

猜你喜欢

转载自blog.csdn.net/mahuibao01/article/details/89121243
今日推荐