Save the Game
Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 25 of 50.
A save game is one object written as JSON. Put everything the save needs in a [System.Serializable] class, fill it from the game, and write JsonUtility.ToJson of it somewhere that outlives the game. This dungeon keeps the floor, the gold and the keys found:
[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 is a folder Unity gives the game on every platform, kept between games and through updates. Path.Combine joins it and a file name with the platform's separator. File.WriteAllText(path, text) writes the file, replacing an old one, File.Exists tells whether there is one, and File.ReadAllText reads it back (all three from System.IO). The game's own folder may be read-only, so saves go in persistentDataPath and nowhere else. Build the path in Awake or Start: Unity refuses persistentDataPath in a field initializer.
The save class holds only what the save needs, and the game copies values into it to save and out of it to load. A small save can go into PlayerPrefs instead of a file: PlayerPrefs.SetString("dungeon", json) and PlayerPrefs.GetString("dungeon") hold the same JSON. Save when something worth keeping happens, at a checkpoint or from a Save button: OnApplicationQuit runs on a normal quit, but a phone can close a game in the background without it.
Challenge
MediumThe explorer walks the island with the arrows, and Space plants a flag where the explorer stands. Make the island a saved game in the file island.json:
- In
IslandSave.cs, write a[System.Serializable]classIslandSavewith the public fieldsplayerPosition(a Vector3) andflags(aList<Vector3>). Save(), which the Save button calls, writes the explorer's position and the flags as JSON toisland.jsoninApplication.persistentDataPath.- In
Start(), ifisland.jsonexists, put the explorer back at the saved position and plant every saved flag again, withPlantFlagso that the flags are in the list for the next save.
Press Play, plant a few flags and click Save, then Stop and Play again. Then Check.
Try it yourself
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");
// Load island.json here
}
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);
}
// The Save button calls this
public void Save()
{
// Write the player's position and the flags to island.json
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Game Architecture in Unity
1Components, Not Hierarchies
Small ComponentsA Base Enemy ScriptAbstract ComponentsComponents Working TogetherRecap: Modular Turret10Project: Arena Survivor
The HeroEnemy Types