CustomEditor in Unity (custom editor)

This article shares the CustomEditor (custom editor) in Unity

Unity provides the display and modification of the property panel for classes that inherit MonoBehavior scripts (of course there are other classes).

By default, the public fields of the class are displayed, and of course these fields are also serialized and stored on the mounted prefab.

In some cases we need to customize the display and modification logic, then we need to use it CustomEditor.

This article will CustomEditordo some basic introduction, mainly around the serializable fields of the class .

Basic knowledge of CustomEditor

Below we first give a relatively complete code, and then explain its meaning one by one.

// Assets/xxxx/MonoTestEditor.cs
public class MonoTest : MonoBehaviour
{
    public enum EnumValue
    {
        EnumValue1,
        EnumValue2,
        EnumValue3,
    }
    
    public int intValue;
    public bool boolValue;

    public EnumValue enumValue;
}

// Assets/xxxx/Editor/MonoTestEditor.cs
[CustomEditor(typeof(MonoTest), true)]
public class MonoTestEditor : Editor
{
    private MonoTest m_Target;
    
    private SerializedProperty m_IntValue;
    private SerializedProperty m_BoolValue;
    private SerializedProperty m_EnumValue;

    private void OnEnable()
    {
        _target = target as MonoTest;
        
        m_IntValue = serializedObject.FindProperty("intValue");
        m_BoolValue = serializedObject.FindProperty("boolValue");
        m_EnumValue = serializedObject.FindProperty("enumValue");
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        
        serializedObject.Update();
        //......//
        serializedObject.ApplyModifiedProperties();
    }
}

First of all, we need to put the custom Editor class in any Editor directory.

Then use [CustomEditor(typeof(MonoTest), true)]the attribute to describe which class to customize, and the second parameter represents whether to take effect on its subclass.

Then inherit the class from the parent class public class MonoTestEditor : Editor.

CustomEditorThe class has two key attributes targetand serializedObject, the former represents the instantiated object of the class to be customized, the default is Objectthe type, we generally convert it to the corresponding class in OnEnable: _target = target as MonoTest;, serializedObjectthe attribute encapsulates all the serialized fields on the corresponding class And some useful methods, each field corresponds to a serialized property SerializedProperty, and bind the two before use: m_IntValue = serializedObject.FindProperty("intValue");.

Then rewrite OnInspectorGUIthe method, which will be called when the object gets the focus or the object properties change or in some other cases, base.OnInspectorGUI();which means that all serialized properties will be drawn according to the default behavior of the Editor. It means that if there is no other code, the property panel Consistent with the default drawing. If this sentence is removed, only the name of the script will be drawn on the property panel.

Then serializedObjectrefresh and apply changes to: serializedObject.Update();, serializedObject.ApplyModifiedProperties();.

Finally, we customize our own display between the two lines of code. By the way, serializedObject.ApplyModifiedProperties()the return value of can indicate whether the serialized field has been modified.

Customize the core logic of Editor

The main content of our custom Editor is: define the appearance of the serialized field, and do some corresponding operations when the field changes .

So the main thing to deal with is serializedObjectand serializedObject, of course, there are various classes that build the appearance, such as GUI, GUILayout, EditorGUILayoutetc. This article is just a basic introduction to the custom Editor, and will not involve the GUIdetailed introduction of related classes.

Defines the appearance of serialized fields

In some cases, the appearance of serialized fields is too simple, and we need a richer display. In this case, using GUIrelated interfaces can achieve the goal. Some examples are given below.

public override void OnInspectorGUI()
{
    // base.OnInspectorGUI(); // 将默认的绘制关闭

    serializedObject.Update();

    // 使用基本的绘制
    // EditorGUILayout.PropertyField(m_IntValue, new GUIContent("这是一个整型值的提示"));
    // EditorGUILayout.PropertyField(m_BoolValue);    
    // EditorGUILayout.PropertyField(m_EnumValue);

    var content = new GUIContent {text = "整型值", tooltip = "这是一个整型值的提示"};
    EditorGUILayout.IntSlider(m_IntValue, 0, 100, content); // 使用一个滑动条来代替基本的绘制, 可以规定上下界, 可以修改相关提示

    var curValue = m_BoolValue.boolValue;
    m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);
    if (m_BoolValue.boolValue != curValue)
        Debug.LogError("value changed!" + m_BoolValue.boolValue); // 在值变化后进行一些操作
    
    //m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);
    // if (serializedObject.ApplyModifiedProperties())
       // Debug.LogError("value changed!" + m_BoolValue.boolValue); // 在值变化后进行一些操作

    m_EnumValue.intValue = (int)(MonoTest.EnumValue)EditorGUILayout.EnumPopup("enumValue", (MonoTest.EnumValue)m_EnumValue.intValue); // 使用自定义的枚举值

    serializedObject.ApplyModifiedProperties();
}

insert image description here

Use EditorGUILayout.PropertyField(xxxx)will draw the field according to the default behavior, and you can also use other controls to get the value and assign the field: m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);, or directly assign the value to the bound object, but this assignment needs to be manually saved and modifiedm_Target when it is performed on the prefab . So We generally use it as an intermediary to manipulate serialized objects.SerializedProperty

Do something when a field changes

We can have some means to detect changes in persistent fields, and do some corresponding operations when they change.

The first way is to store a copy of the current value before drawing, and then compare the two values ​​after drawing assignment, such as:

m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);
if (m_BoolValue.boolValue != curValue)
	Debug.LogError("value changed!" + m_BoolValue.boolValue); // 在值变化后进行一些操作

The second way is to apply an application to each field immediately after drawing serializedObject.ApplyModifiedProperties();. If the value changes, the function of this method returns true, such as:

m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);
if (serializedObject.ApplyModifiedProperties())
	Debug.LogError("value changed!" + m_BoolValue.boolValue); // 在值变化后进行一些操作

Disallow modification of certain fields

Sometimes we need to prohibit the modification of certain fields. At this time, we only need to switch the GUI before and after drawing the field. For example, the field can only be modified in non-running mode:

if (Application.isPlaying)
{
    GUI.enabled = false;
    m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);
    GUI.enabled = true;
}
else
{
    m_BoolValue.boolValue = EditorGUILayout.Toggle("布尔值", m_BoolValue.boolValue);
}

In this way, the drawn field will be grayed out in run mode, indicating that it cannot be edited.

Summarize

This article CustomEditormakes a brief introduction to , and mentions some possible problems and tips, hoping to help everyone.

Guess you like

Origin blog.csdn.net/woodengm/article/details/120952669