【问题标题】:Unity - How to create a Custom Editor for dynamically change size of a list inside an other list with custom size?Unity - 如何创建自定义编辑器以动态更改具有自定义大小的其他列表中的列表大小?
【发布时间】:2018-03-01 20:23:24
【问题描述】:

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

这里有几个我想要的例子:

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

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

如何在不更改其他项目的情况下保存每个选定项目的每个维度或弹出窗口?

这是我的代码:

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

【问题讨论】:

  • 看需求 哎呀。我根本不想编写那个自定义检查器脚本。但是要记住的重要一点:检查器显示的任何数据都必须在您编辑的对象中。您不能在检查器脚本本身中“存储”数据。
  • 是的,我知道我必须编写另一部分代码来将所有数据保存在可编写脚本的对象中,并且创建或删除列表大小的新元素将保存在 scriptablrObject 中。但这只是编辑器使文本更简单的部分,我知道如何存储目标对象或序列化对象。

标签: c# unity3d unity-editor


【解决方案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&lt;string&gt; data = new List&lt;string&gt;(); 很好)。

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

【讨论】:

  • 这是一个非常好的方法,但不起作用,因为我需要使用 ScriptableObjectand 而不是 MonoBehaviour。然而,这个答案帮助我意识到我走错了路,而且 SerializedProperties 更适合我的目的。现在正在使用您的答案的一些提示。谢谢!
  • @Wyrncael 使用 ScriptableObject 不会改变任何事情,这种方法也同样有效......试试吧:)。这就是PropertyDrawers 的美妙之处,它们针对任何地方的任何结构/类,而不是替换给定MonoBehaviourScriptableObject 的整个检查器。
  • 我尝试了你的代码,但只有在我使用 Monobehaviour 而不是 ScriptableObject 时才有效。我不知道为什么我不能在ScriptableObject 中使用CustomPropertyDrawer。也许我犯了更多错误,但是在我的CustomEditor 中使用您的代码而没有特定的CustomPropertyDrawer 并使用SerializedProperties 可以正常工作。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-29
相关资源
最近更新 更多