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

来源:互联网 发布:日本搞笑综艺节目知乎 编辑:程序博客网 时间:2024/04/30 06:47

鄙人接触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编辑器界面,发现上方工具栏处变化

点击之后执行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("大闸蟹我们走!");    }}

结果如图:


其次再说明一下那个诡异的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后如图:


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


则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名    }}
结果如图:


即在中括号格式["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);    }}
运行结果如图:



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

  在脚本的某一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;    }}
运行效果如图:

在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<ChangeName>("统一修改名称", "Change And Close", "Change");    }    private void OnWizardCreate()//按下默认按键"Change And Close",同时有关闭对话框的效果    {        Debug.Log("按下默认按键");    }    private void OnWizardOtherButton()//按下增加的按键"Change"    {        Debug.Log("按下增加的按键");    }}


运行结果如图:



点击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<ChangeName>("统一修改名称", "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


在点击Change按键之后:


我们可以看见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<MyWindow>();//创建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");//记录从而可以撤销        }    }}
运行效果如图:


点击ShowMyWindow按键之后出现窗口,点击窗口上的Create按钮:



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



0 0
原创粉丝点击