読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】ScriptableSingletonでエディタウィンドウ間の情報共有

目次

エディタは値を忘れる

Unityエディタは実は物忘れが激しいです。

何が言いたいかと言えば、エディタウィンドウ等で使用されているstaticな変数を「ゲームの再生時やコンパイル時に忘れる」という、中々面白い挙動を行います。

これは単一のウィンドウ内で完結している場合は全く問題は無いのですが、複数のウィンドウで情報を共有したい場合、非常に面倒くさい事になります。

例えば下の画像では、pushボタンを押した数だけカウントが進んでいくサンプルです。このサンプルではどのウィンドウから押しても数値を加算可能なようにstatic変数で値の共有を行っていますが、ゲーム再生時に初期化されてしまいます。

f:id:tsubaki_t1:20151104220642j:plain

using UnityEngine;
using System.Collections;
using UnityEditor;

public class EditorWIndowTest : EditorWindow 
{
	static int clickCount = 0;

	[MenuItem("Command/Show")]
	static void Init()
	{
		EditorWIndowTest.CreateInstance ().Show ();
	}

	void OnGUI()
	{
		if (GUILayout.Button ("push")) {
			clickCount ++;
		}
		EditorGUILayout.LabelField (clickCount.ToString ("000"));
	}
}

ScriptableSingletonを使う

ScriptableSingletonを使えば、ゲーム再生時に消えない&データが共有できるオブジェクが作れます。

またScriptableSingletonの生存時間は「エディタを止めるまで」とかなり長く、一度インスタンス化が行われれば、エディタ上ではずっと使いまわすことが出来ます。

 例えば上のコードを下のように書き直します。

using UnityEngine;
using System.Collections;
using UnityEditor;

public class EditorWIndowTest : EditorWindow 
{	[MenuItem("Command/Show")]
	static void Init()
	{
		EditorWIndowTest.CreateInstance ().Show ();
	}

	void OnGUI()
	{
		if (GUILayout.Button ("push")) {
			ScriptableSingleton<EditowWindowTestData>.instance.count ++;
		}
		EditorGUILayout.LabelField (ScriptableSingleton<EditowWindowTestData>.instance.count.ToString ("000"));
	}
}

public class EditowWindowTestData : ScriptableSingleton<EditowWindowTestData>
{
	public int count;
}

 大きな違いはstatic変数として持っていたCountの値を、新しく作成したEditorWindowTestDataクラスに持たせている事です。

これによって、ゲーム再生後もデータを失わせることなく、ウィンドウ間のデータ共有が出来る訳です。

感想

本当は「プロジェクト単位でデータを保存できる事」を期待していたのですが、Saveメソッドがあったりデータをロードできるっぽい内部構造をしている割に、全くこの手の操作には使えません。
またScriptableObjectとしてアセットをプロジェクトに保存し全体参照しようにも、起動時最初に呼び出した(保存したSOでなければコードで初期化されたSO)が呼ばれ、インスタンスが重複した場合「ひたすらにエラーログを出す」という微妙な仕様です。

せめてエディタ用APIじゃなければ、それでもマシと思えたのですが…

うーん。