データのセーブ・ロード機能はゲームには欠かせない要素です。
現在制作中のゲームでセーブ機能を実装するために色々調べて自作したので、備忘録として残しておきます。
PlayerPrefs使うのはダメなの?
一応UnityにはPlayerPrefsというセーブ・ロード用の機能がありますが使い勝手があまりよくないようです。(だから自作することにしました)
PlayerPrefsはとても手軽に使える一方で次のような問題点があります。
引用元:【Unity】JSONを使ったセーブ・ロード処理の作り方 | くろくまそふと
・保存できるデータの型が少ない
・処理が遅い
・複数のデータを一括で保存できない
・Windows用ゲームの場合、なぜか保存先がレジストリ(←最悪)
引用元のサイトにあるように「Unity始めたてで試しに実装してみたい」という場合でもなければ使わない方がよさそうです。
セーブ・ロード処理のスクリプト
サンプルで作成したスクリプトを載せておきます。
暗号化については省略しています。
一応暗号化の部分も自作したのですが正しいのか自信ないので…もう少し調べて理解出来たらいつか記事にするかも。
※実装の最適解というわけでは無いのであくまで参考程度で。
セーブデータクラス
以下のサンプルでは名前とスコアをセーブデータとして持つクラスになっています。
JSONとオブジェクト間の変換処理もこのクラスに書いてます。
[Serializable]とつけることでシリアライズ可能になり、JSONへ変換することができるようになります。
using System;
using UnityEngine;
[Serializable]
public class SaveData
{
public string name;
public int score;
/// <summary>
/// オブジェクトからJSONに変換
/// </summary>
/// <returns>JSON文字列</returns>
public string ToJson()
{
return JsonUtility.ToJson(this);
}
/// <summary>
/// JSONからオブジェクトに変換
/// </summary>
/// <param name="jsonStr">JSON文字列</param>
/// <returns>変換後のオブジェクト</returns>
public SaveData FromJson(string jsonStr)
{
return JsonUtility.FromJson<SaveData>(jsonStr);
}
}
セーブ・ロードクラス
このクラスにはセーブ、ロード処理を書いています。
using UnityEngine;
public static class SaveDataManager
{
/// <summary>
/// セーブ処理
/// </summary>
/// <param name="data">セーブデータ</param>
/// <param name="filePath">ファイルパス</param>
public static void SaveJsonData(SaveData data, string filePath)
{
if (FileControll.WriteFile(filePath, data.ToJson()))
{
Debug.Log("セーブ完了");
}
}
/// <summary>
/// ロード処理
/// </summary>
/// <param name="filePath">ファイルパス</param>
/// <returns>ロードしたデータ</returns>
public static SaveData LoadJsonData(string filePath)
{
// ファイルから読み込み
string json = FileControll.ReadFile(filePath);
if (!"".Equals(json))
{
SaveData sd = new SaveData();
return sd.FromJson(json);
}
return null;
}
}
ファイルの読み書きクラス
書き込み、読み込みの処理を書いています。
ファイルのパスを引数で取得するようにしてますがここで定義しちゃってもいいかもしれません。
using System;
using System.IO;
using UnityEngine;
public static class FileControll
{
/// <summary>
/// ファイル書き込み
/// </summary>
/// <param name="filePath">ファイルのパス</param>
/// <param name="json">書き込むJSON文字列</param>
/// <returns>true:正常終了、false:異常終了</returns>
public static bool WriteFile(string filePath, string json)
{
try
{
File.WriteAllText(filePath, json);
return true;
}
catch (Exception e)
{
Debug.LogError("書き込みに失敗しました。");
return false;
}
}
/// <summary>
/// ファイル読み込み
/// </summary>
/// <param name="filePath">ファイルのパス</param>
/// <returns>読み込んだ文字列(例外発生時は空文字)</returns>
public static string ReadFile(string filePath)
{
try
{
return File.ReadAllText(filePath);
}
catch (Exception e)
{
Debug.LogError("読み込みに失敗しました。");
return "";
}
}
}
サンプルの使用例
↓このようなスクリプトを作成しました。
using UnityEngine;
public class sample : MonoBehaviour
{
string filePath;
void Awake()
{
filePath = Application.persistentDataPath + "/" + ".savedata.json";
}
public void DoSave()
{
SaveData sd = new SaveData();
sd.score = 100;
sd.name = "テストネーム";
SaveDataManager.SaveJsonData(sd, filePath);
}
public void DoLoad()
{
SaveData sd = SaveDataManager.LoadJsonData(filePath);
Debug.Log("sd.score:" + sd.score);
Debug.Log("sd.name:" + sd.name);
}
}
セーブボタンとロードボタンを追加し、OnClickでDoSaveとDoLoadを呼び出すようにします。

実行してセーブボタンをクリックすると、「Application.persistentDataPath」の場所にJSONファイルが作成されました。

一度終了した後にもう一度実行してロードボタンをクリックすると、セーブした内容がコンソールに出力されました。

まとめ:JSONを使ってセーブデータ管理
PlayerPrefsを使用せずにセーブ機能を実装する場合はJSONとファイルの読み書きを使用するのがいいと思います。
また、使ったことはありませんがアセットにもセーブ機能用の便利なものがあるようです。
ただアセットは楽ですが有料だったりもするので、自分で実装できるなら自作した方がいいかもしれません。
コメント