【UnityEditor】EditorWindowの状態の永続化

# はじめに
通常、EditorWindowのパラメータは**ウィンドウを閉じてしまうとリセット**されてしまいます。

ウィンドウ上のパラメータを**ScriptableObject**に保存しておくことで、ウィンドウを閉じた後でもデータを保持させておくことができます。

今回はそのやり方についてご紹介したいと思います。


# 環境
Windows 10
Unity5.6.1f1

# STEP1. ScriptableObjectクラスの用意
今回はEditorWindowへ入力した**テキストを永続化**するという例を考えます。

まずはデータ保存用にScriptableObjectクラスを作成します。

以下のスクリプトをプロジェクト内へ入れてください.

```PermanentData.cs
namespace PermanentTest
{
    using UnityEngine;

    [CreateAssetMenu]
    public class PermanentData : ScriptableObject
    {
        [SerializeField] private string text;

        public string Text { get { return this.text; } set { this.text = value; } }
    }
}
```

 [SerializeField]をつけたstring変数と、その読み書きを行うプロパティを定義しただけのシンプルな**ScriptableObject**クラスです。

[CreateAssetMenu]をつけることでメニューからScriptableObjectアセットを作成できるようにしています。

# STEP2. ScriptableObjectの作成
Projectウィンドウ上で右クリックして、**Create -> Permanent Data** を選択してScriptableObjectを作成します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/ed88aab3-0507-ebd9-1138-591abb9f516a.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/38aff6de-64fa-ff75-8767-9f537c411823.png)

# STEP3. EditorWindowの用意
プロジェクト内にEditorフォルダを作成して、以下のスクリプトをフォルダの中へ入れます。

```PermanentTest.cs
namespace PermanentTest
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
	using System.Linq;

    public class PermanentEditorWindow : EditorWindow
    {
        [SerializeField] private PermanentData data; // データ

        [MenuItem("EditorWindow/PermanentEditorWindow")]
        static void Open()
        {
            GetWindow<PermanentEditorWindow>(); // ウィンドウを開く
        }

        /// <summary>
        /// ウィンドウの描画
        /// </summary>
        void OnGUI()
        {
            if (this.data == null) { this.data = LoadData(); }

			EditorGUI.BeginChangeCheck();

			string text = this.data.Text; // ScriptableObjectからテキストを取り出す
			text = EditorGUILayout.TextField("テキスト", text); // テキスト入力

			if (EditorGUI.EndChangeCheck()) // テキストが変更された場合は
			{
				this.data.Text = text; // データへテキストを保存する
				EditorUtility.SetDirty(this.data); // データの変更をUnityに教える
			}
			
        }

        /// <summary>
        /// データのロード
        /// </summary>
        static PermanentData LoadData()
        {
            return (PermanentData)AssetDatabase.FindAssets("t:ScriptableObject") // プロジェクトに存在する全ScriptableObjectのGUIDを取得
               .Select(guid => AssetDatabase.GUIDToAssetPath(guid)) // GUIDをパスに変換
               .Select(path => AssetDatabase.LoadAssetAtPath(path, typeof(PermanentData))) // パスからPermanentDataの取得を試みる
               .Where(obj => obj != null) // null要素は取り除く
               .FirstOrDefault(); // 取得したPermanentDataのうち、最初の一つだけを取り出す
        }
    }
}
```

ScriptableObjectの自動ロードを行い、入力テキストをScriptableObject内へ保存しています。

# STEP4. テキストが永続化していることを確認する。
画面上部のメニューから **EditorWindow -> PermanentEditorWindow** を選択して、ウィンドウを開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/4ad0b226-d91d-fdda-1172-206937da6759.png)

ウィンドウをいったん閉じて開きなおしてもテキストは入力されたままだということが確認できます。

![permanent.gif](https://qiita-image-store.s3.amazonaws.com/0/44288/f8cc275d-019f-23d9-acbb-822d0bacf017.gif)

※ScriptableObjectが存在しない場合はエラーが出てしまうので注意してください

# テキストの保存先について
ScriptableObjectを確認すると、ウィンドウ上のテキストが保存されていることが確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/f1b49512-ea41-4d7f-99df-1abcd6e8529f.png)