最近在负责新项目框架的开发,这里把项目开发中导表工具的开发总结一下。会分成四个部分写四篇博客来进行总结。
- 自定义编辑器窗口
- 类文件生成
- Json文件生成
- 项目中Json的使用
话不多说我们就先从自定义编辑器窗口开始,先看一下导表工具的最终效果。
导表工具由上边自定义的菜单栏导表工具打开。中间显示的就是导表工具窗口,导表工具主要分为两个部分。一个是目录部分,由配置读取目录、类脚本生成目录、Json导出目录组成。另一个是配置列表部分,列表中的配置可以全部一起导出、也可以单个导出。
当使用导表工具时,将配置放置在读取目录下,放置在读取目录下的配置会自动显示在配置列表部分。当导出配置时,会自动生成类脚本文件和Json文件,并生成到各自指定的目录下面。
下面来说一下导表工具的具体代码实现,因为导表工具界面的布局也需要代码来实现,所以将代码分为两部分CommonConfigTool和CommonConfigToolLayout。CommonConfigTool处理逻辑部分,主要为按钮点击后的逻辑。CommonConfigToolLayout处理界面布局部分,主要负责界面的显示内容。
using UnityEditor;
public abstract class CommonConfigToolLayout : EditorWindow
{
[MenuItem("Tools/ConfigTools/CommonConfigTool")]
public static void ShowWindow()
{
EditorWindow window = EditorWindow.GetWindowWithRect(typeof(CommonConfigTool), new Rect(0f, 0f, 600f, 400f), true, "CommonConfigTool");
}
}
如上面的代码,使用MenuItem方法可以在菜单栏添加打开导表工具界面的菜单项,为MenuItem指定的路径就是菜单项在菜单栏中的路径。当点击菜单项时会调用ShowWindow方法,这里需要注意ShowWindow必须是静态方法。在ShowWindow内通过调用GetWindowWithRect方法来创建窗口。
using System.IO;
using UnityEditor;
using UnityEngine;
public abstract class CommonConfigToolLayout : EditorWindow
{
#region OnGUI
private void OnGUI()
{
ShowDescription();
ShowConfigReadPath();
ShowConfigScriptGeneratePath();
ShowConfigExportPath();
ShowExportAllConfig();
ShowConfigList();
}
/// <summary>显示描述</summary>
private void ShowDescription()
{
GUILayout.Label("配置文件导出工具");
}
/// <summary>显示读取路径</summary>
private void ShowConfigReadPath()
{
GUILayout.Space(3);
GUILayout.BeginHorizontal();
GUILayout.Label("配置读取路径", GUILayout.Width(100f));
GUILayout.TextField(EditorConstDefine.CommonConfigReadPath);
if(GUILayout.Button("打开目录", GUILayout.Width(100f)))
{
OnClickOpenConfigReadDirectory(EditorConstDefine.CommonConfigReadPath);
}
GUILayout.EndHorizontal();
}
/// <summary>显示配置脚本生成路径</summary>
private void ShowConfigScriptGeneratePath()
{
GUILayout.Space(3);
GUILayout.BeginHorizontal();
GUILayout.Label("配置脚本生成路径", GUILayout.Width(100f));
GUILayout.TextField(EditorConstDefine.CommonConfigScriptGeneratePath);
if(GUILayout.Button("打开目录", GUILayout.Width(100f)))
{
OnClickOpenConfigScriptGenerateDirectory(EditorConstDefine.CommonConfigScriptGeneratePath);
}
GUILayout.EndHorizontal();
}
/// <summary>显示导出路径</summary>
private void ShowConfigExportPath()
{
GUILayout.Space(3);
GUILayout.BeginHorizontal();
GUILayout.Label("配置导出路径", GUILayout.Width(100f));
GUILayout.TextField(EditorConstDefine.CommonConfigExportPath);
if(GUILayout.Button("打开目录", GUILayout.Width(100f)))
{
OnClickOpenConfigExportDirectory(EditorConstDefine.CommonConfigExportPath);
}
GUILayout.EndHorizontal();
}
/// <summary>显示导出全部配置</summary>
private void ShowExportAllConfig()
{
GUILayout.Space(3);
if(GUILayout.Button("导出全部配置"))
{
OnClickExportAllConfig();
}
}
/// <summary>显示配置列表</summary>
private void ShowConfigList()
{
GUILayout.Space(3);
configScrollPosition = GUILayout.BeginScrollView(configScrollPosition, GUILayout.Height(170f));
if(Directory.Exists(EditorConstDefine.CommonConfigReadPath))
{
string[] configs = Directory.GetFiles(EditorConstDefine.CommonConfigReadPath, "*.xlsx");
foreach(string config in configs)
{
GUILayout.BeginHorizontal();
GUILayout.Label(config);
if(GUILayout.Button("导出配置", GUILayout.Width(100f)))
{
OnClickExportSingleConfig(config);
}
GUILayout.EndHorizontal();
GUILayout.Space(3);
}
}
GUILayout.EndScrollView();
}
#endregion
#region 逻辑调用
protected abstract void OnClickOpenConfigReadDirectory(string path);
protected abstract void OnClickOpenConfigScriptGenerateDirectory(string path);
protected abstract void OnClickOpenConfigExportDirectory(string path);
protected abstract void OnClickExportAllConfig();
protected abstract void OnClickExportSingleConfig(string config);
#endregion
}
创建窗口之后,窗口里是空的,窗口内的布局需要通过调用GUILayout类里的方法来实现,并且这些方法需要写在OnGUI方法里。这里就先简单介绍一下我用到几个GUILayout中的方法。关于GUILayout更多的方法以及参数可以自行查阅官网文档,文章最后有文档连接。
- GUILayout.Label 用于显示文本和图片
- GUILayout.TextField 文本输入框,用于编辑字符串
- GUILayout.Button 用于添加点击按钮
- GUILayout.BeginHorizontal 开始一个水平管理组,可以在一行内显示多个UI,需要和GUILayout.EndHorizontal配合使用
- GUILayout.EndHorizontal 结束一个水平管理组,和GUILayout.BeginHorizontal配对使用
- GUILayout.Space 用于插入空行
上面介绍的都是界面显示的部分,下面介绍一下逻辑部分,逻辑部分的代码都在CommonConfigTool中实现。CommonConfigTool是继承自CommonConfigToolLayout的,在CommonConfigTool中实现CommonConfigToolLayout按钮点击的抽象方法。
using System.IO;
using UnityEditor;
using UnityEngine;
using Editor.Define;
namespace Editor.Config
{
public class CommonConfigTool : CommonConfigToolLayout
{
/// <summary>点击打开读取路径回调</summary>
protected override void OnClickOpenConfigReadDirectory(string path)
{
OpenDirectory(path);
}
/// <summary>点击打开脚本生成路径回调</summary>
protected override void OnClickOpenConfigScriptGenerateDirectory(string path)
{
OpenDirectory(path);
}
/// <summary>点击打开导出路径回调</summary>
protected override void OnClickOpenConfigExportDirectory(string path)
{
OpenDirectory(path);
}
/// <summary>点击导出所有配置回调</summary>
protected override void OnClickExportAllConfig()
{
if(Directory.Exists(EditorConstDefine.CommonConfigReadPath))
{
string[] configs = Directory.GetFiles(EditorConstDefine.CommonConfigReadPath, "*.xlsx");
foreach(string config in configs)
{
ExportConfig(config);
}
}
}
/// <summary>点击导出单个配置回调</summary>
/// <param name="configName">配置名称</param>
protected override void OnClickExportSingleConfig(string configName)
{
ExportConfig(configName);
}
/// <summary>打开目录</summary>
/// <param name="path">路径</param>
private void OpenDirectory(string path)
{
if(Directory.Exists(path))
{
string tempPath = path.Replace("/", "\\");
System.Diagnostics.Process.Start("explorer.exe", tempPath);
}
else
{
Debug.LogWarning("打开目录失败,目录路径不存在:" + path);
}
}
/// <summary>导出配置</summary>
/// <param name="ConfigName">配置名称</param>
private void ExportConfig(string config)
{
ConfigScriptGenerator scriptGenerator = new ConfigScriptGenerator();
scriptGenerator.GenerateScript(config, EditorConstDefine.CommonConfigScriptGeneratePath);
ConfigJsonGenerator jsonGenerator = new ConfigJsonGenerator();
jsonGenerator.GenerateJson(config, EditorConstDefine.CommonConfigExportPath);
AssetDatabase.Refresh();
}
}
}
上面是CommonConfigTool的代码实现,大部分是对于按钮点击抽象方法的实现。OpenDirectory方法中是打开对应文件夹目录的具体实现。关于类脚本生成和Json文件生成是在ConfigScriptGenerator类和ConfigJsonGenerator类中实现的,这两部分将在后面的文章中具体介绍。
相关文档
GUILayout文档 https://docs.unity3d.com/560/Documentation/ScriptReference/GUILayout.html
EditorWindow文档 https://docs.unity3d.com/ScriptReference/EditorWindow.html
MenuItem文档 https://docs.unity3d.com/540/Documentation/ScriptReference/MenuItem.html