You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity自定义Editor Window物品列表展开同步问题求助

问题描述

我正在编写一个自定义Editor Window,用于显示Scriptable Database中的物品,大部分功能已正常实现,但存在以下问题:

  • 展开单个物品的Properties列表时,所有物品的该列表会同时展开。
  • 尝试改用ReorderableList后无法正常显示;按建议修改代码后,列表又无法展开子项。

相关代码及截图如下:


自定义Editor Window代码

using UnityEngine;
using UnityEditor;
using Assets.HeroEditor4D.InventorySystem.Scripts;
using Assets.HeroEditor4D.InventorySystem.Scripts.Data;
using Assets.HeroEditor4D.InventorySystem.Scripts.Enums;
using System.Collections.Generic;
using Unity.VisualScripting.ReorderableList;
using Prop = Assets.HeroEditor4D.InventorySystem.Scripts.Data.Property;

public class ItemsLibraryEditor : EditorWindow
{
    private ItemCollection library;
    private ItemType currentType;
    private Color defaultColor;
    private SerializedObject serializedObject;

    private Vector2 scrollPos;

    public List<Prop> _Properties;

    [MenuItem("RPG/Items")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<ItemsLibraryEditor>();
    }

    void OnEnable() {
        serializedObject = new SerializedObject(this);
        _Properties = new List<Prop>();

    }

    void OnGUI()
    {
        defaultColor = GUI.backgroundColor;
        var collection = GameObject.Find("EquipmentManager").GetComponent<EquipmentManager>().ItemCollection;
        if(collection == null)
        {
            if (ItemCollection.Active == null) return;
            library = ItemCollection.Active;
        }
        else 
        {
            library = collection;
        }
        

        EditorGUILayout.BeginHorizontal();
        currentType = (ItemType)EditorGUILayout.EnumPopup(currentType);
        GUI.backgroundColor = Color.green;
        if (GUILayout.Button("Add")){
            ItemParams NewItem = new ItemParams();
            NewItem.Type = currentType;
             library.Items.Add(NewItem);
        }
        GUI.backgroundColor = defaultColor;
        EditorGUILayout.EndHorizontal();
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
        for (int i = library.Items.Count - 1; i >= 0; i--)
        {
            ItemParams item = library.Items[i];
            if (currentType == item.Type)
            {
                DrawCommonProperties(item);
                if (currentType == ItemType.Weapon) DrawWeaponProperties(item);
            }
        }
        EditorGUILayout.EndScrollView();
    }

    private void DrawCommonProperties(ItemParams item)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("ID", GUILayout.Width(20));
        item.Id = EditorGUILayout.TextField(item.Id, GUILayout.Width(180));
        EditorGUILayout.LabelField("Level:", GUILayout.Width(40));
        item.Level = EditorGUILayout.IntField(item.Level, GUILayout.Width(30));
        EditorGUILayout.LabelField("Name:", GUILayout.Width(40));
        item.DisplayName = EditorGUILayout.TextField(item.DisplayName, GUILayout.Width(160));
        EditorGUILayout.LabelField("Rarity: ", GUILayout.Width(40));
        item.Rarity = (ItemRarity)EditorGUILayout.EnumPopup(item.Rarity, GUILayout.Width(120));
        EditorGUILayout.LabelField("Price:", GUILayout.Width(40));
        item.Price = EditorGUILayout.IntField(item.Price, GUILayout.Width(40));
        EditorGUILayout.LabelField("Icon:", GUILayout.Width(40));
        item.IconId = EditorGUILayout.TextField(item.IconId, GUILayout.Width(300));
        EditorGUILayout.LabelField("Sprite:", GUILayout.Width(40));
        item.SpriteId = EditorGUILayout.TextField(item.SpriteId, GUILayout.Width(300));

        GUI.backgroundColor = Color.red;
        if (GUILayout.Button("Remove", GUILayout.Width(120))) library.Items.Remove(item);
        GUI.backgroundColor = defaultColor;
        EditorGUILayout.EndHorizontal();
    }

    private void DrawWeaponProperties(ItemParams item)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Damage Type: ", GUILayout.Width(100));
        item.damageType = (DamageType)EditorGUILayout.EnumPopup(item.damageType, GUILayout.Width(70));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        if (currentType == ItemType.Weapon)
        {
            EditorGUILayout.LabelField("Properties:", GUILayout.Width(100));
            _Properties = new List<Prop>();
            _Properties = item.Properties;
            serializedObject.Update();
            SerializedProperty CustomInspectorVar = serializedObject.FindProperty("_Properties");
            EditorGUILayout.PropertyField(CustomInspectorVar, true);
            if(EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();  
        }
        EditorGUILayout.EndHorizontal();
    }

    private void DrawListItem(Rect rect, int index, bool isActive, bool isFocused)
    {
        Assets.HeroEditor4D.InventorySystem.Scripts.Data.Property property = _Properties[index];
        EditorGUI.LabelField(rect, property.Id.ToString());
    }

}

Property类(精简版)

using System;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Assets.HeroEditor4D.Common.Scripts.Common;
using Assets.HeroEditor4D.InventorySystem.Scripts.Enums;
using UnityEngine;

namespace Assets.HeroEditor4D.InventorySystem.Scripts.Data
{

public enum PropertyId
    {
        Accuracy,
        Ammo,
        Antidote,
        Bandage,
        Blocking,
        BlockingFatigue,
        Capacity,
        ChargeSpeed,
        ChargeTimings,
        Craft,
        CriticalChance,
        CriticalDamage,
        CustomPrice,
        Damage,
        Duration,
        Effect,
        Exp,
        Fatigue,
        Gunpowder,
        HealthRecovery,
        HealthRestore,
        HealthMax,
        Immunity,
        Magazine,
        Materials,
        Mechanism,
        Radius,
        Range,
        Reloading,
        Resistance,
        ShopChance,
        SkillUp,
        Speed,
        StaminaRecovery,
        StaminaRestore,
        StaminaMax,
        Shock,
        Contains,
        DamageBonus,
        Multishot,
        Fragments,
        DropChance,
        ExpBonus,
        GoldBonus
    }
    /// <summary>
    /// Represents key-value pair for storing item params.
    /// </summary>
    [Serializable]
    public class Property
    {
        public PropertyId Id;
        public string Value;
        [HideInInspector][NonSerialized] public int ValueInt;
        [HideInInspector] [NonSerialized] public int Min;
        [HideInInspector] [NonSerialized] public int Max;
        [HideInInspector] [NonSerialized] public int Duration;
        [HideInInspector] [NonSerialized] public bool Percentage;

        public Property()
        {
        }

        public Property(PropertyId id, object value)
        {
            Id = id;
            Value = value.ToString();
        }

}

其他类型定义

using System;
using System.Collections.Generic;
using System.Linq;

using UnityEngine;

    [CreateAssetMenu(fileName = "ItemCollection", menuName = "HeroEditor4D/ItemCollection")]
    public class ItemCollection : ScriptableObject
    {
        [Header("Main")]
        public List<ItemParams> Items;

        [Header("Extra")]
        public Sprite BackgroundBlue;
        public Sprite BackgroundBrown;
        public Sprite BackgroundGreen;
        public Sprite BackgroundGrey;
        public Sprite BackgroundPurple;
        public Sprite BackgroundRed;

        public static ItemCollection Active;

    }
    
    public class ItemParams
    {
        public string Id;
        public int Level = 1;
        public string DisplayName;
        public ItemRarity Rarity;
        public ItemType Type;
        [SerializeField]
        public List<ItemTag> Tags = new List<ItemTag>();
        [SerializeField]
        public List<Property> Properties = new List<Property>();
        public DamageType damageType;
        public int Price;
        public string IconId;
        public string SpriteId;
}

截图

  • 当前效果截图:当前效果
  • 修改后列表无法展开子项截图:无法展开子项

内容的提问来源于stack exchange,提问作者RedWiz666

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:28:06