📘
[Unity]MessagePackをjsonで読み書きするEditorWindow対応をしました
はじめに
デバッグ用にPlayerPrefsにデータを格納していたのをMessagePackに変更しました。
MessagePackについてはこちらを使用させていただいています。
はじめはPlayerPrefsにjson形式でデータを格納しており表示や編集がしやすかったのですが、バイナリファイルとして保存することになったため確認ができない状態でした。
そこで簡易的に表示・編集をするようなものを作ろうと思いました。
環境
Unity 2022.3.5f1
MessagePack-CSharp 2.4.35
確認用に作成したクラス
Userクラス
[MessagePackObject]
public sealed class User
{
[Key(0)]
public string Name { get; set; }
[Key(1)]
public int Level { get; set; }
}
UserQuestクラス
[MessagePackObject]
public sealed class UserQuest
{
[Key(0)]
public Dictionary<int, Dictionary<int, List<int>>> ClearQuestMap { get; set; }
}
データ
こんな感じで入れてみます。
var user = new User();
user.Name = "hoge";
user.Level = 1;
var bytes = MessagePackSerializer.Serialize(user);
File.WriteAllBytes($"{Application.dataPath}/UserData.bin", bytes);
var userQuest = new UserQuest();
userQuest.ClearQuestMap = new Dictionary<int, Dictionary<int, List<int>>>();
userQuest.ClearQuestMap.Add(1, new Dictionary<int, List<int>>());
userQuest.ClearQuestMap[1].Add(1, new List<int>());
userQuest.ClearQuestMap[1][1].Add(1);
userQuest.ClearQuestMap[1][1].Add(2);
userQuest.ClearQuestMap[1][1].Add(3);
var questBytes = MessagePackSerializer.Serialize(userQuest);
File.WriteAllBytes($"{Application.dataPath}/UserQuest.bin", questBytes);
EditorWindowのコード
UnityのメニューバーのTools => Save File Editでファイルを開くウィンドウを出すようにしてあります。
Saveボタンを押すとファイルを保存します。
public sealed class SaveFileEditorWindow : EditorWindow
{
string _filePath;
string _json;
Vector2 _scroll;
[MenuItem("Tools/Save File Edit")]
static void Init()
{
var filePath = EditorUtility.OpenFilePanel("Select SaveFile", Application.dataPath, "bin");
if (string.IsNullOrEmpty(filePath)) return; // Not selected File
var result = MessagePackSerializer.Deserialize<dynamic>(File.ReadAllBytes(filePath));
var json = MessagePackSerializer.SerializeToJson(result);
var self = (SaveFileEditorWindow)GetWindow(
typeof(SaveFileEditorWindow),
false,
Path.GetFileName(filePath),
true
);
self._json = json;
self._filePath = filePath;
self.Show();
}
void OnGUI()
{
_scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.Height(500));
_json = EditorGUILayout.TextArea(_json, GUILayout.ExpandHeight(true));
EditorGUILayout.EndScrollView();
using (new GUILayout.HorizontalScope()) {
GUILayout.FlexibleSpace();
if (GUILayout.Button("Save", EditorStyles.miniButton)) {
File.WriteAllBytes(_filePath, MessagePackSerializer.ConvertFromJson(_json));
Close();
}
}
}
}
表示
UserData.bin
UserQuest.bin
まとめ
MessagePackSerializerのjson対応のコードを使うことで簡単に対応できました。
jsonとMessagePackで変換するときの型はbyte[]などは問題ありそうですが、今回使いそうなのは数値・文字列・Dictionary・List・Arrayくらいだったので問題なさそうです。
またこのバイナリファイルはこのクラスに対応したものだから、このクラスでDeserializeしないといけないみたいな紐付けする部分が大変かもと思ってたのですが、dynamicが使えたことで解決しました。
il2cppでは使えないのですが、Editorでの動作用なので問題ありませんでした。
Discussion