简体   繁体   English

我可以创建自定义 MonoBehaviour 编辑器来编辑 ScriptableObject 字段中的列表吗?

[英]Can I create a custom MonoBehaviour editor to edit a list from a ScriptableObject field?

I have a custom editor for a MonoBehaviour to display a reorderable list of items.我有一个MonoBehaviour的自定义编辑器来显示可重新排序的项目列表。

public class MyComponent : MonoBehaviour
{
   public MyArrayElement[] myList;
}

public struct MyArrayElement
{
   public string firstField;
   public string secondField;  
}

[CustomEditor(typeof(MyComponent))]
public class MyComponentEditor : Editor
{
    private ReorderableList list;

    private void OnEnable()
    {
        SerializedProperty property = this.serializedObject.FindProperty("myList");
        this.list = new ReorderableList(this.serializedObject, property, true, true, true, true);
        list.drawElementCallback = DrawListItems;
    }

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

    void DrawListItems(Rect rect, int index, bool isActive, bool isFocused)
    {
        EditorGUI.PropertyField(
           new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight), 
           element.FindPropertyRelative("firstField"), 
           GUIContent.none);

        EditorGUI.PropertyField(
           new Rect(rect.x + 150, rect.y, 100, EditorGUIUtility.singleLineHeight), 
           element.FindPropertyRelative("secondField"), 
           GUIContent.none);
    }
}

This works correctly.这可以正常工作。 However, I would like to have the Inspector for every instance of this MonoBehaviour edit the same set of elements, so I created a ScriptableObject但是,我想让这个MonoBehaviour的每个实例的 Inspector 编辑相同的元素集,所以我创建了一个ScriptableObject

public MyScriptableObject : ScriptableObject
{
   public MyArrayElement[] myList;  
}

And then replace MyComponent.myList with an instance of MyScriptableObject然后用MyScriptableObject的实例替换MyComponent.myList

public class MyComponent : MonoBehaviour
{       
   // Remove this
   // public MyArrayElement[] myList;

   // Add this
   public MyScriptableObject myScriptableObject;
}

Then I want to update my custom editor for the MonoBehaviour to show myScriptableObject.myList然后我想更新MonoBehaviour的自定义编辑器以显示myScriptableObject.myList

I tried this, but the list is empty in the Inspector, even if the ScriptableObject 's list is not empty我试过了,但检查器中的列表是空的,即使ScriptableObject的列表不为空

SerializedProperty property = this.serializedObject.FindProperty("myScriptableObject").FindPropertyRelative("myList");
this.list = new ReorderableList(this.serializedObject, property, true, true, true, true);

Is there a way to get my MonoBehaviour s editor to let me edit the ScriptableObject s array?有没有办法让我的MonoBehaviour的编辑器让我编辑ScriptableObject的数组?

Yes there is;就在这里; ;) ;)

But first of all: Starting with Unity 2020 there is no need to use ReorderableList anymore except you want some very special behavior which seems not to be the case here.但首先:从 Unity 2020 开始,不再需要使用ReorderableList ,除非您想要一些非常特殊的行为,而这里似乎并非如此。 For List<T> and T[] this is now the default drawer anyway!对于List<T>T[]无论如何,这现在是默认抽屉!

And then using FindPropertyRelative only works for [Serializable] classes.然后使用FindPropertyRelative仅适用于[Serializable]类。

Whenever you deal with a separate UnityEngine.Object what you need to do is go through the SerializedObject of the instance of that reference.每当您处理单独的UnityEngine.Object ,您需要做的是通过该引用实例的SerializedObject进行 go。

Like eg像例如

var property = serializedObject.FindProperty("myScriptableObject").FindPropertyRelative("myList");
EditorGUILayout.PropertyField(property, true);

if(property.objectReferenceValue)
{
    var so = new SerializedObject(property.objectReferenceValue);
    so.Update();
    
    var list = so.FindProperty("myList");

    EditorGUILayout.PropertyField(list, true);

    so.ApplyModifiedProperties();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM