Unity编辑器扩展:自定义编辑器(Inspector+SceneView)

一、引言

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

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

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

  1. 创建一个新的 C#脚本命名为“LookAtPoint”,内容如下所示,并将脚本附加到场景中的游戏对象。
  2. 创建一段新的 C# 脚本并将其命名为“LookAtPointEditor”,内容如下所示。
//C# 示例 (LookAtPoint.cs)
using UnityEngine;
[ExecuteInEditMode]
public class LookAtPoint : MonoBehaviour
{
    public Vector3 lookAtPoint = Vector3.zero;

    void Update()
    {	
    	//将自身朝向设置为“Look At Point”属性的坐标
        transform.LookAt(lookAtPoint);
    }
}

//C# 示例 (LookAtPointEditor.cs)
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 实例的引用
    	//则必须确保首先手动调用其 SerializedObject.Update 方法
    	//然后再从此实例中读取任何数据,因为一个或多个目标对象可能已在其他位置修改过
    	//例如在单独的 SerializedObject 流中。
        serializedObject.Update();
        
        EditorGUILayout.PropertyField(lookAtPoint);
        
        //首次创建 SerializedObject 实例后,实例是最新的。
        //对于在此数据流中访问的 SerializedProperty 进行的任何更改
        //必须最终通过 SerializedObject.ApplyModifiedProperties 方法来刷新。
        serializedObject.ApplyModifiedProperties();
    }
}

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

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

Editor 类有一个 serializedObject 属性,该属性为所有被检查目标(在本例中为 SineAnimation 组件)提供了一个流,从而更轻松地支持同时编辑多个对象。由于此 SerializedObject 实例在 Editor 实例的生命周期内持续存在,因此 OnInspectorGUI 的基本实现在绘制任何控件之前处理 Update 调用,并在任何用户交互之后处理调用 ApplyModifiedProperties 的调用。因此,在方法退出前,必须通过 ApplyModifiedProperties 来刷新按下此检视面板中添加的按钮时进行的所有修改,否则下次 Editor.OnInspectorGUI 的基本实现在 serializedObject 实例上调用 SerializedObject.Update 方法时,这些修改将丢失。

二、自定义Inspector

1. PropertyAttribute

在编写Property时,可以添加一些Attribute,使得Inspector面板展示出一定的结构性。内置可以使用的Attribute有:

[Range(1,2)]

[Header("Header"))]

[Space(20))]

[Tooltip("提示文字"))]

[ContextMenu("OutInfo"))]

[Multiline(5))]

我们还可以自定义一些Attribute,实现步骤如下:

  • 实现一个自定义的属性类继承自PropertyAttribute

    public class LabelAttribute : PropertyAttribute
    {
        public string label;
        public LabelAttribute(string label)
        {
            this.label = label;
        }
    }
    
  • 实现对应的PropertyDrawer并保存在Editor目录下

    using UnityEngine;
    using UnityEditor;
    using System;
    
    [CustomPropertyDrawer(typeof(LabelAttribute),false)]
    public class LabelDrawer : PropertyDrawer
    {
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            label.text = (attribute as LabelAttribute).label;
            EditorGUI.PropertyField(position, property, label);
        }
    }
    
  • 组件中调用

      public class Chinese : MonoBehaviour {
               [LabelAttribute ("中文属性名")]//修改的Property的名字,即原来Inspector中显示的“TestInt”变成了“中文属性名”
              public int testInt;
          
              [Header("中文")]  //内置的Header标签只是在Property上方添加了label,注意和上面的区别
              public string Name;
      }
    

2. OnInspectorGUI

Unity 在 Inspector 中显示编辑器时将执行 OnInspectorGUI 中的代码。可以在此处插入任何 GUI 代码,原理就像 OnGUI 一样,不过是在 Inspector 内运行。编辑器会定义可用于访问所检查游戏对象的目标属性。

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

三、控制SceneView

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

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

参考

Unity中文手册:自定义编辑器

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity CustomEditor 是Unity中一种自定义Inspector界面的方式,可以帮助开发者更加方便地编辑和管理组件。 以下是一个使用 CustomEditor 的案例: 假设有一个名为“Player”的脚本,它包含一个 public 变量“health”,并且希望在 Inspector 界面中添加一个进度条来显示当前健康值。 首先,需要创建一个名为“PlayerEditor”的自定义编辑器类,并继承 UnityEditor.Editor 类。 在 PlayerEditor 类中,需要使用 SerializedProperty 类来获取 health 变量并创建一个进度条。 代码示例如下: ```csharp using UnityEditor; using UnityEngine; [CustomEditor(typeof(Player))] public class PlayerEditor : Editor { SerializedProperty healthProp; void OnEnable() { healthProp = serializedObject.FindProperty("health"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(healthProp); float healthValue = healthProp.floatValue; EditorGUILayout.LabelField("Health"); EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(), healthValue / 100f, healthValue.ToString("0.00")); serializedObject.ApplyModifiedProperties(); } } ``` 在上面的代码中,首先使用 CustomEditor 特性将 Player 类与 PlayerEditor 类关联起来。 然后,在 OnEnable 方法中,使用 SerializedObject 和 SerializedProperty 类来获取 health 变量。 在 OnInspectorGUI 方法中,使用 EditorGUILayout 类将 health 变量显示为默认的 Inspector 字段。 接下来,使用 EditorGUI 类创建一个进度条,并将其显示在 Inspector 界面中。 最后,使用 SerializedObject 类应用修改后的属性值。 当保存 Player 脚本并返回 Unity 编辑器时,应该可以看到自定义进度条已添加到 Inspector 界面中。 这就是一个简单的 CustomEditor 示例,它演示了如何在 Unity 中创建自定义 Inspector 界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值