したかみ ぶろぐ

Unity成分多め

ReorderableListがわからん

始めに

aizu-vr.hatenablog.com

先週書いたブログです。未だに問題を解決できず、進捗が出ず、イライラが続いています。

ここさえできれば今作成中のゲームは凄い勢いで進むはずだし、次作るゲームに関してもすぐに完成出来るはず。だからこそ諦めたくはないのだ!

と、いうことで今回はReorderableListの実験をしながら結果をまとめていこうと思います。

第一段階

始めは色々なサイトを参考にしながらコード書いていましたが、全くもって動く気配がありませんでした。

なのでこのサイトをそのまんま真似て動くようにしました。

第14章 ReorderbleList - エディター拡張入門
「14.10 要素のGUIをカスタマイズ」

結果はちゃんと要素の追加、削除、入れ替えが正常に動作しました。

第二段階

ねくすと、私がやりたいことはドロップダウンメニューの追加をしたいと思います。 第14章 ReorderbleList - エディター拡張入門 「14.7 「+」ボタンにドロップダウンメニューの追加」

ここではstring[]の要素を追加していますが、私がしたいのは自作クラスの追加です。

書いてある通りやってみる

ここでは先の「14.6 要素の追加」と次のサイトを参考にしました。

kan-kikuchi.hatenablog.com

reorderableList.onAddDropdownCallback =
    (rect, list) => {

        var menu = new GenericMenu();

        menu.AddItem(
            new GUIContent("MonsterAction"),
            false,
            () => {
                // 要素を追加
                actionsProperty.arraySize++;

                // 最後の要素を選択状態にする
                list.index = actionsProperty.arraySize - 1;
            });

        menu.DropDown(rect);

    };

そしてUnityへ.....

結果、 失敗!

f:id:vxd-naoshi-19961205-maro:20190609195922p:plain

ドロップダウンメニューの表示は出来ていますが、要素の追加が上手く出来ていませんでした。ということは要素を追加するところのラムダ式のところが間違っていると思います。



未知なる関数「SerializedProperty.InsertArrayElementAtIndex」を使ってみる

SerializedPropertyにはInsertArrayElementAtIndex(int index)というメンバ関数があるみたい。そいつを使ってみる。

menu.AddItem(
    new GUIContent("MonsterAction"),
    false,
    () => {
        actionsProperty.arraySize++;
        list.index = actionsProperty.arraySize - 1;
        actionsProperty.InsertArrayElementAtIndex(list.index);
    });

結果、 失敗!
ほぼほぼ先ほどと同様の結果でした。


考察

ContextMenuを使って実際に保存されている値を表示する関数をMonsterクラスに実装しています。

 [ContextMenu("PrintMonsterActionParameter")]
    void PrintMonsterActionParameter() {
        Debug.Log("searching...");
        Debug.Log("actions.Count = " + actions.Length);
        for (int i = 0; i < actions.Length; ++i) {
            Debug.Log("count = " + i);
            actions[i].Print();
            Debug.Log("");
        }
    }

ここでは入っているデータの個数と数値を出力しています。Inspectorの値を変更した後にこの関数を呼び出しているのですが、そもそもデータの個数が増えていないことが分かりました。
なので、もう一度データを追加する方法を検討していきます。

まとめ

ここではSerializedObjectを使用したEditor拡張を行いました。このSerializedObjectを使用しない方法もあるのですが、その場合だとUndoとRedoを自分で実装しないといけなかったような気がします(そしてそれが面倒だったはず)。
また、使用しないでReorderableListを使ったことがあったのですが、その時はオブジェクトをprefabにApplyしないとInspector上の値が保存されないというバグがありました。

そういうわけで今回はSerializedObjectでの実装を目指しました。