ReorderableList を使ってインスペクタ上でリストや配列の順番を変更する


ReorderableListを使うと、Unity組込みのインスペクタでよくあるこんな感じのUIを独自のクラスに適用することができます。

例えば、以下のようなクラスが定義されていて、HogeList というプロパティをインスペクタ上で順番変更したいとする

Hoge.cs
public class Hoge : MonoBehaviour {
    public List<string> HogeList;

    // ... snip ...
}

以下のようにカスタムエディタを定義する

HogeEditor.cs
using UnityEditor;
using UnityEditorInternal;

[CustomEditor(typeof(Hoge))]
public class HogeEditor : Editor {

    ReorderableList m_list;

    void OnEnable() {
        m_list = new ReorderableList (
            serializedObject,
            serializedObject.FindPropertyRelative("HogeList")
        );
    }

    // 変更可能なリストを表示
    public override void OnInspectorGUI () {
        // とりあえず元のプロパティ表示はしておく
        DrawDefaultInspector();

        serializedObject.Update ();

        // リスト・配列の変更可能なリストの表示
        m_list.DoLayoutList();

        serializedObject.ApplyModifiedProperties();
    }

以上が最低限の実装

ヘッダの文字を変更するには、OnEnable()に以下を追加

HogeEditor(1).cs
    m_list.drawHeaderCallback = (rect) => {
        EditorGUI.LabelField(rect, "ほげほげ一覧");
    };

リストの個々の要素の描画内容を変更するには以下を追加

HogeEditor(2).cs
    m_list.drawElementCallback = (rect, index, isActive, isFocused) => {
        var motion = m_motionsList.serializedProperty.GetArrayElementAtIndex(index);
        var displayName = string.Format ("{0} : {1}",
            motion.FindPropertyRelative("Name").intValue,
            motion.FindPropertyRelative("Age").stringValue
        );
        EditorGUI.LabelField(rect, displayName);
    };

Tips

1行の高さを変更する

// 2行分の高さに設定する
m_list.elementHeight = EditorGUIUtility.singleLineHeight * 2;

drawElementCallback の中で配列の要素にアクセスする

// callbackが呼び出されるときに渡される index を使って配列の要素を取得
var element = m_list.serializedProperty.GetArrayElementAtIndex(index);
// 配列の要素の"Name"プロパティの値を取得
var name = element.FindPropertyRelative("Word");
// ラベルを描画
EditorGUI.LabelField(rect, string.Format ("{0}:{1}", index, name.stringValue));

参考