【Unity】JSONを使ったセーブ・ロード処理

JSONを使ったセーブ・ロード処理 ゲーム制作メモ
スポンサーリンク

最近Unityでゲームを作っていて「セーブ・ロード処理」でちょっと困ってしまいました。なぜ困ったのかというと、

  • Unityに標準で付いているセーブ・ロード機能である「PlayerPrefs」は問題だらけ(※後述)
  • 自作しようと作り方を調べてみると情報が錯綜している
  • かといってアセットを使うにもまともなアセットはだいたい有料
  • 一応ネットにセーブ・ロード処理を行うプログラムが落ちてはいるが、複雑すぎor原始的すぎて求めているものと違う

といったことがあったからです。結局セーブ・ロード機能を自作することにしたのですが、ネット上に「これだ!」という情報がなくて苦労したので、今回記事にまとめておくことにしました。

Unity標準の「PlayerPrefs」は問題だらけ

さてはじめに、そもそもなぜ今回セーブ・ロード機能を自作する必要があったのかということですが…最も大きな理由はお馴染みのPlayerPrefsは問題だらけのカス機能だから、というのが一番の理由です。PlayerPrefsはとても手軽に使える一方で次のような問題点があります:

  • 保存できるデータの型が少ない
  • 処理が遅い
  • 複数のデータを一括で保存できない
  • Windows用ゲームの場合、なぜか保存先がレジストリ(←最悪)

このような問題があるため、Unityを使い始めたばかりの人が試しに使うならともかく、きちんとしたゲームを作りたいならPlayerPrefsは使うべきではありません。Unityの入門書ではPlayerPrefsを使いましょう、などと書かれている場合がありますがあれは説明を簡略化するための方便なので気をつけましょう。

JSONを使いファイルに読み書きする

ではどうするのかというと、メジャーなやり方としてセーブデータ(=セーブ用の値を持つクラス)を「JSON」というフォーマットにして読み書きするという方法があります。JSONについての詳細はググって欲しいのですが、簡単に言えば複数のデータを記述するのに適した書き方のことです。これを使うとセーブ・ロード処理の手順は次のようになります:

  • セーブ処理:クラスをJSONに変換→ファイルに書き込み
  • ロード処理:ファイル読み込み→JSONからクラスに変換

つまり「クラス~JSON間の変換」と「ファイルの読み書き」ができればセーブデータを扱うことができるというわけです。

JsonUtility

最近のUnityには標準機能としてオブジェクトをJSONに変換する機能が付いています。それが「JsonUtility」です。詳しい使い方は「JSON 形式にシリアライズ – Unity マニュアル」を参照してください。

ファイルの読み書き

ファイル操作にはC#の機能を使います。読込みはStreamReader、書き込みはStreamWriterを使うのが一般的だと思います。詳しくはググってください。

JSONを使ったセーブ・ロード処理のプログラム

それでは今回作ったセーブ・ロード処理のプログラムを載せておきます。

セーブデータのクラス

ここに保存したい値をメンバとして書いておきます。[System.Serializable]の記述を忘れないようにしてください。

[System.Serializable]
public class SaveData
{
	//テスト用の文字列
	public string testString;

}

セーブ・ロード処理

using System.IO;
using UnityEngine;

public class SaveManager : MonoBehaviour
{

	string filePath;
	SaveData save;
	
	void Awake()
	{
		filePath = Application.persistentDataPath + "/" + ".savedata.json";
		save = new SaveData();
	}

//~中略~

	public void Save()
	{
		string json = JsonUtility.ToJson(save);

		StreamWriter streamWriter = new StreamWriter(filePath);
		streamWriter.Write(json);
		streamWriter.Flush();
		streamWriter.Close();
	}
	
	public void Load()
	{
		if (File.Exists(filePath))
		{
			StreamReader streamReader;
			streamReader = new StreamReader(filePath);
			string data = streamReader.ReadToEnd();
			streamReader.Close();

			save = JsonUtility.FromJson<SaveData>(data);
		}
	}

}

なお注意点として、ここでは暗号化処理は行っていないのでゲームによっては別途暗号化処理を行う必要があります。