最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
unity 3d 教程 有什么编辑器吗
编辑器代码触发机制
Unity 3D 允许通过事件触发来执行编辑器代码,不过需要借助一些编译器参数告知编译器何时触发特定代码。在函数上方使用 [MenuItem(XXX)] 声明,能为 Unity 3D 编辑器添加一个菜单项,点击该菜单项时会调用此函数。触发函数中可编写任何合法代码,比如实现一个资源批处理程序,或者弹出一个编辑器窗口。代码里可通过 Selection 类访问当前选中的内容,并据此确定显示视图。类似地,[ContextMenu("XXX")] 可向上下文菜单中添加菜单项。
若编写了一些 Component 脚本,希望在其附属于某个 GameObject 时,能在编辑视图(即 Scene 视图)观察到效果,可在类上方添加 [ExecuteInEditMode],通知编译器该类的 OnGUI 和 Update 等函数在编辑模式下也会被调用。此外,使用 [AddComponentMenu("XXX/XXX")] 可将脚本关联到 Component 菜单,点击相应菜单项就能为 GameObject 添加该 Component 脚本。
开始编写编辑器
为避免不必要的包含,Unity 3D 的运行时和编辑器类分别存储在不同的程序集(UnityEngine 和 UnityEditor)中。准备编写编辑器前,需使用 using UnityEditor 导入编辑器的命名空间。若部分代码在运行时和编辑器中都要执行,可使用 #if UNITY_EDITOR ... #endif 宏对编辑器代码进行特殊处理。
在真正编写代码前,还需了解:所有放在名为 Editor 目录下的脚本会在其他脚本之后编译,这便于使用运行时的内容,但其他目录下的脚本无法访问 Editor 目录下的内容。因此,建议将编辑器脚本放在 Editor 目录下。
如何创建自定义编辑器窗口
创建窗口
若要自定义一个可编辑的面板,需编写一个继承自 EditorWindow 的类。通常还需编写一个 [MenuItem] 告知编译器何时打开该面板,此事件的回调应为静态方法,并返回一个窗口的实例。
点击对应的菜单项时,会弹出一个空白窗口,且该窗口可像 Unity 3D 编辑器预制的窗口一样随意拖动和停靠。接下来探讨如何在窗口内实现所需功能。
扩展窗口
和运行时的 GUI 类似,若要在窗口中添加交互控件,需重写 OnGUI 方法,具体重写方式与运行时的 GUI 相同,甚至可使用任何扩展自原生 GUI 系统的插件(如 iGUI 和 GUIX)简化插件开发流程(仅经过初步测试,更深层次的可用性尚待验证)。同时,UnityEditor 命名空间下的 EditorGUILayout 在原生 GUI 之上提供了更便捷的接口和控件,可轻松使用一些编辑器特有的 UI 控件。
除 OnGUI 外,可能还需以下回调触发特定逻辑(完整列表请参考官方文档):
OnSelectionChange:点击选择物品时触发。OnFocus / OnLostFocus:获得和失去焦点时触发。
进一步扩展窗口
自定义控件
和运行时 GUI 的使用方式一样,若要自定义控件,最简单的方法是实现一个静态方法(也可为非静态),并提供一些可选参数,在方法内部根据这些参数完成控件的布局(如同在 OnGUI 中操作)。若将自定义控件实现在窗口类内部,可使用 Partial 类更好地管理代码。
绘制 2D 内容
- 绘制图片:可使用
GUI.DrawTexture绘制图片资源。 - 绘制基础图元:GUI 本身未提供绘制基础图元的方法,但可通过一些方式封装。
- 绘制线段:通过一个像素的贴图资源配合
GUI.DrawTexture和矩阵旋转完成线段绘制。 - 绘制矩形框:通过
GUI.Box和样式设置封装矩形框和矩形填充框。
资源选择器
EditorLayout.ObjectField 控件提供资源选择逻辑,生成时需指定某种资源类型,可拖动该种资源到控件或点击控件旁边的小圆圈进行列表选择。
如何存储编辑内容
可创建一个继承自 SerializedObject 的类来保存编辑的数据。继承自 SerializedObject 的对象可用于存储数据而不参与渲染,并最终打包到 AssetBundle。针对当前编辑选项等内容的存储,可能需要另一个 SerializedObject 类(与具体系统设计相关)。
向导式的编辑窗口
很多情况下,可能需要一个包含多个参数的编辑面板,编辑结束后有一个确认按钮。无需自行实现,UnityEditor 提供了 ScriptableWizard 帮助快速开发。它继承自 EditorWindow,使用方式类似。点击确认按钮时,OnWizardCreate() 会被调用。另外,ScriptableWizard.DisplayWizard 可帮助生成并显示该窗口。
如何扩展 INSPECTOR 面板
在 Unity 3D 中点击一个对象时,Inspector 面板会显示该对象的属性。可针对某个类型的对象扩展该面板,这在为 Unity 3D 开发插件时非常有用。
定义 INSPECTOR 何时被触发
自定义的 Inspector 面板需继承 Editor 类。由于功能相对具体,无需定义代码何时触发,点击对应物体时代码会自动执行。要定义其对应的类型,只需在类定义前使用编译器命令 [CustomEditor(typeof(XXX))] 即可。
访问被编辑的对象
在 Inspector 视图中,常需访问正在编辑的对象。Editor 类的成员变量 target 提供了这一关联。需注意,target 是 Object 类型的对象,具体使用时可能需要进行类型转换(可使用 C# 的泛型避免重复的类型转换)。
实现自己的 INSPECTOR 界面
扩展 Editor 与扩展 EditorWindow 的唯一区别在于,需重写 OnInspectorGUI 而非 OnGUI。若要绘制默认的可编辑项,调用 DrawDefaultInspector 即可。
在 SCENE 界面定义编辑句柄
选中一个物体时,可能希望在 Scene 视图中定义一些编辑或展现操作。这可通过 OnSceneGUI 和 Handle 类完成。OnSceneGUI 用于处理来自 Scene 视图的事件,Handle 类用于在 Scene 视图实现一些 3D 的 GUI 控件(如控制对象位置的 Position 控制器)。具体使用方式可参考官方参考文档。
一些常用的功能说明
AssetDatabase.CreateAsset:可从资源目录中创建一个资源实例。Selection.activeObject:返回当前选中的对象。EditorGUIUtility.PingObject:实现在Project窗口中点击某一项的操作。Editor.Repaint:重绘界面所有的控件。XXXImporter:设置某种资源的具体导入设置(如某些情况下需设置导入的贴图为可读)。EditorUtility.UnloadUnusedAssets:释放未使用的资源,避免插件产生内存泄漏。Event.Use:标记事件已处理结束。EditorUtility.SetDirty:通知编辑器数据已修改,下次保存时新数据将被存储。