1

我想为 Unity 创建一个自定义编辑器,其中包含列表中的列表,并允许动态编辑大小并在第二个列表中使用弹出窗口。

这是我想要的几个例子:

示例 1

示例 2

问题是我不能改变第二个列表的大小,因为它改变了第二个列表中所有元素的大小,所以我不能为列表的每个元素设置不同的大小。

我对弹出窗口也有同样的问题,选择的项目对于所有弹出窗口都是相同的(如您在第二张图片中所见)。

如何保存所选每个项目的每个维度或弹出窗口而不更改其他项目?

这是我的代码:

ScriptableObject 类

public class MyClass : ScriptableObject {

public class MyInsideClass
{
    public List<string> data;

    public MyInsideClass()
    {
        data = new List<string>();
    }
}

public List<MyInsideClass> allData;
}

自定义编辑器(数据库只有弹出列表名称)

[CustomEditor(typeof(MyClass))]
public class TempEdior : Editor
{
    int numberOfCombinations = 0;
    int numberOfDataForCombination = 0;
    int selected = 0;

    public override void OnInspectorGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Label("Number of combinations:");
        numberOfCombinations =         EditorGUILayout.IntField(numberOfCombinations);
        GUILayout.EndHorizontal();

        for (int i = 0; i < numberOfCombinations; i++)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label("Combination " + (i + 1) + " - number of data:");
            numberOfDataForCombination =     EditorGUILayout.IntField(numberOfDataForCombination);
            GUILayout.EndHorizontal();

            for (int j = 0; j < numberOfDataForCombination; j++)
            {
                Rect rect = EditorGUILayout.GetControlRect();
                selected = EditorGUI.Popup(new Rect(rect.x + 63, rect.y, 100, EditorGUIUtility.singleLineHeight), selected,     Database.Instance.slotTypes.ToArray());
            }
        }
    }
}
4

1 回答 1

1

IMO您以错误的方式处理此问题。永远写检查器代码很容易忘乎所以,以错综复杂的方式破坏 Unity 的范式,几乎没有什么好处。尽可能多地依赖 SerializedProperties,因为它将处理撤消、多重编辑等。

基本上你想要的只是使用弹出窗口编辑一个字符串,对吗?然后只需为此使用 PropertyDrawer,其余的就让 Unity 的数组检查器发挥它的魔力: 在此处输入图像描述

using System;
using UnityEditor;
using UnityEngine;

public class TestArrayOfArray : MonoBehaviour
{
    [Serializable]
    public struct ComboItem
    {
        public string value;
    }

    [Serializable]
    public struct Combo
    {
        public ComboItem[] items;
    }

    public Combo[] combos;
}

[CustomPropertyDrawer(typeof(TestArrayOfArray.ComboItem))]
public class ComboItemDrawer : PropertyDrawer
{
    static readonly string[] comboItemDatabase = { "Bla", "Bli", "Blu" };
    static readonly GUIContent[] comboItemDatabaseGUIContents = Array.ConvertAll(comboItemDatabase, i => new GUIContent(i));

    public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
    {
        property = property.FindPropertyRelative("value");

        EditorGUI.BeginChangeCheck();
        int selectedIndex = Array.IndexOf(comboItemDatabase, property.stringValue);
        selectedIndex = EditorGUI.Popup(position, label, selectedIndex, comboItemDatabaseGUIContents);
        if (EditorGUI.EndChangeCheck())
        {
            property.stringValue = comboItemDatabase[selectedIndex];
        }
    }
}

这是非常粗糙的,单个文件中的运行时+检查器代码,硬编码为静态数组的假“数据库”,在多重编辑等情况下不处理混合值等,但它应该让你开始。

--

一般建议:如果可以的话,优先使用数组而不是列表,例如,在这种情况下,组合是静态序列化数据,您永远不会在运行时调整大小,因此数组更有效。

尽可能的内联字段声明以提高可读性(例如public List<string> data = new List<string>();很好)。

不要初始化序列化的数组/列表,因为它们的默认值将被反序列化覆盖,导致分配浪费。

于 2018-03-02T16:28:40.850 回答