您的位置:首页 > 移动开发 > Unity3D

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

2019-04-09 14:14 351 查看

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

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

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

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

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

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

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

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

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

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

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

我的工具最终效果如图:

一:编辑器扩展界面编写

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

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

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

[code]        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数据类

[code]    /// <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进行比较判断,判断出文件是否已经导出过,而后在界面展示中,展示出不同的颜色,以区分已经导出过的文件。

[code]    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里面后,就可以在编辑器最底部做展示,然后根据相应文件的点击,导出所想要的格式。

[code]    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,此函数将在后面篇章叙述。

至于工具中间部分,所有的一键导出,其实就是循环所有的文件,做出导出的处理。

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: