版本:Unity 6 (6000.0)
语言:English
使用 IMGUI 中的属性绘制器来自定义检查器
使用 IMGUI 创建 TreeView

使用 IMGUI 创建自定义编辑器

注意:强烈建议使用 UI 工具包 来扩展 Unity 编辑器,因为它提供了一种比 IMGUI 更现代、更灵活、更具可扩展性的解决方案。

为了加快应用程序开发速度,可以为常用的组件创建自定义编辑器。此页面将向您展示如何创建一个简单的脚本,使 游戏对象Unity 场景中的基本对象,可以表示角色、道具、场景、摄像机、路径点等等。游戏对象的功 能由附加在其上的组件定义。 更多信息
参见 术语表
始终看向一个点。

  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);
    }
}

现在,如果您在编辑器中移动游戏对象,或在 检查器一个 Unity 窗口,显示有关当前选定的游戏对象、资源或项目设置的信息,允许您检查和编辑值。 更多信息
参见 术语表
中更改“Look At Point”的值,则游戏对象会更新其旋转,使其在世界空间中看向目标点。

创建自定义编辑器

以上演示了如何在编辑时运行简单的脚本,但是这本身不允许您创建自己的编辑器工具。下一步是为刚刚创建的脚本创建自定义编辑器

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

这是 LookAtPoint 组件的检查器默认外观

A default Inspector with a public Vector3 field
具有公共 Vector3 字段的默认检查器

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

要为 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 您可以使用此编辑器选择多个对象并同时更改它们。

Unity 在 OnInspectorGUI 中执行代码,它在检查器中显示编辑器。您可以在此处放置任何 GUI 代码,它的工作方式与 OnGUI 相同,但在检查器内部运行。Editor 定义了 target 属性,您可以使用它来访问正在检查的游戏对象。

这是使用新编辑器时 LookAtPoint 组件的检查器外观

这看起来非常相似(尽管“脚本”字段现在不存在,因为编辑器脚本没有添加任何检查器代码来显示它)。

但是,现在您已控制了检查器在编辑器脚本中的显示方式,您可以使用任何您喜欢的代码来布置检查器字段,允许用户调整值,甚至显示图形或其他 视觉元素视觉树的一个节点,它实例化或派生自 C# VisualElement 类。您可以设置外观样式、定义行为并在屏幕上将其显示为 UI 的一部分。 更多信息
参见 术语表
。实际上,您在 Unity 编辑器中看到的每个检查器,包括更复杂的检查器,例如 地形场景中的景观。地形游戏对象会向场景添加一个大的平面,您可以使用地形的检查器窗口创建详细的景观。 更多信息
参见 术语表
系统和动画导入设置,都是使用与您在创建自己的自定义编辑器时可以访问的相同的 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 组件的检查器外观。

您可以完全访问所有 IMGUI 命令来绘制任何类型的界面,包括使用编辑器窗口内的 摄像机一个组件,它创建场景中特定视点的图像。输出要么绘制到屏幕上,要么捕获为纹理。 更多信息
参见 术语表
渲染场景。

场景视图添加

您可以向 场景视图对您正在创建的世界进行交互式查看。您可以使用场景视图选择和放置场景、角色、摄像机、灯光以及所有其他类型的游戏对象。 更多信息
参见 术语表
添加额外的代码。为此,请在您的自定义编辑器中实现 OnSceneGUI。

OnSceneGUI 的工作方式与 OnInspectorGUI 完全相同,只是它在场景视图中运行。为了帮助您创建自己的编辑控件,您可以使用 Handles 类中定义的函数。其中的所有函数都设计用于在 3D 场景视图中工作。

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 中的属性绘制器来自定义检查器
使用 IMGUI 创建 TreeView