Version: Unity 6.0 (6000.0)
语言 : 中文
将属性绘制器与 IMGUI 结合使用可自定义 Inspector
使用 IMGUI 创建 TreeView

使用 IMGUI 创建自定义编辑器

注意:强烈建议用 UI 工具包扩展 Unity Editor,这样能提供比 IMGUI 更现代、更灵活和可扩展的解决方案。

为了加快应用程序开发,请为常用组件创建自定义编辑器。本页面展示了如何创建简单的脚本以使游戏对象始终看向一个点。

  1. 创建一段 C# 脚本并命名为“LookAtPoint”。
  2. 打开该脚本并将其内容替换为下面的代码。
  3. 将脚本附加到场景中的游戏对象。
using UnityEngine;
public class LookAtPoint : MonoBehaviour
{
    public Vector3 lookAtPoint = Vector3.zero;

    void Update()
    {
        transform.LookAt(lookAtPoint);
    }
}

进入播放模式后,附加脚本的游戏对象会朝向设置为“Look At Point”属性的坐标。编写编辑器脚本时,在编辑模式中执行某些脚本通常很有用(此时尚未运行您的应用程序)。为此,请向类添加ExecuteInEditMode属性,如下所示:

using UnityEngine;
[ExecuteInEditMode]
public class LookAtPoint : MonoBehaviour
{
    public Vector3 lookAtPoint = Vector3.zero;

    void Update()
    {
        transform.LookAt(lookAtPoint);
    }
}

现在,如果在 Editor 中移动游戏对象或者在 Inspector 中更改“Look At Point”的值,则游戏对象将更新其旋转,以便其看向世界空间中的目标点。

创建自定义编辑器

上文演示了如何在编辑时运行简单脚本;但仅凭此不足以创建自己的编辑器工具。下一步需要为您刚创建的脚本创建__自定义 Editor__。

在 Unity 中创建脚本时,默认情况下,此脚本继承自 MonoBehaviour,因此可作为附加到游戏对象的组件。将组件放在游戏对象上时,Inspector 会显示一个默认界面,用于查看和编辑每个公共变量,例如整数、浮点数或字符串。

LookAtPoint 组件的 Inspector 在默认情况下的外观如下:

具有公共 Vector3 字段的默认 Inspector
具有公共 Vector3 字段的默认 Inspector

自定义编辑器是一个单独脚本,可将此默认布局替换为您选择的任何编辑器控件。

要为 LookAtPoint 脚本创建自定义编辑器,请执行以下操作:

  1. 创建一段新的 C# 脚本并命名为“LookAtPointEditor”。
  2. 打开该脚本并将其内容替换为下面的代码。
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor 
{
    SerializedProperty lookAtPoint;
    
    void OnEnable()
    {
        lookAtPoint = serializedObject.FindProperty("lookAtPoint");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(lookAtPoint);
        serializedObject.ApplyModifiedProperties();
    }
}

该类必须继承自 EditorCustomEditor 属性告知 Unity 应作为哪个组件的编辑器。CanEditMultipleObjects 属性告诉 Unity 您可以用此编辑器选择多个对象并同时更改所有对象。

当编辑器在 Inspector 中显示时,Unity 将执行 OnInspectorGUI 中的代码。可以在此处插入任何 GUI 代码,其原理与 OnGUI 相同,但在 Inspector 内运行。编辑器会定义可用于访问所检查游戏对象的目标属性。

使用新编辑器时,LookAtPoint 组件的 Inspector 的外观如下:

这看起来非常相似(但现在不存在“Script”字段,因为编辑器脚本未添加任何 Inspector 代码来显示它)。

但是,现在可以在编辑器脚本中控制 Inspector 的显示方式,可以使用喜欢的任何代码来布局 Inspector 字段,允许用户调整值、显示图形或其他可视元素。实际上,在 Unity Editor 中看到的所有 Inspector(包括地形系统和动画导入设置等更复杂的检视面板)都是使用相同的 API 生成的。创建自定义编辑器时可以访问此 API。

下面是一个简单示例,用于扩展编辑器脚本以显示一条消息,指示目标点在游戏对象之上还是之下:

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
    SerializedProperty lookAtPoint;

    void OnEnable()
    {
        lookAtPoint = serializedObject.FindProperty("lookAtPoint");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(lookAtPoint);
        serializedObject.ApplyModifiedProperties();
        if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Above this object)");
        }
        if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Below this object)");
        }
    }
}

这就是 LookAtPoint 组件的 Inspector 的外观,其中显示了一条消息来指明目标点在游戏对象之上还是之下。

可以全面访问所有 IMGUI 命令来绘制任何类型的界面,包括使用 Editor 窗口中的摄像机来渲染场景。

Scene 视图添加 您可以 Scene 视图中添加额外的代码。为此,请在自定义编辑器中实现 OnSceneGUI。

OnSceneGUI 的运行方式类似于 OnInspectorGUI,只不过是在 Scene 视图中运行。为了方便在 Scene 视图中创建自己的编辑控件,可以使用在 Handles 类中定义的函数。其中的所有函数都是为 3D 模式的 Scene 视图设计的。

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
    SerializedProperty lookAtPoint;

    void OnEnable()
    {
        lookAtPoint = serializedObject.FindProperty("lookAtPoint");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(lookAtPoint);
        if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Above this object)");
        }
        if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Below this object)");
        }
        
            
        serializedObject.ApplyModifiedProperties();
    }

    public void OnSceneGUI()
    {
        var t = (target as LookAtPoint);

        EditorGUI.BeginChangeCheck();
        Vector3 pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(target, "Move point");
            t.lookAtPoint = pos;
            t.Update();
        }
    }
}

如果要添加 2D GUI 对象(例如:GUI 或 EditorGUI),需要将这些对象封装在 Handles.BeginGUI() 和 Handles.EndGUI() 的调用中。

将属性绘制器与 IMGUI 结合使用可自定义 Inspector
使用 IMGUI 创建 TreeView