やりたいこと
セーブデータをファイルとして保存したい。
そのために、下記をシリアライズしたい。
- Vector3などのUnity組み込みクラス
- Dictionary
※今回はシリアライズに関してなので、暗号化やファイル保存、逆アセンブル対策などは扱いません
こまったこと
Unityで利用できるシリアライズ方法は、主に2通り
- .Netで一般的な方法(例:System.Text.Json等)は、
- Vector3やScriptableObjectなど、Unity組み込みクラスに対応しない
- UnityEngine.JsonUtility
- Unity組み込みクラスに対応しているが、Dictionaryを保存できない
でもUnity組み込みクラスとDictionaryを両立したい!
解決方法
Dictionaryを含んだクラスは別に切り分け、byte[]としてシリアライズする
※JsonとかでもOK
※サンプルではNugetとか不要なBinaryFormatterを使用
サンプルコード
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
[Serializable]
public class SaveData
{
public Vector3 position;
public byte[] dictionaryClassBinary;
}
[Serializable]
public class DictionarySaveData
{
// フラグとかを想定
public Dictionary<string, bool> data1;
}
public class SaveTest : MonoBehaviour
{
public void Save() {
var saveData = new SaveData();
saveData.position = transform.position;
var dictionarySaveData = new DictionarySaveData();
// 適当にデータセット
dictionarySaveData.data1= new Dictionary<string, bool>();
dictionarySaveData.data1["test"] = true;
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, dictionarySaveData);
saveData.dictionaryClassBinary = ms.ToArray();
}
string saveDataJson = JsonUtility.ToJson(saveData);
byte[] saveDataBinary = Encoding.UTF8.GetBytes(saveDataJson);
// saveDataBinaryを暗号化してファイル保存
}
public void Load() {
string saveDataJson = /* ファイルを開いて復号、jsonを読み取ってくる */;
SaveData saveData = JsonUtility.FromJson<SaveData>(saveDataJson);
using (var ms = new MemoryStream(saveData.dictionaryClassBinary))
{
var bf = new BinaryFormatter();
var dictionarySaveData = (DictionarySaveData)bf.Deserialize(ms);
// trueと表示される!
Debug.Log(dictionarySaveData.data1["test"]);
}
// Unity組み込みクラスも読み込めている
transform.position = saveData.position;
}
}
まとめ
EasySaveみたいな優良有料アセットだと、こういう悩みとは無縁なのかなぁ…
でもプログラム系のアセットは自分でなんとかしたい
よきゲーム制作を!