I have a CustomEditor that displays my level builder information. It uses the UnityEditorInternal.ReorderableList to draw a list of levels with their properties in the Inspector.
private void OnEnable()
{
//Get top-level list property
list = new ReorderableList(serializedObject,
serializedObject.FindProperty("levels"),
true, true, true, true);
GUIStyle rightAlign = new GUIStyle();
rightAlign.alignment = TextAnchor.UpperRight;
//Draw and style list elements
list.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) => {
var element = list.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
var third = rect.width / 3f;
EditorGUI.LabelField(
new Rect(rect.x, rect.y, 18f, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("id").intValue.ToString(), rightAlign);
EditorGUI.PropertyField(
new Rect(rect.x + 25f, rect.y, third - 30f, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("name"), GUIContent.none);
}
}
So far everything works fine, but now I would like to add a property for an array within my reorderable list. When I try to use element.FindPropertyRelative like in the example above, the inspector draws an empty drop down arrow.
How can I draw array elements like the default Inspector does within my ReorderableList? If possible, I would like to stick to UnityEditorInternal.ReorderableList because it already has all the neat callbacks and most of what I need my custom Inspector to do.
Thanks for any suggestions!
Reviving this thread half a decade later. Did you ever figure this out? I can’t get any foldout (like an array) in a ReorderableList to not draw as a blank area when expanded.
I probably did not back then, but future-me to the rescue, here is a working example:
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
public class Test : MonoBehaviour
{
public List<LevelData> levels;
[System.Serializable]
public class LevelData
{
public string[] names;
}
}
[CustomEditor(typeof(Test))]
public class TestEditor : Editor
{
private ReorderableList list;
private void OnEnable()
{
list = new ReorderableList(
serializedObject,
serializedObject.FindProperty("levels"),
true, true, true, true)
{
elementHeightCallback = ElementHeightCallback,
drawElementCallback = DrawListElement
};
}
private float ElementHeightCallback(int index)
{
// Set the height of each row dynamically depending on the height of the names entries.
SerializedProperty namesProp = GetNamesProp(index);
return EditorGUI.GetPropertyHeight(namesProp) + EditorGUIUtility.standardVerticalSpacing;
}
private void DrawListElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty namesProp = GetNamesProp(index);
// By default, the array dropdown is offset to the left which intersects with
// the drag handle, so we can either indent the array property or inset the rect.
EditorGUI.indentLevel++;
// Take note of the last argument, since this is an array,
// we want to draw it with all of its children.
EditorGUI.PropertyField(rect, namesProp, includeChildren: true);
EditorGUI.indentLevel--;
}
private SerializedProperty GetNamesProp(int index)
{
var element = list.serializedProperty.GetArrayElementAtIndex(index);
return element.FindPropertyRelative("names");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
list.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}
1 Like