簡體   English   中英

在 Unity Inspector 中查看數組的枚舉索引

[英]See Enumerated Indices of Array in Unity Inspector

簡而言之,我有由枚舉中的索引引用的數組。 但是,在 Unity 的檢查器窗口中,它僅顯示“元素 0、元素 1 等”。 我希望列表顯示我的枚舉的索引值。 除非向 Unity 添加新功能,否則我想這需要一個特殊的編輯器腳本,但似乎游戲代碼甚至無法與編輯器代碼交互。 那么我該怎么做呢? 提前致謝!

所以如果我有這個:

public enum ObjectList
{
    Car,
    Sword,
    Friends,
    Depression,
    NumObjects
}

[Somehow declare to use my ObjectList Enum]
public bool [] hasItem = new bool[(int)ObjectList.NumObjects];

理想情況下,檢查員現在會顯示:

Has Item
    Size        4
    Car         []
    Sword       []
    Friends     []
    Depression  []

代替:

Has Item
    Size        4
    Element 0   []
    Element 1   []
    Element 2   []
    Element 3   []

編輯:作為 Int Array 的附加示例(不僅僅是 bool)

Num Item
    Size        4
    Car         0
    Sword       10
    Friends     0
    Depression  50

不完全是你如何描述它,但已經存在非常相似的東西:

枚舉標志


我稍微重寫了腳本:

將此腳本放置在Assets任何位置,例如Assets/Plugins/EnumFlag

EnumFlagAttribute.cs

using UnityEngine;

public class EnumFlagAttribute : PropertyAttribute
{
    public enum FlagLayout
    {
        Dropdown,
        List
    }

    public FlagLayout _layout = FlagLayout.Dropdown;

    public EnumFlagAttribute() { }

    public EnumFlagAttribute(FlagLayout layout)
    {
        _layout = layout;
    }
}

並將此編輯器腳本復制到名為Editor的文件夾中(它放在Assets哪個位置無關緊要,只有它的名稱才重要),例如Assets/Plugins/EnumFlag/Editor → Unity 會自動從最終結果中排除放置在名為Editor文件夾中的所有腳本構建因此不會由於UnityEditor命名空間而產生構建錯誤。

EnumFlagDrawer.cs

using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        if (property.propertyType == SerializedPropertyType.Enum)
        {
            switch (((EnumFlagAttribute)attribute)._layout)
            {
                case EnumFlagAttribute.FlagLayout.Dropdown:
                    property.intValue = EditorGUI.MaskField(position, label, property.intValue, property.enumNames);
                    break;

                case EnumFlagAttribute.FlagLayout.List:
                    var buttonsIntValue = 0;
                    var enumLength = property.enumNames.Length;
                    var flagSet = new bool[enumLength];

                    EditorGUI.LabelField(new Rect(position.x, position.y, EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight), label);
                    EditorGUI.indentLevel++;


                    var posX = position.x;
                    EditorGUI.BeginChangeCheck();
                    {
                        for (var i = 0; i < enumLength; i++)
                        {
                            position.y += EditorGUIUtility.singleLineHeight;

                            // Check if the flag is currently set
                            if (((EnumFlagAttribute.FlagLayout)property.intValue).HasFlag((EnumFlagAttribute.FlagLayout)(1 << i)))
                            {
                                flagSet[i] = true;
                            }

                            EditorGUI.PrefixLabel(new Rect(posX, position.y, EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight), new GUIContent(property.enumNames[i]));

                            var toogePosition = new Rect(posX + EditorGUIUtility.labelWidth, position.y, EditorGUIUtility.currentViewWidth - EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight);
                            flagSet[i] = GUI.Toggle(toogePosition, flagSet[i], property.enumNames[i]);


                            if (flagSet[i])
                            {
                                buttonsIntValue += 1 << i;
                            }
                        }
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        property.intValue = buttonsIntValue;
                    }


                    EditorGUI.indentLevel--;

                    break;
            }
        }
        else
        {
            var color = GUI.color;
            GUI.color = new Color(1f, 0.2f, 0.2f);
            EditorGUI.LabelField(new Rect(position.x, position.y, EditorGUIUtility.labelWidth, position.height), label);
            position.x += EditorGUIUtility.labelWidth;
            EditorGUI.HelpBox(new Rect(position.x, position.y, position.width - EditorGUIUtility.labelWidth, position.height), "Use [EnumFlags] only with an enum!", MessageType.Error);
            GUI.color = color;
        }

        EditorGUI.EndProperty();
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        if (((EnumFlagAttribute)attribute)._layout == EnumFlagAttribute.FlagLayout.Dropdown)
        {
            return EditorGUIUtility.singleLineHeight;
        }


        return (property.enumNames.Length + 1) * EditorGUIUtility.singleLineHeight;
    }
}

然后在你的代碼中你會像這樣使用它

[System.Flags]
public enum ObjectList
{
    Car = 1 << 0,
    Sword = 1 << 1,
    Friends = 1 << 2,
    Depression = 1 << 3 
}

[EnumFlag]
public ObjectList hasItem;

這會向您的 Inspector 添加一個枚舉字段,您可以在其中(取消)檢查多個值而不是一個。

請注意,很多關於此的教程手動向枚舉添加NoneAll值,但這是不必要的,因為 Unity Inspector 會自動添加它們。

在此處輸入圖片說明

或者您可以使用我剛剛添加的列表布局以適合您想要顯示的內容

[EnumFlag(EnumFlagAttribute.FlagLayout.List)]
public ObjectList hasItem;

這將枚舉字段添加為帶有相應標簽的切換列表

在此處輸入圖片說明


在腳本中設置和讀取這些按位標志的工作方式與通常的 enum 或 bool 列表略有不同:

使用按位 OR 設置多個值| 操作員:

hasItem = ObjectList.Car | ObjectList.Sword;

// or to add a value later
hasItem |= ObjectList.Friends;

使用按位 NOT ~和 AND &運算符刪除某個標志

hasItem &= ~ObjectList.Car;

並使用按位 XOR ^運算符切換(反轉)某個標志:

hasItem ^= ObjectList.Car;

而不是檢查是否使用HasFlag設置了某些標志

bool hasCar = hasItem.HasFlag(ObjectList.Car);
bool hasCarOrSword = hasItem.HasFlag(ObjectList.Car | ObjectList.Sword);
bool hasCarAndSword = hasItem.HasFlag(ObjectList.Car & ObjectList.Sword);

更新

正如您現在添加的那樣,您實際上更希望擁有一個int[] 這作為帶有 PropertyDrawer 的 Attribute 非常復雜,因為事實上,propertydrawer 用於該列表/數組中的每個元素而不是整個列表!

但是,您可以將列表包裝在一個類中,並為此創建一個 PropertyDrawer:

EnumIntArray.cs

using System;

[Serializable]
public class EnumIntArray
{
    public string[] Names;
    public int[] Values;

    public EnumIntArray(Type enumType)
    {
        Names = Enum.GetNames(enumType);
        Values = new int[Names.Length];
    }
}

EnumIntArrayDrawer.cs

using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(EnumIntArray), false)]
public class EnumIntArrayDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        EditorGUI.LabelField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), label);

        var values = property.FindPropertyRelative("Values");
        var names = property.FindPropertyRelative("Names");

        EditorGUI.indentLevel++;

        for (var i = 0; i < values.arraySize; i++)
        {
            var name = names.GetArrayElementAtIndex(i);
            var value = values.GetArrayElementAtIndex(i);

            position.y += EditorGUIUtility.singleLineHeight;

            var indentedRect = EditorGUI.IndentedRect(position);

            EditorGUI.LabelField(new Rect(position.x, position.y, EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight), name.stringValue);
            value.intValue = EditorGUI.IntField(new Rect(position.x + EditorGUIUtility.labelWidth - indentedRect.x / 2, position.y, EditorGUIUtility.currentViewWidth - EditorGUIUtility.labelWidth - indentedRect.x, EditorGUIUtility.singleLineHeight), value.intValue);
        }

        EditorGUI.indentLevel--;

        EditorGUI.EndProperty();
    }


    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        var values = property.FindPropertyRelative("Values");

        return (values.arraySize + 1) * EditorGUIUtility.singleLineHeight;
    }
}

然后在您的腳本中使用它,例如

public EnumIntArray hasItems = new EnumIntArray(typeof(ObjectList));

在此處輸入圖片說明

並用於訪問值

var carAmount = hasItems.Values[(int)ObjectList.Car];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM