C++幼女先輩

プログラミング成分多め

UNITY メニュー拡張 part2 値を保存する

はじめに

UNITYのメニュー拡張をし Windowの表示は出来ました
ところが、このままでは一度ウインドウを閉じたあと再び開いても設定した値がデフォルトに戻ります
前回設定した値が残っていて欲しい時は多いと思うので、その設定です

方針

EditorWindowの値をファイルに保存すれば良いが、UNITYにはそれを補助する機能がある
ScriptableObjectを継承していれば簡単に yamlの形でAssetとして保存出来る

アセット作成

まず保存するためのAssetを作る必要があるが、おそらくコードで作成させることも出来るとおもうが
エディタ拡張でぱぱっとやってみる

まず保存するデータのクラスを ScriptableObjectを継承し作成する

[CreateAssetMenu]
public class TestObject : ScriptableObject
{
    [SerializeField] public  string hoge_;
}

[CreateAssetMenu] のアトリビュートをつけると、メニューの Asset->Create に表示されるようになる
つまり メニューから、保存先のAssetを作成する

ScriptableObjectを継承するのはSerializeのためである
今回は string hoge_ を保存する

とりあえず上記で 保存するオブジェクトは出来た

シリアライズ&デシリアライズ

先ほど作った TestObjectを使い シリアライズ、デシリアライズを行う

まず、アセットが読みこまれてない場合は読みこむ
if (this.data == null) { this.data = LoadData(); }

中身は、アセット一覧より TestObjectのものを探す

そして、データのアクセスは TestObjectを経由する

EditorGUI.BeginChangeCheck();
EditorGUI.EndChangeCheck();
にて、GUIの値が変更された時のみ、Assetに書き込む
data.hoge = hoge;
EditorUtility.SetDirty(this.data);

public class TestWindow : EditorWindow
{
    [SerializeField] private TestObject data;


    [MenuItem("Tools/Test")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(TestWindow));
    }

    void OnGUI()
    {
        if (this.data == null) { this.data = LoadData(); }

        EditorGUI.BeginChangeCheck();

        string hoge_ = data.hoge_;
        hoge_ = EditorGUILayout.TextField("HOGE", hoge_);

        if (EditorGUI.EndChangeCheck()) 
        {
            data.hoge_ = hoge_;
            EditorUtility.SetDirty(this.data); 
        }

    }
    static TestObject LoadData()
    {
        return (TestObject)AssetDatabase.FindAssets("t:ScriptableObject")
           .Select(guid => AssetDatabase.GUIDToAssetPath(guid)) 
           .Select(path => AssetDatabase.LoadAssetAtPath(path, typeof(TestObject))) 
           .Where(obj => obj != null) 
           .FirstOrDefault(); 
    }

}

これで簡単だが、EditorWindowの値をシリアライズさせることができる