Unity编辑器扩展

编辑器简介:Unity支持扩展编辑器,扩展编辑器的代码要放入Editor文件夹中,Editor文件夹在项目打包时,是不会被打包的

1:使用MenuItem添加菜单栏按钮:MenuItem是引用UnityEditor命名空间的

public class AddTools  {
    [MenuItem("Assets/Test1",false,10)]
    static void test1()//必须为静态函数
    {
        Debug.Log("test1");      
    }
}

2:MenuItem的路径设置和显示的顺序设置,MenuItem有三个参数,第三个参数是设置按钮显示的先后顺序的。按钮显示一般以11为一个组,参数相差11就不是一个组了。

[MenuItem("Assets/test1",false,1)]

[MenuItem("Assets/test2",false,12)]这两个参数相差11,text1按钮在text2前面显示,text1和text2不是在同一个组。

 [MenuItem("Assets/tab1",false,0)]
    static void tab()
    {
        //这个静态方法是实现上面设置的按钮的功能的
    }
    [MenuItem("Assets/tab2", false, 11)]
    static void tab1()
    {
        //这个静态方法是实现上面设置的按钮的功能的
    }


3:给组件或脚本的右键菜单添加按钮,去实现一些功能。

[menuitem("CONTEXT/组件或脚本名/按钮名")]//往脚本的右键菜单中添加一个按钮实现某种功能

 [MenuItem("CONTEXT/text1/InitHealthAndSpeed1")]
    static void InitHealthAndSpeed()
    {
        //点击InitHealthAndSpeed1按钮就会执行这个静态方法
        Debug.Log("aa");
    }

4:MenuCommand:是获取我们正在操作的组件或脚本的对象,拿到组件或脚本对象我们就可以对其进行操作。

[MenuItem("CONTEXT/text1/InitHealthAndSpeed1")]
    static void InitHealthAndSpeed(MenuCommand cmd)
    {
        //点击InitHealthAndSpeed1按钮就会执行这个静态方法
        text1 ta1 = cmd.context as text1;//MenuCommand获取到正在操作的text1脚本组件
        ta1.a = 10;//对组件的内容进行修改
        Debug.Log(ta1.a);
    }

5:Selection:获取unity中的一些物体对象。

   Selection.activeGameobject//获取Inspector面板中被选中的游戏物体,只能返回选中的一个物体对象,选中多个对象,只会得到第一个对象

    Selection.activeTransform//获取Inspector面板中被选中游戏物体的Transform组件,只能返回一个一个物体的Transform组件。选中多个对象,只会得到第一个对象

    selection.Objects//获取所有选中物体,包括Script scene 的所有资源呢

    selection.activeObject//只能获取一个被选中的资源,资源是可以是任何物体

    Selection.gameObjects//获取所有选中的Gameobject对象

    Selection.transform//获取所有被选中的游戏对象的transfoem属性

   

 GameObject go = Selection.activeGameObject;//获取被选中的一个物体对象,获取的只能是游戏对象
        Transform go1 = Selection.activeTransform;//获取被选中的一个物体的Transform组件,获取的只能是游戏对象
        GameObject[] go2 = Selection.gameObjects;//获取所哟被选中的游戏对象
       
        Transform[] go4 = Selection.transforms;//获取所哟被选中的游戏对象的transform属性
        object[] go3 = Selection.objects;//获取Unity中所有被选中的资源,资源可以是任何种类的
        object go5 = Selection.activeObject;//只能获取Unity中所有种被选中资源的一个,资源可以是任何种类的

6:编写一个删除物体按钮,在物体被删除之后是可以撤销这个删除操作的。

     一般我们自己删除物体操作是无法撤回的,系统的删除物体的按键,删除的物体是可以撤销删除的操作的。因为系统的删除操作在删除之前会把删除操作的记录注册到内存中,物体并没有真正被删除,我们自己写的删除按钮也可以把删除的记录注册到内存中,这样我们自己写的删除操作也是可以撤销的

Undo.DestoryObjectImmediate(gameobject)//利用Undo把删除操作注册到内存中

在编辑器的脚本中删除物体使用DestoryImmediate(gameobject)这个API

  [MenuItem("Assets/tab1",false,0)]
    static void tab()
    {
        //这个静态方法是实现上面设置的按钮的功能的
      
        GameObject go = Selection.activeGameObject;//获取被选中的一个物体对象,获取的只能是游戏对象
         Undo.DestroyObjectImmediate(go);//把删除操作注册要内存中,按ctrl +z可以取消删除
        
      
    }

 7:给我们自己写的按钮添加快捷键

    自己设置快捷键时:%代表ctrl  #代表shift  &代表alt

    

[MenuItem("Assets/tab2 %t", false, 11)]//给Tab2按键设置Ctrl +t为tab2按钮的快捷键
    static void tab1()
    {
       }

设置的快捷键要与前面的按钮名空一格。如果只用一个按键作为快捷键则要在按键前加一个下划线

[MenuItem("Assets/tab2 _t", false, 11)]
    static void tab1()
    {
            }

8:在编辑器上的按钮可能只能作用一些物体,对另一些物体是不适用,当选中的是不适用的物体时,这个按钮是禁用的。这里需要使用menuitem的第二个参数,来判断这个按钮是否启用

这两个Maneitem是配合使用的,false之前的true是判断按钮能按下的条件的,在返回true时,按钮就会被起用

[menuitem("assets/a",true,1)]

static bool delect()

{

  判断是否满足条件,满足返回true,则按钮可以点击

  不满足就返回false 按钮被禁用

}

[menuitem("assets/a",false,1)]

static void delect1()

{

//执行自定义按钮的功能

}

 [MenuItem("Assets/tab1", true, 0)]
    static bool tab2()
    {
        if (Selection.activeGameObject == null)//判断是否选中物体

        {
            return false;
        }
        else
        {
            return true;//选中物体返回true,启用tab1按钮组件
        }
    }

    [MenuItem("Assets/tab1",false,0)]
    static void tab()
    {
        //这个静态方法是实现上面设置的按钮的功能的
      
        GameObject go = Selection.activeGameObject;//获取被选中的一个物体对象,获取的只能是游戏对象
      //  GameObject.DestroyImmediate(go);//删除这个对象
        Undo.DestroyObjectImmediate(go);//把删除操作注册要内存中,按ctrl +z可以取消删除
        
      
    }

mainitem中的True 和false 相互配合,来实现按钮选择性实现

9:[contextMenu(“按键名”)]给自定义的脚本添加按键   [contextMenuitem("按键名","要执行的方法名")]给自定义的脚本属性添加按键

contextMen和contextMenuitem标签不需要再编辑器的脚本中使用,可以直接再要添加按钮的脚本中使用,生成自己定义的按钮

public class text1 : MonoBehaviour {
    [ContextMenuItem("addcount", "Add")]//直接在自定义脚本的属性a添加按钮,按钮执行的功能是执行add方法,按钮名是addCount
    public int a = 0;
    void Add()
    {
        a += 10;
        print(a);
    }
    [ContextMenu("TestButton")]//直接在自定义的脚本添加右键按钮TestButton,执行的功能是标签下面的方法

    void Onbutton()
    {
        print("a");
    }
}

 10:创建一个对话框,对话框中读取的数据是从指定的脚本中读取的。对话框只能从继承ScripttableWizard类的类中读取数据,创建对话框的脚本也是编辑器脚本

       创建对话框的函数是scriptTableWrizard.DisplayWizard<存储数据的脚本,脚本要继承ScripttableWizard的类>("对话框的名称");

using UnityEditor;
public class CreateEdior :ScriptableWizard {

    [MenuItem("Assets/tab3",false,2)]//创建tab3按钮
    static void tab3()
    {
        ScriptableWizard.DisplayWizard<CreateEdior>("修改数据");//创建对话框,读取CreateEditor脚本的数据,文本框的名字为“修改数据”
    }
    public float speed;//CreateEditor脚本中的数据
    public int index;
    [MenuItem("Assets/tab4", false, 3)]//创建tab4按钮
    static void tab4()//创建对话框
    {
        ScriptableWizard.DisplayWizard<stab>("修改数据");
    }

}
public class stab:ScriptableWizard//文本框要交互的数据
{
    public int a = 10;
    public int b = 19;
}

11:在创建的对话框中创建按钮,触发点击事件  ScriptTableWizard.DisplayWizard<存储数据的脚本,脚本要继承ScripttableWizard的类>("对话框的名称",“在对话框中创建的按钮名”)  这个按钮是绑定固定的方法 OnWizardCreate(),按钮被点击时触发这个方法

 public float speed;//CreateEditor脚本中的数据
    public int index;
    [MenuItem("Assets/tab3",false,2)]//创建tab3按钮
    static void tab3()
    {
        ScriptableWizard.DisplayWizard<CreateEdior>("修改数据","CreatButton");//创建对话框,读取CreateEditor脚本的数据,文本框的名字为“修改数据”
    }
    void OnWizardCreate()//对话框的按钮被点击时,触发这个方法
    {
        GameObject[] enemy = Selection.gameObjects;//获取所有被选中的对象
        foreach (var go in enemy)
        {
            if(go.transform.tag=="enemy")//获取选中标签为enemy的物体
            {
                text1 text2 = go.GetComponent<text1>();//获取他们的text1脚本
                text2.a = index;//用对话框的index值修改获取对象的脚本值
            }
        }
    }
   

 12:OnWizardUpdate()  和 OnSelectionChange()

 OnWizardUpdate()我们修改对话框中的字段或值时,就会调用这个方法

 OnSelectionChange()当我们更改选中的对象时,就会触发这个方法

  /// <summary>
    /// 替换被选中的对象时就会触发这个方法
    /// </summary>
    void OnSelectionChange()
    {
        Debug.Log(Selection.activeGameObject.name);//打印出被选中的一个游戏对象的名字
    }
    /// <summary>
    /// 对话框打开时触发这个方法,对话框中字段一改动就执行该方法
    /// </summary>
    void OnWizardUpdate()
    {
        Debug.Log(index);
    }

13: otherButton,创建对话框的第二个按钮,OnwizardotherButton这个方法绑定这个按钮,对话框的第一个按钮在按下之后对话框就会关闭,但第二个按钮按下对话框不会关闭

创建第二个按钮  ScriptTableWiazrd.DisplayWiazid<script>("对话框的名字",“第一个按钮名”,“第二个按钮名”)

第一个按钮名 触发的方法OnWiazrdCreate()

第二个按钮名 触发的方法OnWiazrdotherButton()

 [MenuItem("Assets/tab3",false,2)]//创建tab3按钮
    static void tab3()
    {
        ScriptableWizard.DisplayWizard<CreateEdior>("修改数据","CloseButton","otherButton");//创建对话框,读取CreateEditor脚本的数据,文本框的名字为“修改数据”
    }
    void OnWizardCreate()//对话框的CloseButton按钮被点击时,触发这个方法
    {
        Debug.Log("对话框已关闭");
    }
    void OnWizardOtherButton()//对话框的otherButton按钮被点击时,触发这个方法
    {
        GameObject[] enemy = Selection.gameObjects;//获取所有被选中的对象
        foreach (var go in enemy)
        {
            if (go.transform.tag == "enemy")//获取选中标签为enemy的物体
            {
                text1 text2 = go.GetComponent<text1>();//获取他们的text1脚本
                Undo.RecordObject(text2, "change");//把text2这个类的数据存储起来,类修改后,可以ctrl +z恢复到现在记录的类的数据
                text2.a = index;//用对话框的index值修改获取对象的脚本值
            }
        }
    }
   

14:记录一个类的数据,在类被修改后,可以用Ctrl +z撤销修改类中数据的操作 Undo.Recordobject(类名,“这个操作在内存中的名字,是自己随便起的”)

void OnWizardCreate()//对话框的按钮被点击时,触发这个方法
    {
        GameObject[] enemy = Selection.gameObjects;//获取所有被选中的对象
        foreach (var go in enemy)
        {
            if(go.transform.tag=="enemy")//获取选中标签为enemy的物体
            {
                text1 text2 = go.GetComponent<text1>();//获取他们的text1脚本
                Undo.RecordObject(text2, "change");//把text2这个类的数据存储起来,类修改后,可以ctrl +z恢复到现在记录的类的数据
                text2.a = index;//用对话框的index值修改获取对象的脚本值
            }
        }
    }

15:对话框的提示字符和错误警告提示字符     helpString 提示字符串    errorString 错误提示符

16:ShowNotification显示提示信息。这个函数只能在对话框中显示提示信息。

     

 void OnWizardOtherButton()//对话框的otherButton按钮被点击时,触发这个方法
    {
        int a = 0;
        GameObject[] enemy = Selection.gameObjects;//获取所有被选中的对象
        foreach (var go in enemy)
        {
            a++;
            if (go.transform.tag == "enemy")//获取选中标签为enemy的物体
            {
                text1 text2 = go.GetComponent<text1>();//获取他们的text1脚本
                Undo.RecordObject(text2, "change");//把text2这个类的数据存储起来,类修改后,可以ctrl +z恢复到现在记录的类的数据
                text2.a = index;//用对话框的index值修改获取对象的脚本值
            }
        }
        ShowNotification(new GUIContent(Selection.objects.Length + "个物体值被修改"));//按下第二个按钮,会显示提示信息
    }

17:使用EditorPerfabs保存弹出窗口中修改的数据

保存int 类型的值 Editorperfabs.setint("保存到这个字段",要被保存的字段)

调用这个被保存的Int 类型的值 Editorperfabs.GetInt("保存到的新字段",第一次打开这个对话框的显示值)

 void OnEnable()
    {
     index= EditorPrefs.GetInt("IndexKey", index);//在窗口被打开时,第一次使用index赋值给index,以后再打开就把保存的indexkey值赋予index,这样就完成保存每次修改的Index的值
    }
 EditorPrefs.SetInt("IndexKey", index);//把面板中修改的index值,保存到IndexKey中

18:显示进度条,使用EditorUtility.DisplayProgressBar("标题",“下标题”,进度),关闭EditorUtility.clearProgressBar()进度条

 foreach (var go in enemy)
        {
            a++;
            if (go.transform.tag == "enemy")//获取选中标签为enemy的物体
            {
                text1 text2 = go.GetComponent<text1>();//获取他们的text1脚本
                Undo.RecordObject(text2, "change");//把text2这个类的数据存储起来,类修改后,可以ctrl +z恢复到现在记录的类的数据
                text2.a += index;//用对话框的index值修改获取对象的脚本值
                EditorPrefs.SetInt("IndexKey", index);//把面板中修改的index值,保存到IndexKey中
            }
            EditorUtility.DisplayProgressBar("进度", a + "/" + enemy.Length, a / enemy.Length);//显示修改数值的进度
        }
        EditorUtility.ClearProgressBar();//修改数值结束,关闭进度条

 20:创建自定义的窗口 创建自定义的窗口脚本继承EditorWindows脚本,用MyWindow脚本对象的show方法,实现创建窗口

using UnityEditor;


public class WindowEdior : EditorWindow {
    //脚本继承editorWindow
    [MenuItem("windows/createWindows",false,1)]//创建createwindows按键,实现创建窗口的功能
    static void create()
    {
        WindowEdior window = EditorWindow.GetWindow<WindowEdior>();//创建窗口
        window.Show();//显示窗口
    }
    
}
原文地址:https://www.cnblogs.com/zhangyang4674/p/10976556.html