Version: 6000.3
语言: 中文
将属性抽屉与 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 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。更多信息
请参阅术语表
,游戏对象会更新其旋转,以便查看世界空间中的目标点。

制作自定义编辑器

以上演示了如何在编辑期间运行简单的脚本,但仅凭这一点并不能让你创建自己的编辑器工具。下一步是为刚刚创建的脚本创建自定义编辑器

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

默认情况下,LookAtPoint 组件的 Inspector 如下所示:

具有公共 Vector3 字段的默认检查器
具有公共 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 中执行代码,并在 Inspector 中显示编辑器。您可以在此处放置任何 GUI 代码,它的工作方式与 OnGUI 相同,但在 Inspector 中运行。编辑器定义了可用于访问正在检查的游戏对象的目标属性。

这是 LookAtPoint 组件的 Inspector 在新编辑器中的外观:

新编辑器中的 Look At Point 组件
新编辑器中的 Look At Point 组件

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

但是,现在您可以控制检查器在编辑器脚本中的显示方式,您可以使用任何您喜欢的代码来布局检查器字段,允许用户调整值,甚至显示图形或其他视觉元素实例化或派生自 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 组件的 Inspector 的外观,显示目标点是高于还是低于游戏对象的消息。

Inspector 中的组件现在包含有关相对于游戏对象的目标位置的信息
Inspector 中的组件现在包含有关目标相对于游戏对象的位置的信息

您可以完全访问所有 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