[Unity]LitJsonでセーブデータのシリアライズ

セーブしたい時にFileStreamなどでセーブしたいメンバーを一つずつちまちまWriteしていくのは何かと面倒ですよね。
作っていくうちにデータが増えたりもしますし。
そうなるとファイルバージョンを埋め込んでおいて、バージョンごとに読み込みメソッドと書き込みメソッドを用意してーなんてやっていると、仕様が増えて保存しないといけないデータが増えるごとに億劫に感じてしまいます。

そこで、LitJsonを使ってまずJson化。それを暗号化してファイルに保存すると楽にデータをシリアライズ/デシリアライズできるようになります。

C#のBinaryFormatterでも同じようにシリアライズできるのですが、iOSだと動かないとかで、今回はLitJsonを使うことにしました。
(まだMacはもちろんiPhoneも持ってないので、iOS対応はあくまで念のため・・・)
あとJsonと言ってもただの文字列なので、シリアライズ結果をそのまま確認できるのも良し。

LitJsonはこちらからダウンロードできます。
http://lbv.github.io/litjson

2013/10/10現在の最新版は0.70。
ライセンスはパブリックドメインなので気軽に使えるのもいいですね。

使い方も簡単で。

まずは、DL後、解凍してのbinフォルダにあるLitJson.dllをAssetsのフォルダとかに突っ込む。
もしくは、srcフォルダにあるLitJsonフォルダをそのまま突っ込む。

そして、


public class InventorySlot
{
	public int masterItemID;
	public int stack;
}

public class Data
{
	public string playerName;
	public int playerLevel;
	public List< InventorySlot > inventorySlots;
}

と仮に宣言したとして、
デシリアライズは、

string json;// ファイルとかから取ってくる
Data data = LitJson.JsonMapper.ToObject<Data>(json);

シリアライズは、

Data data;// どこかで生成する
string json = LitJson.JsonMapper.ToJson( data );

コレだけで済みます。

そのまま使う注意点としては、
・floatが扱えず、小数点数を扱うのであればdoubleにする必要がある
・ほか、longなどをデシリアライズしようとすると例外が発生する
などがありますが、これらもLitJson内を変更せずに外部からインポーターとエクスポーターを登録すれば回避できます。

ざっと用意してみたのがコチラです

public class JsonMapper
{
	static JsonMapper()
	{
		LitJson.JsonMapper.RegisterExporter<float>( (obj, writer) => { writer.Write( System.Convert.ToDouble( obj ) ); } );
		LitJson.JsonMapper.RegisterImporter<double,float>( (input) => { return System.Convert.ToSingle( input ); } );
		LitJson.JsonMapper.RegisterImporter<System.Int32,long>( (input) => { return System.Convert.ToInt64( input ); } );
	}

	public static T ToObject<T>( string json )
	{
		return LitJson.JsonMapper.ToObject<T>( json );
	}

	public static string ToJson( object obj )
	{
		return LitJson.JsonMapper.ToJson ( obj );
	}
}

これだけです。これもToObjectとToJsonを呼ぶだけで使えます。

最初にも言ったとおり、このようにしてシリアライズする最大の利点は、あとから追加が容易ということです。
たとえば先ほどのDataを


public class InventorySlot
{
	public int masterItemID;
	public int stack;
	public int durability; // 耐久度追加!
}

public class Data
{
	public string playerName;
	public int playerLevel;
	public List< InventorySlot > inventorySlots;
	public int equipSlot; // 装備追加!
}

このように要素追加してもシリアライズ/デシリアライズ部分は基本的に変更しなくても大丈夫です。
※まあ、大改造入ってデータフォーマットがらっと変わったりとかだとさすがに対応しきれません・・・そういう時はおとなしく変換メソッド作ることに・・・

Unityのアセット販売中!

ステートマシンの状態遷移やパラメータはエディタで編集でき、
ゲームロジックに依存するステートの挙動はスクリプトで記述可能なエディタ拡張。

詳細はこちら

RPGツクールVXやWOLF RPGエディターのオートタイルに準拠したエディタ拡張。

詳細はこちら

オススメ!