Unity3D插件开发教程 #4:获取地址组件

作者:Lawliet
2017-09-07
3 1 0

编者按

本文已于作者 @Lawliet 授权转载,原载于知乎,如需转载请务必联系原作者。

前言

前几天做导出安装包插件时,遇到了个问题,我需要获取地址,可是每次都要手动填入(复制粘贴)地址是个很费时不讨好的事,所以我就写了一个获取地址的小组件。 样子就是这样的:

1

2

一个文本和一个按钮,文本显示选择的路径(路径为空时显示提示语,并且无法选择),点击按钮打开面板选择文件夹。

知识要点

  • 组合 GUI 组件
  • EditorGUI.BeginDisabledGroup()/EndDisabledGroup()
  • EditorUtility.OpenFolderPanel()

使用版本

  • Unity3D 5.3.3

目标

  • 如何把多个组件封装在一起,组合成自己需要用的组件,然后一句代码就可以调用

准备

整个插件的结构:

3

在开始写主要逻辑之前,我们先要做准备工作,那就是,怎么打开下图这个窗口(系统选择文件夹的窗口)。

4

我在网上搜了一下“Unity3d 如何选择文件夹”的资料,发觉都是要导入一个 System.Windows.Forms.dll,然后调用 OpenFileDialog。 可是这种方式很不优雅,所以我就去找 api,发现了原来 EditorUtility 是有操作外部文件的方法(项目内部使用 AssetDatabase)。EditorUtility 里面的 OpenFilePanel()OpenFolderPanel() 方法就是今天我们要用到的,选择文件和选择文件夹。

代码:

准备工作好了,那么接下来就是正式的代码逻辑了,我们先创建一个 GUIExtendWindow 的窗口类,之前的教程已经教了很多次了,这里就不再叙述了。

然后申明一个字段“_folderPath”用于后面保存路径。

public class GUIExtendWindow : EditorWindow
{
    [MenuItem("Tools/GUIExtend")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow("GUIExtend");
    }

    private string _folderPath;
}

接下来就是今天的主角————OpenFolderPanelField() 方法。我们要把按钮和文本的逻辑都封装在这个方法里面。首先先看看整个方法的代码。

/// 
/// 
/// 
/// 选择的路径
/// 按钮上的文字
/// 提示
/// 
private string OpenFolderPanelField(string path, string buttonLabel, string tips)
{
    bool disabled;

    string content;

    if (string.IsNullOrEmpty(path))
    {
        disabled = true;

        content = tips;
    }
    else
    {
        disabled = false;

        content = path;
    }

    EditorGUILayout.BeginHorizontal();

    EditorGUI.BeginDisabledGroup(disabled);
    EditorGUILayout.TextArea(content, EditorStyles.label);
    EditorGUI.EndDisabledGroup();

    if (GUILayout.Button(buttonLabel, GUILayout.Width(100)))
    {
        string currentDirectory;

        if (string.IsNullOrEmpty(path))
        {
            currentDirectory = Directory.GetCurrentDirectory();
        }
        else
        {
            currentDirectory = path;
        }

        path = EditorUtility.OpenFolderPanel(tips, currentDirectory, "");
    }

    EditorGUILayout.EndHorizontal();

    return path;
}

三个参数的作用注释已经说明了,而参数部分是可以根据你功能自定义的,你可以替换成 GUIContent 类型,也可以删除或增加,这就看具体要做到什么的效果了。

接着是判断路径参数是否为空。空的话,文本内容显示为 tips,无法选择。不为空,文本内容显示路径,可以选择。

EditorGUILayout.BeginHorizontal() 方法之前的文章提到过,是水平布局的一个组件。 这些组件都是一对对的,有 Begin 就有 End。例如BeginDisabledGroup()/EndDisabledGroup(),这是个禁用组件,如果参数为 true,包含着的组件都会变成禁用状态。

在禁用组件中间我们绘制一个 TextArea 组件,样式是 EditorStyles.label,这样,原本是文本就不会显示文本框,而又可以选择文本。

接着是点击按钮的逻辑,首先是准备一个默认目录待会打开,默认打开 path,如果 path 为空,则获取项目的目录。

然后我们就可以是使用 OpenFolderPanel 打开面板了,第一个参数为窗口的标题,第二个参数为默认打开的文件夹目录,第三个参数选择的文件夹的默认名字。使用很简单,用一下就可以了。然后这个方法会回调一个你选择的文件夹的绝对地址。然后我们赋值到参数path里,最后返回。

组件封装完毕了,接下来就是使用了,使用也很简单,跟 EditorGUILayout 的方法一样使用就行了。

void OnGUI()
{
    _folderPath = OpenFolderPanelField(_folderPath, "Select Folder", "please select Folder");
}

最后

其实,Unity3D 的 GUILayoutEditorGUILayout 等类都是采用上述的方法将多个组件(内容)封装在一起。 所以这种封装的方法我建议是写在一个类里面,然后变成静态函数,这样就可以任何地方都能使用。例如笔者就用了一个 EditorGUILayoutExtend 作为封装组件的类。

有人问到,如果我不是选择文件夹,而是选择文件怎么办,其实做法也是一样的,当然,我也会在源代码里面把选择文件的逻辑加上。

如果大家有什么意见和建议,或者是有什么疑问,或者是有想看的知识点内容,都欢迎到评论区发上你们的评论。

最后我希望有更多人参与到插件开发的队伍里。也欢迎大家投稿。

  • 源代码
  • 欢迎分享本文
  • QQ群:234204968