如何使用 onAddCallBack 将最新添加到可重新排序列表中的项目设置为默认值


using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
[CustomEditor(typeof(ConversationTrigger))]
public class ConversationTriggerEditor : Editor
{
    private Vector2 scrollPos;
    private SerializedProperty conversations;
    private ConversationTrigger conversationTrigger;
    private ReorderableList conversationList;
    private void OnEnable()
    {
        conversations = serializedObject.FindProperty("conversations");
        conversationTrigger = (ConversationTrigger)target;        
        conversationList = new ReorderableList(serializedObject, conversations)
        {
            displayAdd = true,
            displayRemove = true,
            draggable = true,
            onAddCallback = addcallback =>
            {
                addcallback.list[addcallback.list.Count] = default;
            },
            drawElementCallback = (rect, index, isActive, isSelected) =>
            {
                var element = conversations.GetArrayElementAtIndex(index);
                var name = element.FindPropertyRelative("Name");
                // do this for all properties
                var position = EditorGUI.PrefixLabel(rect, new GUIContent(name.stringValue));
                EditorGUI.PropertyField(position, name);
            },
            elementHeight = EditorGUIUtility.singleLineHeight
        };
    }
    public override void OnInspectorGUI()
    {
        // Load the current values from the real component into the serialized copy
        serializedObject.Update();
        EditorGUILayout.LabelField("Conversations", EditorStyles.boldLabel);
        var newSize = EditorGUILayout.IntField(conversations.arraySize);
        conversations.arraySize = Mathf.Max(0, newSize);
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(250));
        GUILayout.Space(10);
        conversationList.DoLayoutList();
        EditorGUILayout.EndScrollView();
        if (GUILayout.Button("Add new conversation"))
        {
            conversations.arraySize++;
        }
        GUILayout.Space(10);
        if (conversations.arraySize != 0)
        {
            if (GUILayout.Button("Remove conversation"))
            {
                if (conversations.arraySize > 0) conversations.arraySize--;
            }
        }
        GUILayout.Space(100);
        if (GUILayout.Button("Save Conversations"))
        {
            conversationTrigger.SaveConversations();
        }
        GUILayout.Space(10);
        if (GUILayout.Button("Load Conversations"))
        {
            Undo.RecordObject(conversationTrigger, "Loaded conversations from JSON");
            conversationTrigger.LoadConversations();
        }
        serializedObject.ApplyModifiedProperties();
    }
}

主要有两个问题:

首先:属性 displayAdd 和 displayRemove 必须为 true 才能使用 onAddCallback。也许只有显示添加必须是真的。如果它是假的,我使用了一个断点,它永远不会到达行:

addcallback.list[addcallback.list.Count] = default;

如果两者都为真,它将到达这一行,但想法是将最新添加的项目设置为默认空,没有名称,因为现在添加新对话时它会复制最后一项。相反,我想添加一个新的空项目。

第二:即使到达那里,这条线也不起作用,它什么也没做,它不断添加重复的项目:

addcallback.list[addcallback.list.Count] = default;

当显示添加和显示删除都为假时,如何使用onAdd回调?我希望它们是假的,因为我使用两个按钮伪造添加/删除。但如果它们是假的,我就不能使用 onAddCallback

以及如何在添加新项目时进行设置和制作,如果没有名称,它将为空?

一旦你覆盖了onAddCallback你必须主动增加arraySize,如果你不覆盖它,这是默认行为。

                // you don't have to go through the list property
                // you could ofcourse but anyway you already know which list
                // you want to change
onAddCallback = list =>
{
    // first add one element
    conversations.arraySize++;
    // then get that element
    var newIndex = conversations.arraySize - 1;
    var newElement = conversations.GetArrayElementAtIndex(newIndex);
    // now reset all properties like
    var name = newElement.FindPropertyRelative("Name");
    name.stringValue = "";
    // ...
},

请注意,这不会与您的

GUILayout.Button("Add new conversation")

也不通过

EditorGUILayout.IntField(conversations.arraySize);

首先,您可以简单地做同样的事情,例如

if(GUILayout.Button("Add new conversation"))
{
    // first add one element
    conversations.arraySize++;
    // then get that element
    var newIndex = conversations.arraySize - 1;
    var newElement = conversations.GetArrayElementAtIndex(newIndex);
    // now reset all properties like
    var name = newElement.FindPropertyRelative("Name");
    name.stringValue = "";
}

第二,您必须检查是否删除了元素或添加了多少元素:

EditorGUI.BeginChangeCheck();
{
    var newSize = EditorGUILayout.IntField(conversations.arraySize);
}
if(EditorGUI.EndChangeCheck())
{
    if(newSize > conversations.arraySize)
    {
        // elements have to be added -> how many?
        var toAdd = newSize - conversations.arraySize - 1;
        // why -1 ? -> We add the first element and set its values to default
        // now if we simply increase the arraySize for the rest of the elements
        // they will be all a copy of the first -> all defaults ;)
        // first add one element
        conversations.arraySize++;
        // then get that element
        var newIndex = conversations.arraySize - 1;
        var newElement = conversations.GetArrayElementAtIndex(newIndex);
        // now reset all properties like
        var name = newElement.FindPropertyRelative("Name");
        name.stringValue = "";
        // now for the rest simply increase arraySize
        conversations.arraySize += toAdd;
    }
    else
    {
        // for removing just make sure the arraySize is not under 0
        conversations.arraySize = Mathf.Max(newSize, 0);
    }
}

不幸的是,这就是Unity EditorScripting的事情......直到现在,它有点糟糕并且变得非常复杂,只是为了获得你想要的布局;)

但是他们正在努力,新的alpha和beta版本2019.2和2019.3已经提供了新检查器和Unity GUI的一些预览,并且可能很快就会有一种更简单的方法来进行编辑器设计... ;)

最新更新