Unity 两篇文章熟悉所有编辑器拓展关键类 (上)

本专栏基础资源来自唐老狮和siki学院,仅作学习交流使用,不作任何商业用途,吃水不忘打井人,谨遵教诲

编辑器扩展内容实在是太多太多了(本篇就有五千字++)

所以分为两个篇章而且只用一些常用api举例,更多的还是起到留下学习印象的作用

就像引用类型的堆和栈一样,本文提供栈的作用,指向的内存堆为官方文档

什么是编辑器扩展

Unity编辑器扩展是指通过编写自定义脚本和插件,利用Unity提供的API来增强和扩展Unity编辑器的功能,这些扩展可以显著提高开发效率和灵活性

前置知识:GUI

可能需要熟悉的知识: EditorGUI - Unity 脚本 API

大部分的编辑器扩展脚本都需要写在Editor文件中,这样unity打包的时候,不会打包出去该文件

1.MenuItem类

作用:在unity未运行时 一键使用自定义静态函数

MenuItem - Unity 脚本 API --- MenuItem - Unity 脚本 API

1.创建菜单栏

MenuItem("扩展菜单名/一级菜单名/方法名任意")\] 菜单级数任意

实现效果如下

引入命名空间,函数必须为静态函数

cs 复制代码
using UnityEngine;
cs 复制代码
public class T1 
{
   //在unity不同的地方一键执行静态函数
   [MenuItem("扩展菜单名/TestMethod/Function1")]
   public static void Function1(){
        Debug.Log("输出任意一句话");
    }
}

可以添加特殊标识符,在不同的窗口创建使用,而不只是通过菜单栏中去选择

类似这样

总结一下规则如下图

2.绑定快捷键规则

3.在组件菜单中拓展自定义脚本

AddComponentMenu("一级菜单/二级菜单/脚本名建议和实际脚本一致")\] 菜单级数任意

众所周知 ,在unity中脚本就可以理解为组件

所以在菜单栏中的组件菜单中,是可以将自定义的脚本添加进去的

使用特性AddComponentMenu:

cs 复制代码
//在组件菜单中添加 自定义脚本(组件)
[AddComponentMenu("一级菜单/二级菜单/脚本名")]
public class T2 : MonoBehaviour
{
 
}

选中物品就可以添加了

4.为脚本添加使用自定义函数

MenuItem("CONTEXT/脚本名/一级菜单名/函数名任意")\] 菜单级数任意

cs 复制代码
//在组件菜单中添加 自定义脚本(组件)
[AddComponentMenu("一级菜单/二级菜单/脚本名")]
public class T2 : MonoBehaviour
{
    [MenuItem("CONTEXT/T2/一级菜单名/Function1")]
    public static void Function2() {
        Debug.Log("输出任意一句话");
    }
}

2.EditorWindow 类

官方文档:EditorWindow - Unity 脚本 API

继承了 EditorWindow类的编辑器脚本, 你可以在这个窗口中添加自定义方法,如下图演示将创建一个名为Name,有一个任意内容label的窗口

例如如下窗口

cs 复制代码
public class Window : EditorWindow
{
    [MenuItem("MyWindow/window1")]
    private static void MyWindow()
        {
        Window w =EditorWindow.GetWindow<Window>("Name");
        w.Show();

    }
    private void OnGUI() {
        GUILayout.Label("任意内容");
    }
}

3.EditorGUILayout类

在具体绘制这一点,unity提供了一个新的类叫做EditorGUILayout,功能与GUILayout相似加入了自动布局功能

EditorGUILayout - Unity 脚本 API

举例:每种元素都用常用api

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class Window : EditorWindow
{
    [MenuItem("MyWindow/window1")]
    private static void MyWindow()
        {
        Window w =EditorWindow.GetWindow<Window>("Name");
        w.Show();

    }
    //层级和标签
    int layer;
    string tag;

    //选择枚举
    enum E_AnyType{ 
        a=1,
        b=2,
        c=4,
        d=8,
        //要将枚举中的变量定义为2的幂次方,原因是多选枚举时,是按照 或运算 将得出的结果记录下来
        //比如a=1,二进制为0001,b=2,二进制为0010,或运算后结果为0011 = 3 
        //如果不按此规则,a=1,b=2,c=3,当a|b之后,得到的结果就变成了c,而不是多选a和b
    }
    E_AnyType single;
    E_AnyType multiple;

    //字符串选择对应数组值
    int returnNum;
    string[] options = { "op1", "op2", "op3", "op4" };
    int[] result = { 1,2,3,4};

    //关联资源
    GameObject obj;
    int value;//整形输入框
    
    //折叠控件
    bool isHide;
    bool isGroupHide;

    //滑动条
    float slider;
    int intSlider;
    float min;
    float max;
    private void OnGUI() {
        EditorGUILayout.LabelField("页签");
        layer =EditorGUILayout.LayerField(layer);//return int
        tag =EditorGUILayout.TagField("标签");//return sting

        single = (E_AnyType)EditorGUILayout.EnumPopup("单选枚举",single);//return typeof(E_AnyType)
        multiple = (E_AnyType)EditorGUILayout.EnumFlagsField("多选枚举",multiple);

        returnNum = EditorGUILayout.IntPopup("字符串对应数组", returnNum, options, result);
        EditorGUILayout.LabelField(returnNum.ToString());

        EditorGUILayout.DropdownButton(new GUIContent("按钮"), FocusType.Passive);//return bool

        isHide = EditorGUILayout.Foldout(isHide,"折叠控件 bool包裹内容");
        if(isHide){
          
            obj = EditorGUILayout.ObjectField("关联资源对象框", obj, typeof(GameObject), true) as GameObject;
            value = EditorGUILayout.IntField("输入框", value);
        }
        isGroupHide = EditorGUILayout.BeginFoldoutHeaderGroup(isGroupHide,"折叠组控件 必须包括开始和结束");

        EditorGUILayout.EndFoldoutHeaderGroup();

        //开关和开关组类似于折叠控件 关键词:Toggle

        slider =EditorGUILayout.Slider("滑动条",slider,0,1);
        intSlider = EditorGUILayout.IntSlider("整型滑动条",intSlider,0,1);
        //双块滑动条
        EditorGUILayout.MinMaxSlider("双块",ref min,ref max,0,1);

        EditorGUILayout.Space(10);//间隔框
        //提示框
        EditorGUILayout.HelpBox("提示框",MessageType.Warning);//MessageType选择类型

       
    }
}

4.EditorGUIUtility类

该类是 EditorGUI 的各种辅助程序

文档EditorGUIUtility - Unity 脚本 API

cs 复制代码
public class 资源加载和工具类 : EditorWindow
{
    [MenuItem("资源加载部分/openWindow")]
    private static void OpenWindow(){
        资源加载和工具类 l = EditorWindow.GetWindow<资源加载和工具类>("资源加载与工具示例");
        l.Show();
    }

    Texture texture;
    private void OnGUI() {
        //加载Editor Default Resources 文件夹下的资源 要求有后缀名
        texture = EditorGUIUtility.Load("test.jpg") as Texture;//有判空方法 EditorGUIUtility.LoadRequired() 
        GUI.DrawTexture(new Rect(0,50,100,100),texture);//绘制

        //搜索框和选择资源
        if (EditorGUILayout.DropdownButton(new GUIContent("打开资源搜索框"), FocusType.Passive))
          EditorGUIUtility.ShowObjectPicker<Texture>(null,true,"",0);//搜索

        if(Event.current.commandName == "ObjectSelectorUpdated") {
            texture = EditorGUIUtility.GetObjectPickerObject() as Texture;//获取

            EditorGUIUtility.PingObject(texture);//高亮选中资源在Project中
           Debug.Log(texture.name);
        }

        //窗口事件传递 当SendEvent(e)执行后 会发出一个ExecuteCommand枚举类型 只需要检测这个类型 并且事件名相同即可接收
        if (EditorGUILayout.DropdownButton(new GUIContent("传递事件按钮"), FocusType.Passive))
            {
            Event e = EditorGUIUtility.CommandEvent("事件名");
            SendEvent(e);
        }
        //接收事件窗口 可以写在其他窗口之中 
        if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == "事件名") {
            Debug.Log("接收到了事件");
        }

    }
}

5.Selection类

用于访问编辑器中的选择对象,这个类过于简单了,就不做演示,可以自行查看文档或看下面唐老师的注释

文档Selection - Unity 脚本 API

cs 复制代码
       #region 知识点一 获取当前选择的Object
       //获取当前在面板上选择的游戏物体Object
       //未选择则返回Null
       //选择多个则返回第一个选择的游戏物体
       //Selection.activeObject
       #endregion

       #region 知识点二 获取当前选择的GameObject
       //获取当前在面板上选择的游戏物体GameObject
       //未选择则返回Null
       //选择多个则返回第一个选择的游戏物体
       //Selection.activeGameObject
       #endregion

       #region 知识点三 获取当前选择的Transform
       //获取当前在面板上选择的游戏物体的Transform
       //未选择则返回Null
       //选择多个则返回第一个选择的游戏物体
       //Selection.activeTransform

       //只能获取到场景中的对象的Transform
       #endregion

       #region 知识点四 获取当前选择的所有Object
       //获取当前在面板上选择的物体数组
       //未选择则返回Null
       //Selection.objects 
       #endregion

       #region 知识点五 获取当前选择的所有GameObject
       //获取当前在面板上选择的游戏物体或Project中预设体 GameObject数组
       //未选择则返回Null
       //Selection.gameObjects
       //可以遍历获取所有信息
       #endregion

       #region 知识点六 获取当前选择的所有Transform
       //获取当前在面板上选择的游戏物体Transform数组
       //未选择则返回Null
       //Selection.transforms
       //可以遍历获取所有信息
       #endregion

   }

6.Event类

作用:检测Unity中的事件/输入,或者是 用于UnityGUI 布局/渲染事件

你如果将此类写在OnGUI之中并配合EditorWindow的话那么其所有的方法与属性都将与自定义窗口有关

文档Event - Unity 脚本 API

由于api过多且简单,故不做全部演示

cs 复制代码
  private void OnGUI() {
      //有一个大类 Event.current
      Vector2 mousePostion = Event.current.mousePosition;
      Debug.Log(mousePostion);
  }
相关推荐
牙膏上的小苏打23331 小时前
Unity Surround开关后导致获取主显示器分辨率错误
unity·主屏幕
『六哥』1 小时前
Windows 10 如何设置右击鼠标快速进行“关机”
windows·经验分享·编辑器
Unity大海3 小时前
诠视科技Unity SDK开发环境配置、项目设置、apk打包。
科技·unity·游戏引擎
浅陌sss9 小时前
Unity中 粒子系统使用整理(一)
unity·游戏引擎
维度攻城狮13 小时前
实现在Unity3D中仿真汽车,而且还能使用ros2控制
python·unity·docker·汽车·ros2·rviz2
为你写首诗ge16 小时前
【Unity网络编程知识】FTP学习
网络·unity
1alisa18 小时前
Sublime Text for Mac v4【注册汉化版】代码编辑器
macos·编辑器·sublime text
神码编程18 小时前
【Unity】 HTFramework框架(六十四)SaveDataRuntime运行时保存组件参数、预制体
unity·编辑器·游戏引擎
菲fay20 小时前
Unity 单例模式写法
unity·单例模式
mzak21 小时前
vscode集成deepseek实现辅助编程(银河麒麟系统)【详细自用版】
linux·vscode·编辑器·银河麒麟·deepseek