目录
一、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()
{
//.......//
}
效果如图:
以及
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() 就行了
绘制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();
}
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,需选中如图按钮
项目在调试玩家自动战斗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,查找手册来一步步完成自己的插件,这是个繁琐的过程。
希望读完本文,读者在拿到一个别人编写的插件时,也能大体想象出插件的代码结构,快速找出插件的关键代码,为自己所用。