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
相关产品推荐
相关产品推荐

