Re-orderable object lists in inspector

Hello. I have a list of serializable objects to represent entries in a library. I want to be able to order them in the inspector, just for ease of work.
I know this is a common question, so I’ve looked up some answers and found a plugin by rotorz. This works like a charm for simple type lists, but not for lists of a serialized object class.

Any ideas? What is your way around it?

The way I should do that is by making a custom inspector.

Since Unity 4.5 There is this class called UnityEditorInternal.ReorderableList. Sadly it is not documented, but it is a very nice class. (The result should be compareable to your list)

This is a class that can be used to draw a list in the inspector the way Unity draws some of it’s own lists (Like the list used to add sorting layers for instance)

Since you are talking about serializable objects, I assume you are talking about classes that have the Serializable attribute, and not MonoBehaviours that are serializable by default.

To implement this you need a Class that is Serializable (Or MonoBehaviour)

using UnityEngine;
using System;

[Serializable]
public class ListItemExample
{
    public bool boolValue;
    public string stringvalue;
}

Then you need the MonoBehaviour that has a list you want to show in the inspector

using UnityEngine;
using System.Collections.Generic;

public class ListExample : MonoBehaviour
{
    [HideInInspector] // we do this beacause we call base.OnInspectorGUI(); And we don't want that to draw the list aswell.
    public List<ListItemExample> list;
}

And then the place where the magic happens. The custom inspector.

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;

[CustomEditor(typeof(ListExample))]
public class listExampleInspector : Editor
{
    private ReorderableList reorderableList;

    private ListExample listExample
    {
        get
        {
            return target as ListExample;
        }
    }

    private void OnEnable()
    {
        reorderableList = new ReorderableList(listExample.list,typeof(ListItemExample), true, true, true, true);

        // This could be used aswell, but I only advise this your class inherrits from UnityEngine.Object or has a CustomPropertyDrawer
        // Since you'll find your item using: serializedObject.FindProperty("list").GetArrayElementAtIndex(index).objectReferenceValue
        // which is a UnityEngine.Object
        // reorderableList = new ReorderableList(serializedObject, serializedObject.FindProperty("list"), true, true, true, true);

        // Add listeners to draw events
        reorderableList.drawHeaderCallback += DrawHeader;
        reorderableList.drawElementCallback += DrawElement;

        reorderableList.onAddCallback += AddItem;
        reorderableList.onRemoveCallback += RemoveItem;
    }

    private void OnDisable()
    {
        // Make sure we don't get memory leaks etc.
        reorderableList.drawHeaderCallback -= DrawHeader;
        reorderableList.drawElementCallback -= DrawElement;

        reorderableList.onAddCallback -= AddItem;
        reorderableList.onRemoveCallback -= RemoveItem;
    }

    /// <summary>
    /// Draws the header of the list
    /// </summary>
    /// <param name="rect"></param>
    private void DrawHeader(Rect rect)
    {
        GUI.Label(rect, "Our fancy reorderable list");
    }

    /// <summary>
    /// Draws one element of the list (ListItemExample)
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="index"></param>
    /// <param name="active"></param>
    /// <param name="focused"></param>
    private void DrawElement(Rect rect, int index, bool active, bool focused)
    {
        ListItemExample item = listExample.list[index];

        EditorGUI.BeginChangeCheck();
        item.boolValue = EditorGUI.Toggle(new Rect(rect.x, rect.y, 18, rect.height), item.boolValue);
        item.stringvalue = EditorGUI.TextField(new Rect(rect.x + 18, rect.y, rect.width - 18, rect.height), item.stringvalue);
        if (EditorGUI.EndChangeCheck())
        {
            EditorUtility.SetDirty(target);
        }

        // If you are using a custom PropertyDrawer, this is probably better
        // EditorGUI.PropertyField(rect, serializedObject.FindProperty("list").GetArrayElementAtIndex(index));
        // Although it is probably smart to cach the list as a private variable ;)
    }

    private void AddItem(ReorderableList list)
    {
        listExample.list.Add(new ListItemExample());

        EditorUtility.SetDirty(target);
    }

    private void RemoveItem(ReorderableList list)
    {
        listExample.list.RemoveAt(list.index);

        EditorUtility.SetDirty(target);
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        // Actually draw the list in the inspector
        reorderableList.DoLayoutList();
    }
}

This is then how it looks in the editor:
34828-result.png

This works even better if you use a CustomPropertyDrawer (for the link: go to the “WRITING A PROPERTYDRAWER FOR A CUSTOM SERIALIZABLE CLASS” part) for you custom Serializable class. Maybe the solution you are using now also works when you use a custompropertydrawer, but I can’t tell for sure because I never used this plugin :wink:

Hi guys,

How to make a object references for inspector list, to be used like drag and drop in Unity?
For strings, ints floats I managed but for GameObject or Transforms?

Thanks in advance!

I made a series of methods for my custom inspectors since I had to write waaay too many of those in my time. It lets me reorder, copy, select/delete etc.

PEGI Inspector

There is a GIST that shows what needs to be done to make custom Inspector.

And the scripts themselves are here.

In this video, I show off one of the custom inspectors to control some global lighting settings.

Not many people use those scripts as I know, and there is probably still room for improvements, but I think it could save some time overall.