从中派生自定义编辑器的基类。使用此类可为对象创建您自己的自定义检视面板和编辑器。
设想一个 MyPlayer 脚本,其中包含盔甲和伤害的变量,以及对枪支 GameObject 的引用。
using UnityEngine; using System.Collections;
// This is not an editor script. public class MyPlayer : MonoBehaviour { public int armor = 75; public int damage = 25; public GameObject gun;
void Update() { // Update logic here... } }
Using a custom Editor, the apperance of the script in the Inspector can be changed.
您可以使用 CustomEditor 属性将编辑器附加到自定义组件。
There are multiple ways to design custom Editors.
If you want the Editor to support multi-object editing, you can use the CanEditMultipleObjects attribute.
Instead of modifying script variables directly, it's advantageous to use the SerializedObject and SerializedProperty
system to edit them, since this automatically handles multi-object editing, undo, and Prefab overrides. If this approach is used a user can select multiple assets in the hierarchy window and change the values for all of them at once.
You can either use UIElements to build your custom UI or you can use IMGUI. To create a custom inspector using UIElements, you have to override the Editor.Editor on the Editor class. To create a custom inspector using IMGUI, you have to override the Editor.OnInspectorGUI on the Editor class. If you use UIElements and have Editor.Editor overwritten, any existing IMGUI implementation using Editor.OnInspectorGUI on the same Editor will be ignored.
Here's an example of a custom inspector using UIElements:
using UnityEditor; using UnityEngine.UIElements; using UnityEditor.UIElements;
// Custom Editor using SerializedProperties and UIElements. // Automatic handling of multi-object editing, undo, and Prefab overrides. [CustomEditor(typeof(MyPlayer))] public class MyPlayerEditorUIE : Editor { SerializedProperty damageProp; SerializedProperty armorProp; SerializedProperty gunProp;
void OnEnable() { // Setup the SerializedProperties. damageProp = serializedObject.FindProperty ("damage"); armorProp = serializedObject.FindProperty ("armor"); gunProp = serializedObject.FindProperty ("gun"); }
public override VisualElement CreateInspectorGUI() { // Create inspector container element. var inspector = new VisualElement();
// Create custom element. var customLabel = new Label ("This is a custom inspector.");
// Create field elements. var damageField = new PropertyField (damageProp, "Damage"); var armorField = new PropertyField (armorProp, "Armor"); var gunField = new PropertyField (gunProp, "Gun Object");
// Add all elements to the container. inspector.Add (customLabel); inspector.Add (damageField); inspector.Add (armorField); inspector.Add (gunField);
return inspector; } }
Here's an example of a custom inspector using IMGUI and multi-selection:
Custom editor in the Inspector.
using UnityEditor; using UnityEngine; using System.Collections;
// Custom Editor using SerializedProperties. // Automatic handling of multi-object editing, undo, and Prefab overrides. [CustomEditor(typeof(MyPlayer))] [CanEditMultipleObjects] public class MyPlayerEditor : Editor { SerializedProperty damageProp; SerializedProperty armorProp; SerializedProperty gunProp;
void OnEnable() { // Setup the SerializedProperties. damageProp = serializedObject.FindProperty ("damage"); armorProp = serializedObject.FindProperty ("armor"); gunProp = serializedObject.FindProperty ("gun"); }
public override void OnInspectorGUI() { // Update the serializedProperty - always do this in the beginning of OnInspectorGUI. serializedObject.Update ();
// Show the custom GUI controls. EditorGUILayout.IntSlider (damageProp, 0, 100, new GUIContent ("Damage"));
// Only show the damage progress bar if all the objects have the same damage value: if (!damageProp.hasMultipleDifferentValues) ProgressBar (damageProp.intValue / 100.0f, "Damage");
EditorGUILayout.IntSlider (armorProp, 0, 100, new GUIContent ("Armor"));
// Only show the armor progress bar if all the objects have the same armor value: if (!armorProp.hasMultipleDifferentValues) ProgressBar (armorProp.intValue / 100.0f, "Armor");
EditorGUILayout.PropertyField (gunProp, new GUIContent ("Gun Object"));
// Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI. serializedObject.ApplyModifiedProperties (); }
// Custom GUILayout progress bar. void ProgressBar (float value, string label) { // Get a rect for the progress bar using the same margins as a textfield: Rect rect = GUILayoutUtility.GetRect (18, 18, "TextField"); EditorGUI.ProgressBar (rect, value, label); EditorGUILayout.Space (); } }
Alternatively, if automatic handling of multi-object editing, undo, and Prefab overrides is not needed, the script variables can be modified directly by the editor without using the SerializedObject and SerializedProperty system, as in the IMGUI example below.
using UnityEditor; using UnityEngine; using System.Collections;
// Example script with properties. public class MyPlayerAlternative : MonoBehaviour { public int damage; public int armor; public GameObject gun;
// ...other code... }
// Custom Editor the "old" way by modifying the script variables directly. // No handling of multi-object editing, undo, and Prefab overrides! [CustomEditor (typeof(MyPlayerAlternative))] public class MyPlayerEditorAlternative : Editor {
public override void OnInspectorGUI() { MyPlayerAlternative mp = (MyPlayerAlternative)target;
mp.damage = EditorGUILayout.IntSlider ("Damage", mp.damage, 0, 100); ProgressBar (mp.damage / 100.0f, "Damage");
mp.armor = EditorGUILayout.IntSlider ("Armor", mp.armor, 0, 100); ProgressBar (mp.armor / 100.0f, "Armor");
bool allowSceneObjects = !EditorUtility.IsPersistent (target); mp.gun = (GameObject)EditorGUILayout.ObjectField ("Gun Object", mp.gun, typeof(GameObject), allowSceneObjects); }
// Custom GUILayout progress bar. void ProgressBar (float value, string label) { // Get a rect for the progress bar using the same margins as a textfield: Rect rect = GUILayoutUtility.GetRect (18, 18, "TextField"); EditorGUI.ProgressBar (rect, value, label); EditorGUILayout.Space (); } }
serializedObject | 表示正在检查的一个或多个对象的 SerializedObject。 |
target | 所检查的对象。 |
targets | 正在检查的所有对象的数组。 |
DrawDefaultInspector | 绘制内置检视面板。 |
DrawHeader | 调用此函数以绘制编辑器标头。 |
DrawPreview | 预览绘制的第一个入口点。 |
GetInfoString | 实现此方法以在资源预览上显示资源信息。 |
GetPreviewTitle | 如果要更改 Preview 区域的标签,可重载此方法。 |
HasPreviewGUI | 如果实现 OnPreviewGUI,可在子类中重载此方法。 |
OnInspectorGUI | 实现此函数以创建自定义检视面板。 |
OnInteractivePreviewGUI | 实现此方法可创建您自己的交互式自定义预览。交互式自定义预览用于检视面板和对象选择器的预览区域。 |
OnPreviewGUI | 实现此方法可为检视面板、主编辑器标头和对象选择器的预览区域创建您自己的自定义预览。 |
OnPreviewSettings | 如果要在预览标头中显示自定义控件,可重载此方法。 |
RenderStaticPreview | 如果要渲染静态预览,可重载此方法。 |
Repaint | 重新绘制显示此编辑器的任意检视面板。 |
RequiresConstantRepaint | 是否需要在当前状态下不断重绘此编辑? |
UseDefaultMargins | 如果您不想使用默认边距,可在子类中重载此方法以返回 false。 |
ShouldHideOpenButton | 返回检视面板中“open”按钮的可见性设置。 |
CreateCachedEditor | 返回时,previousEditor 为 targetObject 或 targetObjects 的编辑器。如果该编辑器已在跟踪对象,则函数会返回,否则该函数会销毁之前的编辑器并创建一个新编辑器。 |
CreateCachedEditorWithContext | 使用上下文对象创建缓存的编辑器。 |
CreateEditor | 为 targetObject 或 targetObjects 创建自定义编辑器。 |
CreateEditorWithContext | 使用上下文对象为 targetObject 或 targetObjects 创建自定义编辑器。 |
OnSceneGUI | Enables the Editor to handle an event in the Scene view. |
finishedDefaultHeaderGUI | An event raised while drawing the header of the Inspector window, after the default header items have been drawn. |
hideFlags | Should the object be hidden, saved with the Scene or modifiable by the user? |
name | 对象的名称。 |
GetInstanceID | 返回对象的实例 ID。 |
ToString | 返回 GameObject 的名称。 |
Destroy | 删除 GameObject、组件或资源。 |
DestroyImmediate | 立即销毁对象 /obj/。强烈建议您改用 Destroy。 |
DontDestroyOnLoad | Do not destroy the target Object when loading a new Scene. |
FindObjectOfType | 返回第一个类型为 type 的已加载的激活对象。 |
FindObjectsOfType | 返回所有类型为 type 的已加载的激活对象的列表。 |
Instantiate | 克隆 original 对象并返回克隆对象。 |
CreateInstance | 创建脚本化对象的实例。 |
bool | 该对象是否存在? |
operator != | 比较两个对象是否引用不同的对象。 |
operator == | 比较两个对象引用,判断它们是否引用同一个对象。 |