【Unity知识点详解】导表工具开发(一)—— 自定义编辑器窗口

最近在负责新项目框架的开发,这里把项目开发中导表工具的开发总结一下。会分成四个部分写四篇博客来进行总结。

  • 自定义编辑器窗口
  • 类文件生成
  • 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

猜你喜欢

转载自blog.csdn.net/huoyixian/article/details/104593410