Unity条件字段自定义编辑器

3

我的目标: 我有一个脚本

public class MyScript: MonoBehaviour
{
   public bool A;
   public bool B;
}

如果A为TRUE,我希望只显示B

我对脚本进行了扩展,并在标题中添加了UnityEditor

[CustomEditor(typeof(MyScript))]
public class MyEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        MyScript tool = (MyScript) target;

        tool.A = GUILayout.Toggle(tool.A, "Flag");

        if(tool.A)
        {
            tool.B= EditorGUILayout.Toggle(tool.B, "Flag");
        }
    }
}

但实际上什么都没有改变。我做错了什么?

1个回答

5
首先,你的类定义是错误的。如果要将其附加到游戏对象上,则需要[Serializable]或该类应继承自MonoBehaviour。无论哪种情况,请删除()
[Serializable]
public class MyScript
{
   public bool A;
   public bool B;
}

或者

public class MyScript : MonoBehaviour
{
   public bool A;
   public bool B;
}

请注意,自定义编辑器仅适用于继承自MonoBehaviourScriptableObject的类。在其他情况下,您需要实现自定义属性绘制器

请尽量不要直接更改target。您要处理很多东西,如标记为脏、撤消/重做等...

而是始终通过SerializedProperty进行操作。

还要注意,base.OnInspectorGUI();将绘制默认的检查器。


假设MyScript是一个MonoBehaviour类。

[CustomEditor(typeof(MyScript))]
public class MyEditor : Editor
{
    SerializedProperty a;
    SerializedProperty b;

    // is called once when according object gains focus in the hierachy
    private void OnEnable()
    {
        // link serialized properties to the target's fields
        // more efficient doing this only once
        a = serializedObject.FindProperty("A");
        b = serializedObject.FindProperty("B");
    }

    public override void OnInspectorGUI()
    {
        // fetch current values from the real instance into the serialized "clone"
        serializedObject.Update();

        // Draw field for A
        EditorGUILayout.PropertyField(a);

        if(a.boolValue)
        {
            // Draw field for B
            EditorGUILayout.PropertyField(b);
        }

        // write back serialized values to the real instance
        // automatically handles all marking dirty and undo/redo
        serializedObject.ApplyModifiedProperties();
    }
}

如果 MyScript 实际上不是一个 MonoBehaviour,那么可以将其作为 PropertyDrawer 使用。这两者的原理基本相似,只是在使用字段时必须始终使用带有位置参数 RectEditorGUI 版本:

[CustomPropertyDrawer(typeof(MyScript), true)]
public class MyEditor : PropertyDrawer
{
    private bool isUnFolded;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // draw folder for the entire class
        isUnFolded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), isUnFolded, label);
        // go to the next line
        position.y += EditorGUIUtility.singleLineHeight;

        // only draw the rest if unfolded
        if (isUnFolded)
        {
            // draw fields indented
            EditorGUI.indentLevel++;

            // similar to before get the according serialized properties for the fields
            var a = property.FindPropertyRelative("A");
            var b = property.FindPropertyRelative("B");

            // Draw A field
            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), a);
            position.y += EditorGUIUtility.singleLineHeight;

            if (a.boolValue)
            {
                // Draw B field
                EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), b);
            }

            // reset indentation
            EditorGUI.indentLevel--;
        }
    }

    // IMPORTANT you have to implement this since your new property is
    // higher then 1 single line
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        // default is 1 single line
        var height = 1;
        // if unfolded at least 1 line more, if a is true 2 lines more
        if(isUnFolded) height += (property.FindPropertyRelative("A").boolValue ? 2 : 1);

        return height * EditorGUIUtility.singleLineHeight;
    }
}

有些错误是值得犯的。 我应该在第一时间就将其写成MonoBehaviour(更新了问题),因为这是我的类(笔误),但那样你就不会将你的答案扩展到PropertyDrawer。所以现在我要再次感谢你。 :) - likuku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接