I’ve been trying to use Unity’s own ReorderableList inside a custom property drawer. All the examples and tutorials I’ve come across only show it being used inside custom editors. I’m pretty sure it can be used in custom property drawers since that’s what UnityEventDrawer does.
The problem I’m having is that I can’t select any of the list’s element in the inspector.
I’m using this very simple code:
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
[CustomPropertyDrawer(typeof (Test))]
public class TestDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label) + 100f;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var list = property.FindPropertyRelative("test");
var r = new ReorderableList(property.serializedObject, list, true, true, true, true);
var x = ReorderableList.defaultBehaviours.draggingHandle;
;
r.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) => {
EditorGUI.PropertyField(rect, list.GetArrayElementAtIndex(index));
};
r.DoList(position);
}
}
[Serializable]
public class Test
{
public List<int> test;
}
I believe the problem is that you are creating the ReorderableList in every frame which is trashing the state of the ReorderableList.
This is why the CustomEditor examples instantiate the ReorderableList in the OnEnable() method. I’m afraid I haven’t tested if you can use the OnEnable() in a PropertyDrawer though.
I’m pretty sure that you’ll have to apply the result. Do a property.serializedObject.ApplyModifiedProperties(). I hide it in a EndChangeCheck, just to be safe:
if (EditorGUI.EndChangeCheck()) {
property.serializedObject.ApplyModifiedProperties();
}
It’s kind of a mystery when you need to apply modified properties, but as a general rule, do it unless all you’re using is PropertyFields.
I believe it should work even if you’re recreating the Reorderable every frame, but in case you ever need to cache stuff in a PropertyDrawer, this is how I do it:
private bool initialized = false;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
if (!initialized)
Initialize(property);
...
}
private void Initialize(SerializedProperty property) {
initialized = true;
//set up lists and cache data and whatnot
}
Unity generates a unique PropertyDrawer for each instance of a property (I believe), so this works.
Apparently [in SerializeReference lists] elements inside a ReorderableList use some sort of pooling system, so local fields can’t be trusted as is… We’d have to implement some sort of Dictionary to keep track of local fields for the correct SerializedProperty