Menu
CoddyTech

ゲームを保存する

CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 31/64。

セーブデータは、JSONとして書き込まれる1つのオブジェクトです。セーブに必要なものをすべて[System.Serializable]クラスに入れ、ゲームから値を設定し、ゲーム終了後も残る場所にそのオブジェクトのJsonUtility.ToJsonを書き込みます。このダンジョンでは、階層、ゴールド、見つけた鍵を保存します。

[System.Serializable]
public class DungeonSave
{
    public int floor;
    public int gold;
    public List<string> keys;
}
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class Dungeon : MonoBehaviour
{
    public int floor = 1;
    public int gold;
    public List<string> keys = new List<string>();
    private string path;

    void Start()
    {
        path = Path.Combine(Application.persistentDataPath, "dungeon.json");
        if (File.Exists(path))
        {
            DungeonSave save = JsonUtility.FromJson<DungeonSave>(File.ReadAllText(path));
            floor = save.floor;
            gold = save.gold;
            keys = save.keys;
        }
    }

    public void Save()
    {
        DungeonSave save = new DungeonSave();
        save.floor = floor;
        save.gold = gold;
        save.keys = keys;
        File.WriteAllText(path, JsonUtility.ToJson(save));
    }
}

Application.persistentDataPathは、Unityが各プラットフォームでゲームに提供するフォルダーで、ゲームを終了した後も、アップデート後も保持されます。Path.Combineは、このフォルダーとファイル名をプラットフォーム固有の区切り文字で結合します。File.WriteAllText(path, text)は古いファイルを置き換えてファイルを書き込み、File.Existsはファイルがあるかどうかを知らせ、File.ReadAllTextはファイルを読み戻します(この3つはすべてSystem.IOに含まれます)。ゲーム本体のフォルダーは読み取り専用の場合があるため、セーブデータはpersistentDataPathに保存し、それ以外の場所には保存しません。パスはAwakeまたはStartで作成します。Unityでは、フィールド初期化子でpersistentDataPathを使うことはできません。

セーブ用クラスにはセーブに必要なものだけを入れ、ゲームから値をクラスにコピーして保存し、読み込むときはクラスからゲームに値をコピーします。小さなセーブデータなら、ファイルの代わりにPlayerPrefsに保存できます。PlayerPrefs.SetString("dungeon", json)とPlayerPrefs.GetString("dungeon")で、同じJSONを保持できます。残しておく価値のあることが起きたとき、チェックポイントで、または「保存」ボタンからセーブします。通常の終了時にはOnApplicationQuitが実行されますが、スマートフォンでは、バックグラウンドにあるゲームがその処理を実行せずに終了されることがあります。

challenge icon

チャレンジ

中級

island.json に島を保存します。

  1. IslandSave.cs で、public Vector3 playerPosition; と public List<Vector3> flags; を持つ [System.Serializable] クラス IslandSave を記述します。
  2. Start() で、path を Path.Combine(Application.persistentDataPath, "island.json") に設定します。
  3. Save() は、transform.position と flags を含む IslandSave を JSON として path に書き込みます。
  4. Start() で既存のファイルを読み込みます。位置を復元し、各フラグに対して PlantFlag を呼び出します。

「プレイ」を押し、旗を立てて「保存」を押し、「停止」してから「プレイ」を押すと、旗が戻っています。その後、「確認」を押します。

自分で試してみよう

using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.InputSystem;

public class Explorer : MonoBehaviour
{
    public GameObject flagPrefab;
    public float speed = 4f;
    private List<Vector3> flags = new List<Vector3>();
    private InputAction moveAction;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
        // ここで island.json を読み込む
    }

    void Update()
    {
        Vector2 input = moveAction.ReadValue<Vector2>();
        transform.Translate(new Vector3(input.x, 0f, input.y) * speed * Time.deltaTime);
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            PlantFlag(transform.position);
        }
    }

    void PlantFlag(Vector3 position)
    {
        flags.Add(position);
        Instantiate(flagPrefab, new Vector3(position.x, 0.5f, position.z), Quaternion.identity);
    }

    // Save ボタンから呼び出される
    public void Save()
    {
        // プレイヤーの位置と旗の情報を island.json に書き込む
    }
}

Unityのゲームアーキテクチャのすべてのレッスン

自分で練習してみよう: Unityプレイグラウンド