版本: 2022.3+
虽然您的 MonoBehaviour 和 ScriptableObjects 有一个默认的 检视器一个 Unity 窗口,显示有关当前选定游戏对象、资源或项目设置的信息,允许您检查和编辑值。 更多信息
查看 词汇表,但您可能希望为您的类编写一个自定义检视器。自定义检视器可以帮助您执行以下操作
本示例为 MonoBehaviour 类创建自定义检视器。它同时使用 C# 脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间推移修改组件属性并以任何您喜欢的方式响应用户输入。 更多信息
查看 词汇表 和 UI Builder 来创建 UI。自定义检视器还具有自定义的 属性绘制器一个 Unity 功能,允许您使用脚本上的属性或通过控制特定可序列化类的外观来自定义检视器窗口中某些控件的外观 更多信息
查看 词汇表。
自定义检视器显示 Car
类的属性,包括制造商、制造年份、颜色和轮胎列表。检视器使用 PropertyField 控件显示 Car
类的属性,并使用自定义属性绘制器显示 Tire
类的属性。
您可以在此 GitHub 存储库 中找到本示例创建的完整文件。
本指南适用于熟悉 Unity 编辑器、UI 工具包和 C# 脚本的开发人员。在开始之前,请熟悉以下内容
要创建自定义检视器,首先定义一个从 MonoBehaviour
继承的自定义类。自定义类表示一个具有多个属性的简单 car
。
在 Unity 中使用任何模板创建一个项目。
在您的 项目窗口一个窗口,显示您的 Assets
文件夹的内容(项目选项卡) 更多信息
查看 词汇表 中,创建一个名为 create-a-custom-inspector
的文件夹来存储所有文件。
使用以下内容创建一个名为 Car.cs
的 C# 脚本
using UnityEngine;
public class Car : MonoBehaviour
{
public string m_Make = "Toyota";
public int m_YearBuilt = 1980;
public Color m_Color = Color.black;
}
在 场景场景包含游戏环境和菜单。将每个唯一的场景文件视为一个唯一的关卡。在每个场景中,您放置环境、障碍物和装饰,本质上是分段设计和构建游戏。 更多信息
查看 词汇表 中创建一个新的 游戏对象Unity 场景中的基本对象,可以代表角色、道具、场景、相机、路点等。游戏对象的功
要为任何序列化对象创建自定义检视器,您需要创建一个从 Editor 基类派生的类,并向其添加 CustomEditor 属性。此属性让 Unity 知道此自定义检视器代表哪个类。
注意:自定义检视器脚本必须位于 Editor
文件夹或仅限编辑器的程序集定义中。这是因为 UnityEditor
命名空间对于创建自定义检视器至关重要,在这些区域之外无法访问它。如果您尝试在不遵守此规则的情况下创建独立构建,则构建过程将失败。
在 create-a-custom-inspector
文件夹中创建一个名为 Editor
的文件夹。
在 Editor
文件夹中创建一个名为 Car_Inspector.cs
的 C# 脚本,内容如下
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CustomEditor(typeof(Car))]
public class Car_Inspector : Editor
{
}
选择已附加 Car
组件的游戏对象。默认检视器将显示。
要替换默认检视器,在 Car_Inspector
类中,添加以下代码以覆盖 CreateInspectorGUI() 并返回一个新的 视觉元素视觉树的一个节点,它实例化或派生自 C# VisualElement
类。您可以设置外观、定义行为,并将其显示在屏幕上作为 UI 的一部分。 更多信息
查看 词汇表,其中包含 UI
public override VisualElement CreateInspectorGUI()
{
// Create a new VisualElement to be the root of our Inspector UI.
VisualElement myInspector = new VisualElement();
// Add a simple label.
myInspector.Add(new Label("This is a custom Inspector"));
// Return the finished Inspector UI.
return myInspector;
}
选择已附加 Car
组件的游戏对象。现在,检视器显示标签 This is a custom Inspector
而不是默认检视器。
您可以使用 UI Builder 创建自定义检视器 UI,并使用 C# 脚本从 UXML 文件加载和实例化 UI。
要打开 UI Builder,请选择 窗口 > UI 工具包 > UI Builder。
选择 文件 > 新建 以创建一个新的视觉树资源。
要 在 UI Builder 中启用仅限编辑器的控件,请选择 层次结构 视图中的 <unsaved file>*.uxml
,然后选中 编辑器扩展创作 复选框。
从 库 拖动一个标签控件到 层次结构。这将向视觉树添加一个标签控件。
在标签控件的检视器面板中,更新标签文本。
选择 文件 > 保存,并将视觉树保存为 Car_Inspector_UXML.uxml
到 Assets/create-a-custom-inspector
文件夹。
要在自定义检视器中使用您创建的 UXML 文件,请将该文件分配给自定义检视器,并在 CreateInspectorGUI()
函数中加载和克隆它,并将其添加到视觉树。为此,您可以使用 CloneTree 方法。您可以将任何 VisualElement
作为参数传递,以充当创建元素的父元素。
在 Car_Inspector.cs
中,在您的脚本中为 VisualTreeAsset
创建一个公共变量,并将 Car_Inspector_UXML.uxml
分配给它。
public VisualTreeAsset m_InspectorXML;
将 CreateInspectorGUI()
方法更新为以下内容
public override VisualElement CreateInspectorGUI()
{
// Create a new VisualElement to be the root of our Inspector UI.
VisualElement myInspector = new VisualElement();
// Add a simple label.
myInspector.Add(new Label("This is a custom Inspector"));
// Load the UXML file.
m_InspectorXML= AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/create-a-custom-inspector/Car_Inspector_UXML.uxml");
// Instantiate the UXML.
myInspector = m_InspectorXML.Instantiate();
// Return the finished Inspector UI.
return myInspector;
}
选择已附加 Car
组件的游戏对象。现在,car
组件的检视器显示两个标签:一个通过脚本,另一个通过 UI Builder/UXML。
此自定义检视器显示 Car
类的所有属性。当用户修改任何 UI 控件时,Car
类实例内的值会发生变化。为此,请将 UI 控件添加到视觉树并将其绑定到类的各个属性。
要将控件绑定到序列化属性,请将属性分配给控件的 binding-path
字段。当您创建自定义检视器时,绑定是自动的。 CreateInspectorGUI()
在您返回视觉树后会进行隐式绑定。有关更多信息,请参阅 序列化对象数据绑定。
双击 Car_Inspector_UXML.uxml
以在 UI Builder 中打开它。
添加一个 文本字段控件文本字段控件向用户显示一段非交互式文本,例如标题、其他 GUI 控件的标签或说明。 更多信息
查看 词汇表。
在文本字段的检视器面板中,将标签文本设置为 Make of the car
。
将绑定路径设置为 m_Make
。
向 样式类列表 添加样式类 unity-base-field__aligned
,以便文本字段与检视器窗口中的其他字段对齐。有关更多信息,请参阅 BaseField。
在 UI Builder 中,选择 文件 > 保存。
选择已附加 Car
组件的游戏对象。现在,car
组件的检视器显示 Make of the car
文本字段。文本字段绑定到 Car
类的 m_Make
属性。
要显示 Car
类的属性,请为每个字段添加一个控件。控件必须与属性类型匹配。例如,您必须将 int
绑定到整数字段或整数滑块。
除了根据属性类型添加特定控件外,您还可以使用通用 PropertyField 控件。此控件适用于大多数类型的序列化属性,并为该属性类型生成默认的检视器 UI。
PropertyField
的优势在于,当您在脚本中更改变量类型时,检视器 UI 会自动调整。但是,您无法在 UI Builder 中预览控件,因为在将视觉树绑定到序列化对象之前,控件类型是未知的。
双击 Car_Inspector_UXML.uxml
以在 UI Builder 中打开它。
为Car
类的m_YearBuilt
属性添加一个PropertyField控件,并设置绑定路径和标签文本。
在**样式类列表**中添加样式类unity-base-field__aligned
。
为Car
类的m_Color
属性添加一个PropertyField控件,并设置绑定路径和标签文本。
在**样式类列表**中添加样式类unity-base-field__aligned
。
在 UI Builder 中,选择 文件 > 保存。
选择具有Car
组件的游戏对象。现在,car
组件的检查器将显示“建造年份”和“油漆颜色”属性字段。
自定义属性绘制器是针对自定义可序列化类的自定义检查器UI。如果该可序列化类是另一个序列化对象的的一部分,则自定义UI会在检查器中显示该属性。在UI工具包中,如果存在自定义属性绘制器,则PropertyField
控件将显示该属性的自定义属性绘制器。
在create-a-custom-inspector
文件夹中,创建一个名为Tire.cs
的新脚本,内容如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Tire
{
public float m_AirPressure = 21.5f;
public int m_ProfileDepth = 4;
}
在Car.cs
中,向Car
类添加一个Tire
列表。完成后的Car.cs
文件如下所示
using UnityEngine;
public class Car : MonoBehaviour
{
public string m_Make = "Toyota";
public int m_YearBuilt = 1980;
public Color m_Color = Color.black;
// This car has four tires.
public Tire[] m_Tires = new Tire[4];
}
PropertyField控件适用于所有标准属性类型,还支持自定义可序列化类和数组。要显示汽车轮胎的属性,请在Car_Inspector_UXML.uxml
中添加另一个PropertyField
,并将其绑定到m_Tires
。完成后的Car_Inspector_UXML.uxml
文件如下所示
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
<ui:TextField picking-mode="Ignore" label="Make of the car" value="filler text" binding-path="m_Make" class="unity-base-field__aligned" />
<uie:PropertyField binding-path="m_YearBuilt" label="Year Built" class="unity-base-field__aligned" />
<uie:PropertyField binding-path="m_Color" label="Paint Color" class="unity-base-field__aligned" />
<uie:PropertyField label="Tires" binding-path="m_Tires" class="unity-base-field__aligned" />
<ui:Foldout text="Default Inspector" value="false" name="Default_Inspector" />
</ui:UXML>
选择具有Car
组件的游戏对象。现在,car
组件的检查器将显示“轮胎”属性字段。
您可以创建自定义属性绘制器来自定义列表中各个Tire
元素的外观。自定义属性绘制器不从Editor
基类派生,而是从PropertyDrawer
类派生。
您可以使用C#脚本或UXML创建属性的UI。此示例使用C#脚本创建自定义UI。要为自定义属性创建UI,请覆盖CreatePropertyGUI方法。
在Editor
文件夹中,创建一个名为Tire_PropertyDrawer.cs
的新脚本,内容如下
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CustomPropertyDrawer(typeof(Tire))]
public class Tire_PropertyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// Create a new VisualElement to be the root the property UI.
var container = new VisualElement();
// Create drawer UI using C#.
var popup = new UnityEngine.UIElements.PopupWindow();
popup.text = "Tire Details";
popup.Add(new PropertyField(property.FindPropertyRelative("m_AirPressure"), "Air Pressure (psi)"));
popup.Add(new PropertyField(property.FindPropertyRelative("m_ProfileDepth"), "Profile Depth (mm)"));
container.Add(popup);
// Return the finished UI.
return container;
}
}
选择具有Car
组件的游戏对象。现在,car
组件的检查器将显示带有自定义属性绘制器的“轮胎”属性字段。
创建一个Foldout控件来显示默认检查器UI。要将默认检查器UI附加到Foldout,您必须获取对其的引用。您可以使用UQuery从检查器的可视化树中检索Foldout的可视化元素,并使用FillDefaultInspector方法InspectorElement类将默认检查器UI附加到Foldout控件。
双击Car_Inspector_UXML.uxml
文件,在UI Builder中打开它。
向UI中添加一个Foldout控件,将其命名为Default_Inspector
,并设置标签文本。
在Car_Inspector.cs
文件中,更新CreateInspectorGUI()
方法以获取对Default_Inspector
Foldout的引用,并将默认检查器UI附加到它。完成后的Car_Inspector.cs
文件如下所示
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CustomEditor(typeof(Car))]
public class Car_Inspector : Editor
{
public VisualTreeAsset m_InspectorXML;
public override VisualElement CreateInspectorGUI()
{
// Create a new VisualElement to be the root of the Inspector UI.
VisualElement myInspector = new VisualElement();
// Load the reference UXML.
m_InspectorXML= AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/create-a-custom-inspector/Car_Inspector_UXML.uxml");
// Instantiate the UXML.
myInspector = m_InspectorXML.Instantiate();
// Get a reference to the default Inspector Foldout control.
VisualElement InspectorFoldout = myInspector.Q("Default_Inspector");
// Attach a default Inspector to the Foldout.
InspectorElement.FillDefaultInspector(InspectorFoldout, serializedObject, this);
// Return the finished Inspector UI.
return myInspector;
}
}
选择具有Car
组件的游戏对象。现在,car
组件的检查器将显示“默认检查器”Foldout,其中包含默认检查器UI。