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

Unity嵌套列表自定义编辑器开发:动态调整子列表及弹窗问题

Fixing Nested List Issues in Unity Custom Editor

Got it, let's tackle these two problems one by one—they’re both rooted in not tying state (like sublist expansion and popup selection) to individual sublist items, instead relying on global variables in your editor script. Here’s how to fix this properly:

1. First: Define a Serializable Nested Data Structure

You need each sublist item to track its own unique state. Create a serializable class for your nested items that includes:

  • The sublist content itself
  • A boolean to control if the sublist is expanded (this controls its visible "size" in the editor)
  • An integer to store the selected popup index for that specific item
using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class NestedListItem
{
    // Your sublist content (customize this to match your data needs)
    public List<string> subItems = new List<string>();
    // Tracks if this item's sublist is expanded/collapsed (controls visible size)
    public bool isExpanded = false;
    // Stores the selected popup index for THIS item alone
    public int selectedOptionIndex = 0;
    // Popup options (can be static or dynamic—adjust as needed for your use case)
    public string[] popupOptions = new string[] { "Option A", "Option B", "Option C" };
}

// Your main MonoBehaviour that holds the top-level list
public class NestedListHolder : MonoBehaviour
{
    public List<NestedListItem> topLevelList = new List<NestedListItem>();
}

2. Build the Custom Editor with Per-Item State

Now, in your editor script, use SerializedProperty to access each item’s individual state. This ensures every sublist’s expansion and popup selection are fully independent.

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(NestedListHolder))]
public class NestedListEditor : Editor
{
    private SerializedProperty topLevelList;

    private void OnEnable()
    {
        // Get the serialized property for the top-level list
        topLevelList = serializedObject.FindProperty("topLevelList");
    }

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

        // Draw the top-level list header with default add/remove controls
        EditorGUILayout.PropertyField(topLevelList, true);

        // Iterate over each top-level item to customize the sublist UI
        for (int i = 0; i < topLevelList.arraySize; i++)
        {
            SerializedProperty currentItem = topLevelList.GetArrayElementAtIndex(i);
            
            // Get references to the item's unique state properties
            SerializedProperty isExpanded = currentItem.FindPropertyRelative("isExpanded");
            SerializedProperty selectedOption = currentItem.FindPropertyRelative("selectedOptionIndex");
            SerializedProperty popupOptions = currentItem.FindPropertyRelative("popupOptions");
            SerializedProperty subItems = currentItem.FindPropertyRelative("subItems");

            // Foldout to control sublist expansion (fixes the size sync issue)
            isExpanded.boolValue = EditorGUILayout.Foldout(isExpanded.boolValue, $"List Item {i+1}");

            if (isExpanded.boolValue)
            {
                // Popup bound to THIS item's selected index (fixes global selection issue)
                selectedOption.intValue = EditorGUILayout.Popup(
                    "Select Option", 
                    selectedOption.intValue, 
                    popupOptions.stringValue
                );

                // Draw the sublist with its own nested add/remove controls
                EditorGUI.indentLevel++;
                EditorGUILayout.PropertyField(subItems, true);
                EditorGUI.indentLevel--;
            }

            EditorGUILayout.Space();
        }

        serializedObject.ApplyModifiedProperties();
    }
}

Key Fixes Explained

  • Independent Sublist Sizes: By storing isExpanded on each NestedListItem, we control visibility per-item—no more global expansion state affecting all sublists at once.
  • Per-Item Popup Selection: The selectedOptionIndex is tied directly to each individual item, so selecting an option in one sublist won’t overwrite selections in others. The Popup control uses this item-specific index instead of a global variable.

Extra Tips

  • If your popup options need to be dynamic (e.g., loaded from a ScriptableObject or resource), move the options array to a static field in your editor script or populate it in OnEnable()—just make sure each item’s selection index remains stored per-item.
  • For more complex sublist items, you can create a custom PropertyDrawer for NestedListItem to clean up the editor code and reuse the UI logic elsewhere.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:55:12