目录

一、MenuItem --> Unity菜单选项扩展二、CustomEditor --> 针对自定义Component的Inspector面板的扩展
三、DrawGizmo辅助显示
四、OnGUI
五、EditorWindow --> 自定义一个窗口
六、ScriptableWizard --> 自定义一个对话框


 Unity提供了灵活的插件支持,供开发者自定义插件来提供开发效率,几乎所有介绍到的支持都必须包含



using UnityEditor;



一般所属脚本文件需要放在名为Editor的目录下,如果不想将脚本文件放在Editor下,就需要用预编译包含相关文件,否则编译打包时会报错



#if UNITY_EDITOR
    //...... Code In Editor
#endif



以下简单介绍几种常用扩展


一、MenuItem -->  Unity菜单选项扩展

* 必须写在静态方法之前

* 格式: [MenuItem("路径",  isValidateFunction , 优先级)]

  路径 --> 用"/"分割路径层级,可支持添加快捷键(语法细节不深入)

  isValidateFunction -->  是否有验证函数,比如[MenuItem("Assets\OutputVertexCount", true)],Unity将自动执行一个名为ValidateOutputVertexCount(Validate+菜单选项名)的函数,返回值为true则该菜单项才会被启用

  优先级 --> 指在弹出的菜单中显示排序的优先级,小前大后(系统自带选项有自己的优先级数值,这个没有深究其数值范围,一般相隔100内的选项会成组,并被用横线隔开,这个制作插件的时候自由发挥,无需在意太多细节),默认在菜单最后

简单说就是编辑器中的右键菜单扩展,包括以下几类

1) Assets



[MenuItem("Assets/NPC/生成",false, 1)]
public static void GeneratePrefab()
{
     //.......//      
}



效果如图:

Unity 插件 绘画 unity如何制作插件_优先级

 以及 

Unity 插件 绘画 unity如何制作插件_ui_02

2) GameObject



[MenuItem("GameObject/UITemplate/Creat To Prefab", false, 11)]
static void CreatToPrefab(MenuCommand menuCommand)
{
    //.......//
}



效果类似Assets,不同的是可在Hierarchy层级面板弹出右键菜单中看到添加的选项

3) 其他字符串

直接在编辑器上层菜单栏添加

4) Selection

在函数中善用Unity自带的Selection类,Selection.Objects用来指带目前被选中的对象(一个或多个),进行逻辑操作。详细用法参照


 

二、CustomEditor --> 针对自定义Component的Inspector面板的扩展

在开发中经常遇到自己写了一个脚本Component,附带了一些属性和逻辑,想要自定义这个Component在Inspector面板的一些操作,就要用到CustomEditor扩展

用法很简单,如下:


//Editor类 --> 下面这句声明了专门是为MyComponent定制的
[CustomEditor(typeof(MyComponent))]
public class MyComponentEditor : Editor
{
    //Inspector面板的显示绘制
    public void OnInspectorGUI()
    {
           //........//
    }

    //还可以自定义scene视图的显示绘制
    public void OnSceneGUI()
    {
           //........//
    }
}

//MyComponent类的实现
public class MyComponent: MonoBehaviour
{
    //......//
}



MyComponent是我们自己实现的功能类,当Scene视图中某个GameObject被选中,且该GameObject有MyComponent这个控件,则其对应的MyComponentEditor就会接管编辑器的显示,如:

1) OnInspectorGUI --> 控制Inspector面板的绘制

如果需要显示默认的Inspcetor,则加一句  DrawDefaultInspector() 就行了

Unity 插件 绘画 unity如何制作插件_ui_03

绘制GUI主要依靠几个类:

GUI, GUILayout, EditorGUILayout, EditorGUI 用于绘制按钮、文字,单选框,滚动条,图片之类的,GUI与Editor大体是一样的

GUIStyle 风格设置

建议可以在需要绘制UI的时候去查一下手册,看看有什么可以用到的控件。

2) OnSceneGUI --> 控制Scene视图窗口的消息处理

这个函数可以接收Scene视窗中发生的事件 --> UnityEngine.Event



public void OnSceneGUI()
{
     //可获取当前事件
     UnityEngine.Event e = UnityEngine.Event.current;
    
     //事件类型(常见有MouseUp/Down, KeyUp/Down, Layout, Used, Repaint等)
     UnityEngine.EventType EType = e.type;

     //根据事件类型,在OnSceneGUI做对应的显示处理
     //以下判断识别鼠标按下,移动,或者拖动
             if (EType == UnityEngine.EventType.MouseDown
            || EType == UnityEngine.EventType.MouseMove
            || EType == UnityEngine.EventType.MouseDrag)
        {
            //Event.current中有详细的状态信息
            //如下面获取了某些按键的状态,进行逻辑排除
            if (UnityEngine.Event.current.alt                   //按着alt键位     忽略
                || UnityEngine.Event.current.button == 2        //中键            忽略
                )
            {
                return;
            }

            //下面代码在获取鼠标点击的位置
            Ray worldRay = HandleUtility.GUIPointToWorldRay(UnityEngine.Event.current.mousePosition);
            RaycastHit hitInfo;
            if (Physics.Raycast(worldRay, out hitInfo))
            {
                Vector2 Target = new Vector2(hitInfo.point.x, hitInfo.point.z);
            }
    }

    //调用Use()表示该事件已经被处理过了,不会再传给其他模块
    UnityEngine.Event.current.Use();
}


Editor的其他接口

3) Unity内置控件的Editor

Unity已有的内置空间也可以做Editor扩展,如Material有MaterialEditor,这块没尝试过...

4) Attributes --- 常见属性标签语法

我们会常常用到一些标签式的语法,修饰在某个函数或者类前,用来指代这个函数或者类的一些属性,MenuItem就是其中一种,常见的还有:



//表现MyCompoent需要用到MeshFilter这个Component,添加MyComponent的时候,如果同级没有MeshFilter,会自动添加
[RequireComponent(typeof(MeshFilter))]
public class MyComponent : MonoBehaviour {
}

//表示这个Component在Edit模式下也会运行,但注意其Update只有在场景中的GameObject有发生变化的时候才会调用
[ExecuteInEditMode]
public class MyComponent: MonoBehaviour{
}


public class MyComponent:MonoBehaviour{
        //序列化属性,可在Inspector见到(即使是private),并操作
        [SerializeField]
    private bool hasHealthPotion = true;

        //不在Inspcetor显示这个属性
        [HideInInspector]
        public int p = 5;
}



延伸阅读

 


 

三、DrawGizmo辅助显示

重载MonoBehaviour的OnDrawGizmos可以用来绘制在场景辅助显示,如Line(线段), Mesh(网格), Ray(射线), Sphere(球形)等。

具体使用Gizmos.DrawXXX系列函数,参考

需注意Scene视图默认显示Gizmos绘制,如果要在Game视图显示Gizmos,需选中如图按钮

Unity 插件 绘画 unity如何制作插件_Unity 插件 绘画_04

 

项目在调试玩家自动战斗AI、玩家摇杆移动、布怪、刷阻挡,都用到了Gizmos这个功能,好处是调试起来较为直观


 

四、OnGUI

重载MonoBehaviour的OnGUI可以用来在场景视图上绘制简单的UI界面

项目目前使用OnGUI绘制帧率,内存等游戏基本信息


 

五、EditorWindow --> 自定义一个窗口

EditorWindow用于创建一个独立窗口,当你在制作一个功能较杂且较为独立的插件的时候或许会用到。用法也十分简单,编写一个继承EditorWindow的类就行了



public class ConsoleEditorWindow : EditorWindow
{
  //重载OnGUI,其绘制的UI不是在Scene视图中,而是在打开的EditorWindow上
  void OnGUI()
  {
  }
}



绘制的函数也是使用GUILayout,EditorGUILayout等一系列API,不在赘述。

另外你需要通过编写一个带MenuItem的Attribute或者其他什么函数,来作为打开这个EditorWindow的入口。

EditorWindow中包含一些比较常用的函数,如:

1) Show ---> 显示窗口,功能类似的还有ShowPopup,ShowAsDropDown等,不同的是这些接口应用了一些固定的外观Style

2) Repaint ---> 重绘,你在OnGUI中处理了一些逻辑,需要重绘来理解更新UI的,可以调用这个

3) Close --> 关闭窗口

4) OnFocus/OnLostFocus --> 窗口得到或者失去焦点,也挺有用的

参考


 

六、ScriptableWizard --> 自定义一个对话框

由ScripttableWizard派生出来的类主要干的事情就是类似你安装一个软件时,不停的弹出引导安装的对话框(下一步取消下一步取消下一步取消下一步取消)的事情一样。

不过ScripttableWizard目前只支持两个操作按钮(Create、Other)

有用到类似功能的朋友可以去看看


 

结语:

本文主要简介了下Unity编写插件的几种方式,没有具体讲到某个插件例子的编写。实际编写遇到的问题大部分是因为对API的不熟悉,只能通过多多Google,查找手册来一步步完成自己的插件,这是个繁琐的过程。

希望读完本文,读者在拿到一个别人编写的插件时,也能大体想象出插件的代码结构,快速找出插件的关键代码,为自己所用。