工欲善其事,必先利其器
在游戏开发中,我们总是要自己开发一些游戏相关的工具,以加快开发效率,或是给其他人提供一些支持。
Unity 通过一些基类和接口,对此类工作提供了一定的支持。
MonoBehaviour
GameObject 可以在编辑器中显示一些自定义元素,比如你想用线将策划编辑的导航路点平滑地连起来,可以使用以下两个接口(可参照官方那个飞机的例子)。
OnDrawGizmos
正常状态下的显示。
OnDrawGizmosSelected
选中后的显示。
Editor
代码要放在 Editor 目录下。
如果你想对场景视图添加一些扩展,提供一些自己的编辑面板或类似旋转框一样的东西,可以继承此类。
EditorWindow
代码要放在 Editor 目录下。
完全独立的工具窗口。
PropertyDrawer
代码不用放在 Editor 目录下,放在通常的脚本目录即可。
自定义属性编辑。
编辑过程中的数据存储
SerializedObject
SerializedProperty
局限
场景中的点击处理接口
虽然可以在 OnSceneGUI 接口中添加一些自定义的鼠标交互处理,但自定义的 Editor 是要在选中自定义的组件所在的 GameObject 时才会生效。如果点击了别的 GameObject,则就不会再调用自定义 Editor 的 OnSceneGUI 接口了。
所以如果你想在全局的鼠标事件中加入自己的逻辑,目前还没有相关接口。
不过还是有个小技巧可以阻止用户通过在场景中点击切换到别的 GameObject,但不能阻止在 Hierachy 窗口选择别的 GameObject。
参考
private void OnSceneGUI()
{
if (Event.current.type == EventType.Layout)
{
HandleUtility.AddDefaultControl(0);
}
}
搜索框接口
如果你想要通过代码设置场景视图的搜索框,像 Unity 自己的导航网格工具窗口那样,过滤场景中的 Mesh Renderer 或 Terrains 对不起,暂时没有开放此类接口。
不过网上有人反编译 UnityEditor.dll,找到相关接口,通过反射,倒是也可以在代码中调用,但毕竟不健壮。
参考
/// filterMode 可以是 0:全部, 1:名字,2:类型
public static void SetSearchFilter(string filter, int filterMode)
{
SearchableEditorWindow hierarchy = null;
SearchableEditorWindow[] windows = (SearchableEditorWindow[])Resources.FindObjectsOfTypeAll (typeof(SearchableEditorWindow));
foreach (SearchableEditorWindow window in windows)
{
if(window.GetType().ToString() == "UnityEditor.SceneHierarchyWindow")
{
hierarchy = window;
break;
}
}
if (hierarchy == null)
{
return;
}
MethodInfo setSearchType = typeof(SearchableEditorWindow).GetMethod("SetSearchFilter", BindingFlags.NonPublic | BindingFlags.Instance);
object[] parameters = new object[]{filter, filterMode, false};
setSearchType.Invoke(hierarchy, parameters);
}
注意
扩展接口所在的上下文环境
所有的这些扩展接口其实都是在内部一些事件触发时调用的,比如鼠标事件、布局事件等。
而自己的代码,一方面可能要调用的系统接口对上下文环境有要求,另一方面,也有可能触发新的事件,所以在自己写代码的时候要注意不要跟上下文冲突。
-
比如你在布局时修改了场景中的游戏对象,导致要重新布局,那后续的布局代码就很可能会出问题。
-
再比如,如果不是在类似 OnGUI 这样的交互事件处理接口中,你是获取不到鼠标相关按键状态的。
-
再比如,在 OnDrawGizmos 的代码中就不能调用 GUI 布局的相关接口。
网友评论