今回は、Unityゲーム開発において超便利なJSONを使ったセーブ・ロードシステムについて、紹介したいと思います。
【Unity】JSONを使ったセーブ・ロード:初心者でも簡単に実装!
JSONって何?
JSONは「JavaScript Object Notation」の略で、人間にも機械にも読みやすいデータ形式です。まるで、データが会話しているかのようなシンプルな構造を持っています。
なぜUnityでJSONを使うの?
超シンプル!データ管理が楽チン
{
"playerName": "勇者",
"level": 10,
"score": 1500
}
このように、データを直感的に保存できます。プログラミング初心者でも、一目でデータの中身が分かりますね。
軽量で高速
JSONは軽いデータ形式なので、ゲームの読み込みや保存が超高速!モバイルゲームでも快適に動作します。
複雑なデータも保存可能
プレイヤーの位置、装備、スキル等あらゆるデータが保存できちゃいます。
実際の実装方法(Cubeの位置情報をセーブ&ロードする)
ここから、例としてCubeをプレイヤーに見立てて位置情報をセーブしたりロードしたりしてみたいと思います。
プロジェクトを作ったら適当にPlaneを作ってその上にCubeを用意します。とりあえずプレイヤーの役割をしてほしいのでCubeの名前は「Player」に変更しておきます。
セーブとボタン用のボタンをそれぞれ作ります。
ゲームビューはこんな感じですね。
セーブ及びロードを行うためのスクリプト「Gamemanager」スクリプトを作成します。
using UnityEngine;
using System.IO; // ファイル操作のために必要
public class Gamemanager : MonoBehaviour
{
public static Gamemanager Instance; // シングルトンパターンのためのインスタンス
private string savePath; // セーブデータのファイルパス
void Awake()
{
if (Instance == null) // インスタンスが存在しない場合
{
Instance = this; // このインスタンスをセット
DontDestroyOnLoad(gameObject); // シーン遷移時も破棄しない
}
else // すでにインスタンスが存在する場合
{
Destroy(gameObject); // このオブジェクトを破棃
}
// セーブデータのパスを設定(プラットフォーム間で一貫性のあるパス)
savePath = Path.Combine(Application.persistentDataPath, "savedata.json");
}
[System.Serializable] // JSONシリアライズ可能にする
private class SaveData
{
public float[] playerPosition; // プレイヤーの位置を保存する配列
}
public void SaveGame(Vector3 playerPosition)
{
SaveData data = new SaveData
{
// Vector3をfloat配列に変換
playerPosition = new float[3] { playerPosition.x, playerPosition.y, playerPosition.z }
};
string json = JsonUtility.ToJson(data); // データをJSON文字列に変換
File.WriteAllText(savePath, json); // JSONをファイルに書き込み
Debug.Log("ゲームがセーブされました");
}
public Vector3 LoadGame()
{
if (File.Exists(savePath)) // セーブファイルが存在する場合
{
string json = File.ReadAllText(savePath); // ファイルからJSONを読み込み
SaveData data = JsonUtility.FromJson(json); // JSONをオブジェクトに変換
// float配列をVector3に変換して返す
Vector3 loadedPosition = new Vector3(data.playerPosition[0], data.playerPosition[1], data.playerPosition[2]);
Debug.Log("ゲームがロードされました");
return loadedPosition;
}
else
{
Debug.Log("セーブデータが見つかりません");
return Vector3.zero; // デフォルト位置として(0, 0, 0)を返す
}
}
}
シングルトンパターンを使用してGamemanagerのインスタンスと1つにしています。
今回は、プレイヤーの位置情報をJSONファイルにセーブします。そしてセーブした位置情報はJSONファイルから位置をロードします。
空のオブジェクト「GameManager」を作成してアタッチしておきます。
続いて、Cubeを動かしたいので「PlayerController」スクリプトを作成しましょう。
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed = 5f;
void Update()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0f, moveVertical);
transform.Translate(movement * moveSpeed * Time.deltaTime);
}
public void SetPosition(Vector3 newPosition)
{
transform.position = newPosition;
}
}
このスクリプトは、シンプルに入力を取得してTranslate関数を使ってCubeを動かすだけですね。
こちらはPlayerにアタッチしておきましょう。
最後に、ボタンの処理を管理する「UIManager」スクリプトを作成します。
using UnityEngine;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
public Button saveButton; // セーブボタンの参照
public Button loadButton; // ロードボタンの参照
public PlayerController player; // プレイヤーコントローラーの参照
void Start()
{
// ボタンにリスナーを追加
saveButton.onClick.AddListener(SaveGame);
loadButton.onClick.AddListener(LoadGame);
}
// セーブボタンが押されたときの処理
void SaveGame()
{
GameManager.Instance.SaveGame(player.transform.position);
}
// ロードボタンが押されたときの処理
void LoadGame()
{
Vector3 loadedPosition = GameManager.Instance.LoadGame();
player.SetPosition(loadedPosition);
}
}
シーン上に配置した各ボタンが押された時の処理をまとめています。
空のオブジェクト「UIManager」を作ってアタッチしておきます。
そして、UIManagerのインスペクターからそれぞれのボタンとプレイヤーを設定します。
ここまで出来たら、ゲームを実行して確認してみましょう。
こんな感じで、セーブしたい位置でセーブボタンを押して別の場所でロードするとセーブしていた位置にCubeが移動するかと思います。
注意点
- セキュリティ上の理由から、重要な情報は暗号化することをおすすめします。
- 大量のデータを扱う場合は、パフォーマンスに注意が必要です。