我正在尝试在 Inspector 中使用 ReorderableList 但效果不佳.我应该如何处理它? [英] I'm trying to use ReorderableList in Inspector but it's not working good. How should I work with it?

查看:62
本文介绍了我正在尝试在 Inspector 中使用 ReorderableList 但效果不佳.我应该如何处理它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑器脚本.

问题是我在 ReorderableList 中看到了从索引 0 到 17 的项目,然后还有更多项目,但它们都丢失了.当试图删除它们时,它们不会被删除.

The problem is that I see in the ReorderableList items from index 0 to 17 and then many more item but they are all Missing. And when trying to delete them they are not deleted.

我想使用 MenuItem 和 Selection 添加新项目.我想为每个项目添加更多属性,例如 Undo,以便 Undo 将从列表中的游戏对象中删除 BoxCollider 和脚本 Whilefun.FPEKit.FPEInteractablePickupScript

I want to add new items using the MenuItem and the Selection. I want to add more propertied to per item like Undo so Undo will remove from the gameobject in the list the BoxCollider and the script Whilefun.FPEKit.FPEInteractablePickupScript

这个想法是,当我在层次结构中选择一个游戏对象时,如果我正在右键单击并选择仅生成为拾取项目,然后添加 BoxCollider 和脚本 Whilefun.FPEKit.FPEInteractablePickupScript,然后才将该选定的游戏对象添加为项目到 ReorderableList,如果我在 ReorderableList 中的一个项目上创建,用鼠标右键单击并选择撤消,然后首先删除 Box Collider 和 Whilefun.FPEKit.FPEInteractablePickupScript,然后从 ReorderableList 中删除游戏对象项目.

The idea is that when I select an gameobject in the hierarchy if I'm doing right click and select Generate as Pickup Item only then add the BoxCollider and the script Whilefun.FPEKit.FPEInteractablePickupScript and only then add that selected gameobject as item to the ReorderableList and if I make in the ReorderableList on one of them items right click with the mouse and select undo then first remove the Box Collider and the Whilefun.FPEKit.FPEInteractablePickupScript and then remove the gameobject item from the ReorderableList.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

[CustomEditor(typeof(PickupObjects))]
public class PickupObjectsEditor : Editor
{
    private static List<GameObject> pickeditems = new List<GameObject>();
    private static bool picked = false;

    [MenuItem("GameObject/Generate as Pickup Item", false, 30)]
    public static void GeneratePickupItems()
    {
        if (Selection.gameObjects.Length > 0)
        {
            pickeditems.Clear();

            for (int i = 0; i < Selection.gameObjects.Length; i++)
            {
                if (Selection.gameObjects[i].GetComponent<Whilefun.FPEKit.FPEInteractablePickupScript>() == null)
                {
                    Selection.gameObjects[i].AddComponent<BoxCollider>();
                    Selection.gameObjects[i].AddComponent<Whilefun.FPEKit.FPEInteractablePickupScript>();
                }

                Selection.gameObjects[i].layer = 9;
                Selection.gameObjects[i].tag = "Pickup Item";

                pickeditems.Add(Selection.gameObjects[i]);
            }

            picked = true;
        }
    }

    PickupObjects _target;

    private ReorderableList _myList;

    public void OnEnable()
    {
        _target = (PickupObjects)target;

        _myList = new ReorderableList(serializedObject, serializedObject.FindProperty("pickUpObjects"), true, true, true, true);

        _myList.drawHeaderCallback = rect =>
        {
            EditorGUI.LabelField(rect, "My Reorderable List", EditorStyles.boldLabel);
        };

        _myList.drawElementCallback =
            (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                var element = _myList.serializedProperty.GetArrayElementAtIndex(index);
                EditorGUI.ObjectField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
            };
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        _myList.DoLayoutList();
        serializedObject.ApplyModifiedProperties();
    }
}

和单声道脚本

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class PickupObjects : MonoBehaviour
{
    public List<GameObject> pickUpObjects = new List<GameObject>();
}

这是 ReorderableList 的屏幕截图.一团糟:

This is a screenshot of the ReorderableList. All messed :

推荐答案

正如前面提到的 Missing 实际上意味着之前设置了引用但相应的对象被删除/销毁.

As mentioned Missing actually means the reference was set before but according object was deleted/destroyed.

由于您执行了 pickedItems.Clear(),该列表不应包含实际选择的更多内容.

Since you do pickedItems.Clear() that list should never contain more then the selection actually.

为了添加一个额外的按钮,你可以简单地扩展你的 drawElement 回调,例如

In order to add an additional button you can simply extend your drawElement callback like e.g.

public void OnEnable()
{
    //_target = (PickupObjects)target;

    _myList = new ReorderableList(serializedObject, serializedObject.FindProperty("pickUpObjects"))
    {
        draggable = true,

        // I wouldn't show the Add button
        // since you have your own add functionality
        displayAdd = false,

        // I wouldn't show the remove button either
        // since you want a custom button for removing items
        displayRemove = false,

        drawHeaderCallback = rect => EditorGUI.LabelField(rect, "My Reorderable List", EditorStyles.boldLabel),

        drawElementCallback = (rect, index, isActive, isFocused) =>
        {
            if (index > _myList.serializedProperty.arraySize -1 ) return;
            var element = _myList.serializedProperty.GetArrayElementAtIndex(index);

            // In order to prevent errors when directly changing the reference
            // I would forbid the direct editing of thisfield
            EditorGUI.BeginDisabledGroup(true);
            {
                EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width - 20, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
            }
            EditorGUI.EndDisabledGroup();

            if (GUI.Button(new Rect(rect.x + rect.width - 20, rect.y, 20, EditorGUIUtility.singleLineHeight), "X"))
            {
                var obj = (GameObject) element.objectReferenceValue;

                if (obj)
                {
                    var boxCollider = obj.GetComponent<BoxCollider>();
                    if (boxCollider) DestroyImmediate(boxCollider);

                    var picker = obj.GetComponent<Whilefun.FPEKit.FPEInteractablePickupScript>();
                    if(picker) DestroyImmediate(picker);
                }

                if(_myList.serializedProperty.GetArrayElementAtIndex(index).objectReferenceValue != null)
                    _myList.serializedProperty.DeleteArrayElementAtIndex(index);
                _myList.serializedProperty.DeleteArrayElementAtIndex(index);

                serializedObject.ApplyModifiedProperties();
            }
        }
    };
}

另外我刚刚注意到您删除了您实际添加对象到列表的整个部分!

Also I just noted that you removed the entire part where you actually ADD objects to the list!

public override void OnInspectorGUI()
{
    var list = serializedObject.FindProperty("pickUpObjects");

    serializedObject.Update();

    if(picked)
    {
        picked = false;
        foreach(var newEntry in pickeditems)
        {
            // check if already contains this item
            bool alreadyPresent = false;
            for(var i=0; i < list.arraySize; i++)
            {
                if((GameObject)list.GetArrayElementAtIndex(i).objectReferenceValue == newEntry)
                {
                    alreadyPresent = true;
                    break; 
                }
            }

            if(alreadyPresent) continue;

            // Otherwise add via the serializedProperty
            list.arraySize++;
            list.GetArrayElementAtIndex(list.arraySize - 1).objectReferenceValue = newEntry;
        }
        pickeditems.Clear();
    }

    _myList.DoLayoutList();
    serializedObject.ApplyModifiedProperties();
}

<小时>

因为我没有你的组件,所以我只用 BoxCollider 来做演示;)

如您所见,将对象添加到列表后,它们都具有 BoxCollider,删除它们后,它们不再拥有.

As you can see after adding the objects to the list they all hace the BoxCollider, after removing them they do not have it anymore.

这篇关于我正在尝试在 Inspector 中使用 ReorderableList 但效果不佳.我应该如何处理它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆