对于Unity3D编辑器拓展的一些小结

鄙人接触Unity也算有一段时间了,不过在开发的过程中,可能会有各种各样的需求是Unity本身无法完成的,不过Unity3D引擎非常强大的地方之一就是其可拓展性,也就是说Unity允许开发者去自定义菜单等等完成开发者想要的各种的需求,鄙人于网上各种找资料并动手操作实践了一番,在这边小小的总结一下:


一、MenuItem操作相关

首先是最为简单的操作,在Unity编辑器的上方工具栏里面添加自己的一些按键,需要在Assets/Editor文件夹里新建个脚本,鄙人这边为了方便理解就命名为:ToolsMenu.cs。由于是对Unity编辑器进行拓展,那么就需要引用using UnityEditor;另外脚本也不需要继承自MonoBehaviour了,还有把脚本自带的Update()与Start()方法删掉。具体操作代码如下

using UnityEngine;
using UnityEditor;

public class ToolsMenu {
    [MenuItem("Tools/Button1",false,1)]//菜单栏路径,是否为验证方法,菜单优先级
    static void Button1()
    {
        Debug.Log("皮皮虾我们走!");
    }
}
保存完毕后,在回到Unity编辑器界面,发现上方工具栏处变化

对于Unity3D编辑器拓展的一些小结_第1张图片

点击之后执行Button1方法控制台输出。其实也可以给自己的按键添加快捷键:

using UnityEngine;
using UnityEditor;

public class ToolsMenu {
    [MenuItem("Tools/Button1 _Y",false,1)]
    static void Button1()
    {
        Debug.Log("皮皮虾我们走!");
    }
}
如代码所示,键盘Y键就为方法的快捷键,其实把“_Y”换成“%Y”就是ctrl+Y,类似的有“&”对应alt,“#”对应shift等;

这边解释下静态方法前中括号的内容,括号内的字符串指定了按键在菜单栏的指定位置,bool值表示该方法是否为验证方法,最后的int型数表示

该选项的优先级,菜单内的选项根据有限级由小到大排列。顺带一提,要是相邻选项的优先级相差值大于等于11的话菜单栏内会出现分隔线:

using UnityEngine;
using UnityEditor;

public class ToolsMenu {
    [MenuItem("Tools/Button1 _Y",false,1)]
    static void Button1()
    {
        Debug.Log("皮皮虾我们走!");
    }
    [MenuItem("Tools/Button2 %U",false,12)]
    static void Button2()
    {
        Debug.Log("大闸蟹我们走!");
    }
}

结果如图:

对于Unity3D编辑器拓展的一些小结_第2张图片

其次再说明一下那个诡异的bool值控制的验证方法,上代码:

using UnityEngine;
using UnityEditor;

public class ToolsMenu {

    [MenuItem("Tools/Button1", false, 1)]
    static void Button1()
    {
        foreach (Object g in Selection.objects)//删除全部选中游戏物体
        {
            GameObject.DestroyImmediate(g);
        }
    }

    [MenuItem("Tools/Button1", true, 1)]
    static bool Button1Validate()
    {
        if (Selection.objects.Length > 0)
            return true;
        else
            return false;
    }
}


在这里设置验证方法中括号内除了bool值之外都跟Button1的一样,效果是先执行Button1Validate()方法后根据判断返回的值决定相应菜单选项是否可选。


保存脚本后,如果选中场景中的至少一样GameObject后如图:

对于Unity3D编辑器拓展的一些小结_第3张图片

Button1按键为可选状态,如果不选择任何GameObject:

对于Unity3D编辑器拓展的一些小结_第4张图片

则Button1为灰色不可选状态。

顺带一提这边直接使用DestroyImmediate()方法删除物体后是无法Ctrl+Z撤销的,不过换成Undo.DestroyObjectImmediate(g);即可。


二、给某个组件的右键菜单栏添加选项

方法1:在Editor内部脚本上动手,上代码:

using UnityEngine;
using UnityEditor;

public class ToolsMenu {

    [MenuItem("CONTEXT/MyScript/LogGameObjectName")]
    static void LogName(MenuCommand cmd)//MenuCommand为当前正在操作的组件
    {
        Debug.Log(cmd.context.name);//输出当前组件所在GameObject名
    }
}
结果如图:

对于Unity3D编辑器拓展的一些小结_第5张图片

即在中括号格式["CONTEXT/组件名/添加的选项名"],便可完成添加选项。

方法2:这回是在脚本本身动手脚,上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyScript : MonoBehaviour {
    
	void Start () {
		
	}
	void Update () {
		
	}

    [ContextMenu("LogGameObjectName2")]
    void LogName()
    {
        Debug.Log(gameObject.name);
    }
}
运行结果如图:

对于Unity3D编辑器拓展的一些小结_第6张图片


三、给脚本某个字段添加右键菜单

  在脚本的某一public变量前加入[ContextMenuItem("按键名","方法名")],上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyScript : MonoBehaviour {

    [ContextMenuItem("Add Life", "AddLife")]//给该字段添加了个右键菜单,[ContextMenuItem("按键名","方法名")]
    public float life = 0;

	void Start () {
		
	}
	void Update () {
		
	}

    void AddLife()
    {
        life += 100;
    }
}
运行效果如图:
对于Unity3D编辑器拓展的一些小结_第7张图片

在MyScript组件的Life属性处右键可以出现菜单栏选项Add Life ,点击后执行脚本中的AddLife()方法。


四、创建对话框

举个简单的例子,实现改变选中Game Object的名称的功能:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class ChangeName : ScriptableWizard//继承自可编程对话框
{
    [MenuItem("Tools/ChangeNameWizard", false, 50)]
    static void CreateWizard()
    {
        //创建对话框,标题为“统一修改名称”,把默认按钮Create命名为"Change And Close",增加按键"Change"
	ScriptableWizard.DisplayWizard("统一修改名称", "Change And Close", "Change");
    }
    private void OnWizardCreate()//按下默认按键"Change And Close",同时有关闭对话框的效果
    {
        Debug.Log("按下默认按键");
    }
    private void OnWizardOtherButton()//按下增加的按键"Change"
    {
        Debug.Log("按下增加的按键");
    }
}


运行结果如图:

对于Unity3D编辑器拓展的一些小结_第8张图片

点击Tools/ChangeNameWizard按键后,出现对话框,点击下发的Change和ChangeAndClose按键分别执行OnWizardOtherButton()与

OnWizardCreate()方法,不同点再于执行完OnWizardCreate()方法之后,关闭对话框。

接下来上完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class ChangeName : ScriptableWizard//继承自可编程对话框
{
    public string changeName = "GameObject";//物体命名

    [MenuItem("Tools/ChangeNameWizard", false, 50)]
    static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard("统一修改名称", "Change And Close", "Change");//创建对话框,标题为“统一修改名称”,
                                                                                                    //把默认按钮Create命名为"Change And Close",增加按键"Change"
    }
    private void OnWizardCreate()//按下默认按键"Change And Close",同时有关闭对话框的效果
    {
        Debug.Log("按下默认按键");
        foreach(GameObject g in Selection.objects)
        {
            g.name = changeName;
        }
        ShowNotification(new GUIContent("有" + Selection.gameObjects.Length + "个游戏物体被更名为" + changeName));//字幕输出
    }
    private void OnWizardOtherButton()//按下增加的按键"Change"
    {
        Debug.Log("按下增加的按键");
        foreach (GameObject g in Selection.objects)
        {
            g.name = changeName;
        }
        ShowNotification(new GUIContent("有" + Selection.gameObjects.Length + "个游戏物体被更名为"+changeName));//字幕输出
    }
    private void OnWizardUpdate()//当字段值发生改变时一直调用
    {
        Debug.Log("Update");
        errorString = null;
        helpString = null;
        if (Selection.gameObjects.Length > 0)
        {
            helpString = "您当前选择了" + Selection.gameObjects.Length + "个物体";
        }
        else
        {
            errorString = "请至少选择一个物体";
        }
    }
}
测试截图:在点击Change之前,选中4个GameObject

对于Unity3D编辑器拓展的一些小结_第9张图片
在点击Change按键之后:

对于Unity3D编辑器拓展的一些小结_第10张图片

我们可以看见4个Game Object被更名为“皮皮虾”......

代码中比较可能有疑问的地方打上了必要的备注在此就不必多言....


五、创建窗口

关于窗口界面布局的编程在OnGUI()方法中实现,这边举个简单的例子:创建空物体

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class MyWindow : EditorWindow {

    [MenuItem("Tools/ShowMyWindow",false,80)]
	static void ShowMyWindow()
    {
        //Debug.Log("Show My Window");
        MyWindow window = EditorWindow.GetWindow();//创建Window
        window.Show();
    }

    private string name = "Object";

    private void OnGUI()
    {
        GUILayout.Label("我的窗口");
        name = GUILayout.TextField(name);//显示输入框
        if (GUILayout.Button("创建"))//显示按钮
        {
            GameObject g = new GameObject(name);
            ShowNotification(new GUIContent("您创建了"+name));//字幕输出
            Undo.RegisterCreatedObjectUndo(g,"Create Gameobject");//记录从而可以撤销
        }
    }
}
运行效果如图:

对于Unity3D编辑器拓展的一些小结_第11张图片
点击ShowMyWindow按键之后出现窗口,点击窗口上的Create按钮:

对于Unity3D编辑器拓展的一些小结_第12张图片


鄙人的小结到此就先告一段落,要是有什么小瑕疵啥的还望阁下海涵海涵,最后头像镇楼。

对于Unity3D编辑器拓展的一些小结_第13张图片


你可能感兴趣的:(Unity3D)