我正在尝试为PlayerInventory类创建自定义检查器。 PlayerInventory类由项目列表(ScriptableObjects)以及每个项目的数量组成,如下所示:

public class Item : ScriptableObject
{
   public string description;
   public Sprite picture;
}

public class InventoryItem : ScriptableObject
{
   // A reference to the Item object that contains the item's description,
   // picture, stats, etc.
   public Item item;

   // The quantity of this item that the player has in his inventory
   public int quantity;
}

[CreateAssetMenu(menuName = "Player/Player Inventory")]
public class PlayerInventory : ScriptableObject
{
   // The list of each distinct item that the player has in his inventory,
   // along with the quantity of each item
   public List<InventoryItem> items;
}


我创建了PlayerInventory的实例作为游戏资产。默认情况下,检查器显示InventoryItem的列表。但是,我要的是使Inspector显示每个InventoryItem元素,并为它选择一个Item字段,一个用于输入数量的字段和一个“删除”按钮。

这是我要实现的视觉示例,以及下面的当前代码。该屏幕快照的问题在于Unity使我为每个元素选择一个InventoryItem对象。我希望能够为每个元素选择一个Item对象。我遇到的第二个问题是我不知道如何将EditorGUILayout.TextField设置为InventoryItem.quantity属性,因为我不知道如何将SerializedProperty转换为InventoryItem对象。

c# - Unity自定义检查器,允许选择的子对象-LMLPHP

[CustomEditor(typeof(PlayerInventory))]
public class PlayerInventoryEditor : Editor
{
   public override void OnInspectorGUI()
   {
       this.serializedObject.Update();

       SerializedProperty items = this.serializedObject.FindProperty("items");
       for (int i = 0; i < items.arraySize; i++)
       {
           EditorGUILayout.BeginHorizontal();
           EditorGUILayout.LabelField("Item", GUILayout.Width(50));

           // I don't know how to make this line reference the child "item"
           // field of the current InventoryItem
           EditorGUILayout.PropertyField(items.GetArrayElementAtIndex(i), GUIContent.none, GUILayout.Width(170));

           EditorGUILayout.LabelField("    Quantity", GUILayout.Width(80));

           // I don't know how to set the text field to the "quantity" field
           // of the current InventoryItem
           EditorGUILayout.TextField("0", GUILayout.Width(50));

           EditorGUILayout.LabelField("", GUILayout.Width(20));
           GUILayout.Button("Delete Item");
           EditorGUILayout.EndHorizontal();
       }

       GUILayout.Button("Add Item");
   }
}

最佳答案

类必须可序列化才能出现在检查器中。见Serializable

编辑。在下面的评论中进行进一步的讨论之后,以下是完整的摘要;

标有Serializable的标准类;

[System.Serializable]
public class InventoryItem
{
    public Item item;
    public int quantity;
}


使用PlayerInventoryEditor;

public override void OnInspectorGUI ()
{
    this.serializedObject.Update();

    SerializedProperty items = this.serializedObject.FindProperty("items");

    for (int i = 0; i < items.arraySize; i++)
    {
        SerializedProperty item = items.GetArrayElementAtIndex(i);

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Item", GUILayout.Width(50));
        EditorGUILayout.PropertyField(item.FindPropertyRelative("item"), GUIContent.none, GUILayout.Width(170));
        EditorGUILayout.LabelField("    Quantity", GUILayout.Width(80));
        EditorGUILayout.IntField(item.FindPropertyRelative("quantity").intValue, GUILayout.Width(50));

        EditorGUILayout.LabelField("", GUILayout.Width(20));
        GUILayout.Button("Delete Item");
        EditorGUILayout.EndHorizontal();
    }

    GUILayout.Button("Add Item");
}

10-01 23:11