一.什么是编辑器拓展

Unity是一个编辑器,编辑器就是可以进行编辑的工具,比如我们的文本Text就是一个文本编辑器,那我们的Unity其实就是用来编辑游戏的,编辑的扩展就是对编辑器本身的功能进行添加。但是由于Unity是不开源的引擎,所以我们只能使用特定的功能去编辑。

UNITY3D的IDE本身的强大,除了表现在其提供的强大功能外,更让人喜欢的,是它高度的可扩展特性。这也是一个项目开发中,必不可少的环节。

二.菜单按钮的拓展

对菜单按钮进行拓展,首先新建一个C#脚本MenuItemTool。

首先引入命名空间 UnityEditor

1.使用方法MenuItem来创建菜单

比如我们创建一个用来清除缓存的按钮。引号里面是菜单的名字,ClearMemory是一级菜单,二级和三级菜单用/表示。

[MenuItem("ClearMemory/ClearAll")]

我们想在点击ClearAll的时候执行某些方法,需要在下面创建一个和菜单名相同的静态方法。

static void ClearAll()
    {
        Debug.Log("清除所有缓存");
    }

在这里,创建的方法必须是静态的,如果不是静态的,菜单就不能显示

因为静态成员是和类一起存在的,有了类就有了静态成员,我们可以直接通过类来调用静态成员,非静态成员是和对象一起存在的,有了对象才有非静态成员,非静态成员通过对象来访问。

2.修改优先级

MenuItem里面除了添加菜单名字外,还可以添加两个参数,F12点进MenuItem可以查看

优先级和是否可用,数字越小,优先级越高

[MenuItem("ClearMemory/ClearAll",false,1)]
    static void ClearAll()
    {
        Debug.Log("清除所有缓存");
    }
    [MenuItem("ClearMemory/ClearOther/ClearShopInfor", false, 2)]
    static void ClearShopInfor()
    {
        Debug.Log("清除商店缓存");
    }

这里:true代表不可用,False可用,true的时候,菜单不显示,没有设置优先级的菜单取子菜单的最大优先级。


3.菜单分组

我们会发现在菜单中会有一条线把二级菜单分开,这个就是多二级菜单进行分组。

只要两个菜单的优先级相差11,就会进行分组

Unity实现编辑器菜单窗口通用框架 unity 编辑器拓展_游戏

4.在系统自带的菜单下面添加二级菜单

比如在GameObject中添加菜单,我们只需要添加GameObject/

没有添加优先级,是在最下面的,我们可以测试一下在什么优先级对应的排名。

也可以把我们的Text插入到二级菜单中。



三.属性面板拓展

1.贴图的增加

在Script中新建一个脚本ChangeInspector,首先我们让脚本显示一张贴图

public Texture texture;

回到场景中,创建一个空的物体Enemy,将我们创建的脚本挂在上面,此时,我们的属性面板中就会显示TexTure属性,但是我们发现,我们只能在这里选择贴图,但是看不见贴图。那我们就通过编辑Inspector面板来显示出贴图

我们在Editor中新建一个脚本InspectorEditor。继承Editor类,并导入命名空间

然后我们给他自定义脚本

[CustomEditor(typeof(ChangeInspector))]

我们要把贴图显示出来,就要绘制一个贴图层

重写一下OnInspectorGUI,我们要拓展面板里的属性,必须要重写这个方法

获取一下对象

接下来开始绘制贴图层

objectField有四个参数:标签 贴图 类型 是否允许指定物体,最后转换成Texture类型

public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        ChangeInspector inspectorObj = (ChangeInspector)target;
        //绘制帖图槽
        inspectorObj.texture =EditorGUILayout.ObjectField("选择贴图", inspectorObj.texture, typeof(Texture), true) as Texture;
    }

回到面板中,我们就可以看到我们的贴图可以显示出来了

此时我们就可以把Texture属性隐藏了

[HideInInspector]
public Texture texture;

2.修改Rect

我们再创建一个Rect类型的属性rectValue

public Rect rectValue;

回到Editor中修改

RectField中的参数:标签 显示的目标

inspectorObj.rectValue = EditorGUILayout.RectField("窗口坐标", inspectorObj.rectValue);

3.文本输入框

inspectorObj.remark = EditorGUILayout.TextField("输入姓名", inspectorObj.remark);

4.滑动条

public float sliderValue = 0.8f;
inspectorObj.sliderValue = EditorGUILayout.Slider("进度值",inspectorObj.sliderValue, 0f, 1f);

三个参数,初始值 最小值最大值


5.复选框

public bool isOpen = true;
inspectorObj.isOpen = EditorGUILayout.Toggle("开始", inspectorObj.isOpen);


6.下拉列表

我们在Script中新建一个脚本ToolType,添加一个命名空间Tool,并添加一个枚举类型EdirType

namespace Tool
{
    public enum EdirType
    { 
        up,
        down,
        left,
        right
    }
public class ToolType : MonoBehaviour {  
}
}

回到ChangeInspector脚本中,引用一下Tool命名空间

定义一个枚举值theType默认为up

private EdirType theType = EdirType.up;
public EdirType TheType
    {
        get {
            return theType;
        }
        set {
            theType = value;
        }
    }

回到Editor中,也引用一下命名空间

绘制下拉列表

inspectorObj.TheType = (EdirType)EditorGUILayout.EnumPopup("方向", inspectorObj.TheType);




7.绘制一个分组,通过复选框决定是否开启

到Editor中

声明一个bool值 GroundEnable=false

GUILayout.Label("*****以下是附加设置*****");//首先绘制一个Label
        groundEnable = EditorGUILayout.BeginToggleGroup("是否开启附加设置", groundEnable);//用GroundEnable来控制开启分组
        inspectorObj.theValue1 = EditorGUILayout.FloatField("1", inspectorObj.theValue1);//绘制两个float类型的值
        inspectorObj.theValue2 = EditorGUILayout.FloatField("2", inspectorObj.theValue2);
        inspectorObj.isAdd = EditorGUILayout.Toggle("开启", inspectorObj.isAdd);//绘制一个复选框
        EditorGUILayout.EndToggleGroup();//闭合分组

8.扩展自带组件

在Editor中新建一个脚本CameraEditor

继承Editor 引用命名空间

自定义脚本

[CustomEditor(typeof(Camera))]

重写一下GUI

这里因为我们要重写自带的属性,所以应该使用base.DrawDefaultInspector

public override void OnInspectorGUI()
    {
        base.DrawDefaultInspector();
        GUILayout.Label("1111111111111");//我们添加一个Label
        if (GUILayout.Button("点击处理"))//绘制一个按钮
        {
            Debug.Log("检测到点击了");
        }
    }




其他的组件也是一样,想要扩展哪一个组件,我们就把组件的名字传进来