Unity - 如何创建自定义编辑器以动态更改具有自定义大小的其他列表中列表的大小?

时间:2018-03-01 20:23:24

标签: c# unity3d unityscript unity-editor

我想为Unity创建一个自定义编辑器,列表中有一个列表,允许动态编辑大小,并在第二个列表中使用Popup。

以下是我想要的几个例子:

Example 1

Example 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());
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

IMO你以错误的方式接近这个。很容易被永远地编写检查员代码带走,以复杂的方式打破Unity的范例,几乎没有任何好处。尽可能依靠SerializedProperties,因为它将处理撤消,多编辑等。

基本上你想要的只是使用弹出窗口编辑一个字符串,对吧?然后只需使用PropertyDrawer,剩下的就是让Unity的阵列检查器发挥其魔力: enter image description here

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];
        }
    }
}

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

-

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

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

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