UnityのセーブデータにMessagePack-CSharpを利用してみる

はじめに

前回はUnityでMasterMemoryを使ってみました。 今回はこのMasterMemoryに付属してくるMessagePack-CSharpを セーブデータの保存に利用してみます。

  • Unity: 2019.2.1f1
  • MessagePack-CSharp: Ver 1.7.3.5

MessagePack-CSharpを使う

前回の記事のとおりに実行していれば、MessagePack-CSharpを利用するのに必要なコード生成の処理が書かれています。

試しにスキルレベルを保存するコードを書いてみます。

SaveData.csに次のように。

using System.Collections.Generic;
using MessagePack;

[MessagePackObject]
public class SaveData {
    [Key (0)]
    public List<int> SkillLevels { get; set; }

    public SaveData (List<int> skillLevels) {
        SkillLevels = skillLevels;
    }
}

SaveDataManager.csに次のように。

using System.Collections.Generic;
using System.IO;
using MessagePack;
using UnityEngine;

public class SaveDataManager {
    private static SaveDataManager _instance = new SaveDataManager ();
    public static SaveDataManager Instance => _instance;

    private SaveData _saveData;

    private void CreateNewSavedata () {
        _saveData = new SaveData (new List<int> { 1, 1, 1, 2 });
    }

    public void Load (string saveFilename) {
        var saveDirectory = $"{Application.dataPath}/SaveData";
        var filePath = $"{saveDirectory}/{saveFilename}";

        try {
            using (var fs = new FileStream (filePath, FileMode.Open, FileAccess.Read)) {
                byte[] bytes = new byte[fs.Length];
                fs.Read (bytes, 0, bytes.Length);
                _saveData = MessagePackSerializer
                    .Deserialize<SaveData> (bytes);
            }
        } catch {
            CreateNewSavedata ();
        }
    }

    public void SaveSkillLevels (string saveFilename, List<int> skillLevels) {
        _saveData.SkillLevels = skillLevels;

        var bytes = MessagePackSerializer.Serialize (_saveData);

        var saveDirectory = $"{Application.dataPath}/SaveData";
        Directory.CreateDirectory (saveDirectory);

        var filePath = $"{saveDirectory}/{saveFilename}";

        using (var fs = new FileStream (filePath, FileMode.Create)) {
            fs.Write (bytes, 0, bytes.Length);
        }
    }

    public IReadOnlyList<int> SkillLevels => _saveData.SkillLevels;
}

Test.csを次のようにします。

using System.Linq;
using UnityEngine;

public class Test : MonoBehaviour {
    void Start () {
        var db = MasterDataDB.DB;

        var saveDataManager = SaveDataManager.Instance;
        saveDataManager.Load ("save-file-0");
        var skillLevels = saveDataManager.SkillLevels;

        foreach (var skill in db.SkillTable.All) {
            Debug.Log ($"Skill Name: {skill.SkillName}");

            var lv = skillLevels[skill.SkillID];
            Debug.Log ($"Skill Lv: {lv}");

            var parameter = db.SkillParameterTable
                .FindBySkillIDAndSkillLv ((skill.SkillID, lv));
            Debug.Log ($"Skill Damage: {parameter.Damage}");
        }

        var newLevels = skillLevels.Select (lv => {
            if (lv >= 9) return lv;
            return lv + 1;
        }).ToList ();
        saveDataManager.SaveSkillLevels ("save-file-0", newLevels);
    }
}

「MasterMemory > CodeGenerate」を実行します。

2019 08 22 16 23 32

実行するたびにレベルが上っていきます。

2019 08 22 16 23 49

2019 08 22 16 24 14

2019 08 22 16 24 25

バイナリファイルにデータが書き込まれています。

2019 08 22 16 25 10

おわりに

バイナリファイルにシリアライズすることでセーブデータの保存ができました。 今回作ったセーブデータマネージャがあまりにも適当なので もっとしっかりしたセーブデータ管理システムを作りたいです。

今回のソースコードのリポジトリ

  • Unity
  • C#