unity 编辑器扩展

别来无恙 提交于 2019-12-18 13:10:21

引入UnityEditor;
不继承MonoBehaviour

添加Unity菜单栏按钮

    [MenuItem("Tools/test/test1")]
    static void Test()
    {
        Debug.Log("Test");
    }

效果:点击unity的菜单栏中Tools/test/test1会打印出Test

设置按钮的优先级

	[MenuItem("Tools/test/test1", false, 2)]
    static void Test1()
    {
        Debug.Log("Test1");
    }

    [MenuItem("Tools/test/test2", false, 1)]
    static void Test2()
    {
        Debug.Log("Test2");
    }

由于test2的优先级是1,test1的优先级是2
test2的优先级更高
所以在菜单栏中test2在test1的上方

按钮的分组
当优先级相差较大时,会将按钮分组

	[MenuItem("Tools/test/test1", false, 2)]
    static void Test1()
    {
        Debug.Log("Test1");
    }

    [MenuItem("Tools/test/test2", false, 100)]
    static void Test2()
    {
        Debug.Log("Test2");
    }

    [MenuItem("Tools/test/test3", false, 1)]
    static void Test3()
    {
        Debug.Log("Test3");
    }

这时菜单栏中test3和test1为一组,在最上方,test2在另一组
不同组之间有一条线隔开
在这里插入图片描述

给组件右键菜单栏添加按钮

    [MenuItem("CONTEXT/Rigidbody/TestButton")]// CONTEXT 组件名 按钮名
    static void TestButton()
    {
        Debug.Log("Test");
    }

此时右键点击Rigidbody组件,菜单里会出现TestButton按钮,点击这个按钮将打印Test
在这里插入图片描述

获得当前的组件

    [MenuItem("CONTEXT/Rigidbody/TestButton")]// CONTEXT 组件名 按钮名
    static void TestButton(MenuCommand cmd)//通过menucommand可获取当前正在操作的组件
    {
        Rigidbody rb = cmd.context as Rigidbody;
        rb.useGravity = false;
        Debug.Log("Init");
    }

对选中的物体操作

Selection类可以获取选中的物体

    [MenuItem("Tools/delete gameObject", false, 2)]
    static void Delete()
    {
        //Debug.Log(Selection.activeGameObject.name); //输出选中的第一个物体的名字

        foreach (var item in Selection.gameObjects)
        {
            //GameObject.DestroyImmediate(item); //Destroy只能在游戏运行的时候使用
            Undo.DestroyObjectImmediate(item);//利用Undo进行的删除操作 是可以撤销的
        }
    }

给按钮添加快捷键

    //%=ctrl #=shift &=alt
    [MenuItem("Tools/test1 %q", false, 1)]
    static void Test1()
    {
        Debug.Log("Test1");
    }

ctrl+q为该按钮的快捷键

控制unity菜单栏的按钮是否启用

    [MenuItem("Tools/show info", true, 5)]
    static bool ShowInfoValidate()
    {
        if (Selection.objects.Length > 0)
            return true;
        else
            return false;
    }

    [MenuItem("Tools/show info", false, 5)]
    static void ShowInfo()
    {
        foreach (var item in Selection.objects)
        {
            Debug.Log(item.name);
        }
    }

MenuItem中的第二个参数就是控制按钮是否启用的,填true,可编写一个控制按钮是否启用的函数
每次会先执行ShowInfoValidate(),如果返回的时true则按钮可点击
返回的是false按钮不可点击
在这里插入图片描述

ContextMenu与ContextMenuItem

两者不需引入UnityEditor命名空间,他们都在UnityEngine命名空间中
直接在脚本里的函数前面添加ContextMenu可在该脚本组件上生成右键菜单按钮
直接在脚本里的属性前面添加ContextMenuItem,然后绑定一个函数,则可以在该脚本的属性上生成右键菜单

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

public class TestScript : MonoBehaviour
{
    public Color color = Color.red;
    [ContextMenuItem("Add Score","AddScore")]
    public int score = 100;

    [ContextMenu("Change to blue")]
    private void ChangeToBlue()
    {
        color = Color.blue;
    }

    private void AddScore()
    {
        score += 50;
    }
}

在这里插入图片描述
在这里插入图片描述

创建对话框

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

public class Add : ScriptableWizard
{
    public int score;
    public float speed;

    [MenuItem("Tools/Create Wizard")]
    static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard<Add>("AddData");
    }
}

通过点击菜单栏的Create Wizard按钮创建一个对话框
在这里插入图片描述
通过对话框改变选中物体的属性

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

public class Add : ScriptableWizard
{
    public int score;
    public float speed;

    [MenuItem("Tools/Create Wizard")]
    static void CreateWizard()
    {
    	//第二个参数为对话框右下角按钮的名称  可以写第三个参数,第三个参数为另一个新增button的名称
        ScriptableWizard.DisplayWizard<Add>("AddData","Change");
    }

	//该函数由unity自动调用,点击Change按钮后执行,执行完自动关闭对话框
    private void OnWizardCreate()
    {
        GameObject[] gameObjects = Selection.gameObjects;
        foreach (var item in gameObjects)
        {
            TestScript ts = item.GetComponent<TestScript>();
            //在这句之后的对ts的操作会被记录下来,修改后可以按ctrl+z撤销
            Undo.RecordObject(ts, "add data");
            ts.score += score;
            ts.speed += speed;
        }
    }
}

ScriptableWizard中还包含helpString和errorString,对他们进行赋值可在对话框中显示出来
弹出提示信息

    [MenuItem("Tools/Create Wizard")]
    static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard<Add>("AddData","Change and close", "change");
    }

    private void OnWizardOtherButton()
    {
        OnWizardCreate();
    }

    private void OnWizardCreate()
    {
        GameObject[] gameObjects = Selection.gameObjects;
        //弹出提示信息
        ShowNotification(new GUIContent(Selection.gameObjects.Length + "个游戏物体的值被修改了"));
        foreach (var item in gameObjects)
        {
            TestScript ts = item.GetComponent<TestScript>();
            //在这句之后的对ts的操作会被记录下来,修改后可以按ctrl+z撤销
            Undo.RecordObject(ts, "add data");
            ts.score += score;
            ts.speed += speed;
        }
    }

注意:直接点击Change and close按钮的话窗口关闭 提示信息会来不及显示

Editor模式下数据的保存

使用EditorPrefs
用法同PlayerPrefs的用法相同

显示进度条

用到EditorUtility.DisplayProgressBar()

    private void OnWizardCreate()
    {
        GameObject[] gameObjects = Selection.gameObjects;
        //弹出提示信息
        ShowNotification(new GUIContent(Selection.gameObjects.Length + "个游戏物体的值被修改了"));
        EditorUtility.DisplayProgressBar("进度", "0/" + gameObjects.Length + " 完成修改值", 0);
        int count = 0;
        foreach (var item in gameObjects)
        {
            TestScript ts = item.GetComponent<TestScript>();
            //在这句之后的对ts的操作会被记录下来,修改后可以按ctrl+z撤销
            Undo.RecordObject(ts, "add data");
            ts.score += score;
            ts.speed += speed;
            EditorUtility.DisplayProgressBar("进度", count + "/" + gameObjects.Length + " 完成修改值", (float)count / gameObjects.Length);
        }
        //显示完进度后要删除进度条
        EditorUtility.ClearProgressBar();
    }

创建自定义窗口

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

public class MyWindow : EditorWindow
{
    [MenuItem("Window/My Window")]
    private static void CreateWindow()
    {
		//创建窗口
        MyWindow myWindow = EditorWindow.GetWindow<MyWindow>();
        //显示窗口
        myWindow.Show();
    }

    private string name = "";

    private void OnGUI()
    {
        GUILayout.Label("hello world");
        name = GUILayout.TextField(name);
        if(GUILayout.Button("CreateGameObject"))
        {
            GameObject go = new GameObject(name);
            //便于撤销操作
            Undo.RegisterCreatedObjectUndo(go, "CreateGameObject");
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!