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に次のように。

1
2
3
4
5
6
7
8
9
10
11
12
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に次のように。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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を次のようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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」を実行します。

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

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

おわりに

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

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