LoginSignup
2
4

More than 1 year has passed since last update.

Unityでセーブ:ScriptableObjectもDictionaryもシリアライズしたい

Posted at

やりたいこと

セーブデータをファイルとして保存したい。
そのために、下記をシリアライズしたい。

  • 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みたいな優良有料アセットだと、こういう悩みとは無縁なのかなぁ…
でもプログラム系のアセットは自分でなんとかしたい

よきゲーム制作を!

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4