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

JSONでセーブ機能を作ろう Unity

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を使ったセーブ・ロード処理のプログラム

それではサンプルとしてセーブ・ロード処理のプログラムを掲載しておきます。注意点として、このサンプルでは暗号化処理は行っていないのでゲームによっては別途暗号化処理を行う必要があります。

セーブデータ用のクラス

まずはセーブデータ用のクラスです。ここに保存したい値をメンバとして書いておきます。このクラスはシリアライズしたいので[Serializable]の記述を忘れないようにしてください。

using 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();
    
    }
    
    // 省略。以下のSave関数やLoad関数を呼び出して使用すること
    
    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);
        }
    }

}

おわりに

以上、JSONを使ったセーブ・ロード処理について説明しました。

近年のゲームではセーブ・ロード機能が欠かせない中、有名ゲームエンジンであるUnityが標準でまともなセーブ機能を用意していないのはとても残念なのですが、JSONを使えば比較的簡単にこれらの機能を自作できることは覚えておいて頂いて損はないと思います。

この記事がUnityでのゲーム開発のお役に立てば幸いです。