【Unity】【エディタ】アセンブリリロード時に消えない値を保持するSessionStateの使い方まとめ

Unityでアセンブリリロード時に消えない値を保持するSessionStateの使い方をまとめました。

Unity2020.2.7f1

SessionState?

Unityエディタにおいて、ホットリロードの対象でない値はアセンブリリロード時に初期化されます。
例えば以下のようにInspector拡張に使っている値は、再生ボタンを押したときにリセットされます。

using UnityEditor;
using UnityEngine;

public class Example : MonoBehaviour
{
}

[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
    // アセンブリリロード(再生ボタン押したりしたとき)にコレがfalseに戻る
    private bool _foldOut;
    
    public override void OnInspectorGUI()
    {
        _foldOut = EditorGUILayout.Foldout(_foldOut, "FoldOut");
        if (_foldOut)
        {
            GUILayout.Label("Foo");
            GUILayout.Label("Bar");
            GUILayout.Label("Boo");
        }
        
    }
}

動作の様子は以下の通りです。再生時に折り畳みが解除されていることがわかります。

f:id:halya_11:20210602222028g:plain
動作

SessionStateを使うとアセンブリをリロードしても消えない値を保持しておけます。
また、アセンブリリロードしても消えないものの、Unityを閉じた時には消えてくれます。
内部的にはEditorPrefsが使われているようです。

使い方

それでは実際にSessionStateを使って前節の問題を解消します。
ソースコードは以下の通りです。

using UnityEditor;
using UnityEngine;

public class Example : MonoBehaviour
{
}

[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
    private bool _foldOut;
    private bool _isInitialized;
    
    private static string FoldOutStateKey => $"{nameof(ExampleEditor)}{nameof(_foldOut)}";

    public override void OnInspectorGUI()
    {
        if (!_isInitialized)
        {
            // SessionStateから値を取得する
            _foldOut = SessionState.GetBool(FoldOutStateKey, false);
            _isInitialized = true;
        }

        using (var ccs = new EditorGUI.ChangeCheckScope())
        {
            _foldOut = EditorGUILayout.Foldout(_foldOut, "FoldOut");
            if (ccs.changed)
            {
                // SessionStateに値を保存する
                SessionState.SetBool(FoldOutStateKey, _foldOut);
            }

            if (_foldOut)
            {
                GUILayout.Label("Foo");
                GUILayout.Label("Bar");
                GUILayout.Label("Boo");
            }
        }
    }
}

初期化時に値を取り出し、変更があったら値を保存しています。
動作の様子は以下の通りです。

f:id:halya_11:20210602222533g:plain
動作の様子

再生しても折り畳みが解除されなくなりました。

ホットリロードについて

ホットリロードの対象となっている値についてはアセンブリリロード時にも値を保持します。
ホットリロードについては以下の記事にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

関連

light11.hatenadiary.com

参考

docs.unity3d.com