Unity3d 编写编辑器自定义插件

来源:互联网 发布:怎么用手机在知乎提问 编辑:程序博客网 时间:2024/06/10 01:43

Unity3D的运行时和编辑器类分别存储在不同的Assemblies里:UnityEngine和UnityEditor。由于编辑器插件是独立于游戏之外的,因此需要在assets文件夹下建立Editor目录来存放自定义插件的代码。需要注意的是Editor文件夹是被编辑器智能识别的,可以是其他文件夹的子文件夹,并且可以存在多个,这样就给我们安排文件结构提供了便利。注意游戏中的脚本是不能访问Editor文件夹下的代码的。 
准备开始编写编辑器之前,需要using UnityEditor来导入编辑器的名称空间。顺便一说,Editor文件夹下的代码应该也是在这个名称空间里的。

如何开启自定义插件窗口

一般的插件都是需要交互窗口的(也有不需要的),一般写一个静态方法打开插件窗口,并在该静态方法前加上编辑器自定义的几种特性之一,进入的方法有有以下两种: 
[MenuItem(path)]:告知编译器给Unity3D编辑器添加一个菜单项,并且当点击该菜单项的时候调用该函数。触发函数里可以编写任何合法的代码,可以是一个资源批处理程序,也可以弹出一个编辑器窗口。代码里可以访问到当前选中的内容(通过Selection类),并据此来确定显示视图。 
[ContextMenu(“path”)]:可以向你的上下文菜单中添加一个菜单项,点击该菜单项时显示视图。

如何编辑自定义插件窗口

编写自定义的窗口界面,需要编写一个继承自EditorWindow的类。通常需要写一个[MenuItem]来告知编译器何时打开这个面板。这个方法可以返回void,在方法内可以使用EditorWindow.GetWindow<T>();来打开界面,T即插件类本身。同时在这个插件类中需要有OnGUI()方法,在此方法中绘制界面即可。 
除了OnGUI外,还可以使用以下回调来触发某些具体的事件: 
OnSelectionChange,但你点选物品时触发 
OnFocus /OnLostFocus,获得和失去焦点时触发 
OnDestroy:窗口被关闭时触发 
OnHierarchyChange:当层级视图被改变时触发 
OnInspectorUpdate:当监视器面板更新时触发 
Update: 每秒100次被触发

除了继承EditorWindow之外,还可以继承自ScriptableWizard类来实现向导式窗口的编写,注意ScriptableWizard本身是继承自EditorWindow类的,所以它们的用法类似。不过注意,当点击确认按钮时,OnWizardCreate()会被调用。另外,ScriptableWizard.DisplayWizard()可以生成并显示出该窗口。

编写窗口内元素

一般游戏内的插件,比如技能编辑器,导出bundle包等的功能使用unity自带的UI建议方式即可,主要用到以下几个类:GUI,GUILayout,EditorGUILayout,EditorUtility。

GUI类是系统自带的UI生成类,可以生成各种基础元素如window,toggle,label,button等。

GUILayout布局类,中包括了最常用的几种功能比如BeginArea,BeginHorizontal,BeginVertical,BeginScrollView以及相应的End方法,是按照自动布局的方式快捷生成界面UI的。也有Button,Label等常用控件可通过该类快速生成。

EditorGUILayout是GUILayout的补充,里面有一些更复杂的控件,如Toggle,TextField,Slider,IntField,IntPopup,EnumMaskField,TagField等。还有其他的一些自动布局方法,如BeginScrollView,BeginFadeGroup,BeginToggleGroup等。

EditorUtility则是一些编辑器实用方法,如显示工作进度的DisplayProgressBar;打开保存路径RevealInFinder;显示弹出界面DisplayPopupMenu;替换预设ReplacePrefab等实用的方法。注意SetDirty也在此类中,这个函数是告诉编辑器哪个东西被修改了,如果是序列化的数据编辑器就会将修改后的数据保存起来。

除了以上几个编辑界面时需要用的类之外,还有一些实用的类和方法在编写自定义插件的时候也会用到:

Selection,这个类主要是获取目前用户的选中对象; 
Application,应用相关方法,可以获得各种当前状态,还可以使用logMessageReceived注册新log产生时的回调方法。 
GUI .GetNameOfFocusedControl () : 获取控件是否处于焦点状态。

一些需要挂在才能生效的Component脚本,会需要用到下面的特性: 
[ExecuteInEditMode]通知编译器,该类的OnGUI和Update等函数在编辑模式也也会被调用。 
[AddComponentMenu(“XXX/XXX”)]:把脚本关联到Component菜单中,点击相应菜单项即可为选中的GameObject添加该脚本。

最后是一个简单的例子,用来整体缩放UI控件(其中的UISprite是NGUI中的组件):

public class UISetLabelSize : EditorWindow{    private float Size = 1.0f;    [MenuItem("CustomTool/设置UI缩放")]    static void SetColor()    {        EditorWindow.GetWindow<UISetLabelSize>();    }    void OnGUI()    {        EditorGUILayout.BeginVertical();        Size = EditorGUILayout.Slider("设置缩放倍数:", Size, 0f, 100f);        if (GUILayout.Button("设置"))        {            Selection.activeGameObject.transform.localScale = new Vector3(Selection.activeGameObject.transform.localScale.x * Size,                Selection.activeGameObject.transform.localScale.y * Size, 1f);        }        if (GUILayout.Button("恢复默认大小"))        {            Selection.activeGameObject.GetComponent<UISprite>().MakePixelPerfect();        }        EditorGUILayout.EndVertical();    }}
0 0
原创粉丝点击