Unity Project Guide: Save and Load a Checkpoint With JSON
Saving is one of the first systems that makes a prototype feel like a real game. This guide walks through a practical Unity save system using JSON.
You will save:
Player position
Player health
Last checkpoint id
Simple inventory item ids
This is not the final save architecture for every game, but it is a strong beginner-friendly foundation.
Step 1: Decide What Should Be Saved
Beginners often try to save entire GameObjects. Avoid that.
Save small, stable data:
TEXT
1Good to save:2- player position3- health number4- item ids5- quest ids6- checkpoint ids78Bad to save:9- GameObject references10- Transform components11- Sprite objects12- MonoBehaviour instances
GameObjects are runtime objects. Save data should be plain information that can be recreated.
Step 2: Create Save Data Classes
Create SaveData.cs.
CSHARP
1using System;2using System.Collections.Generic;34[Serializable]5public class SaveData6{7 public int version =1;8 public PlayerSaveData player =new PlayerSaveData();9 public List<string> inventoryItemIds =new List<string>();10}1112[Serializable]13public class PlayerSaveData14{15 public float x;16 public float y;17 public int health;18 public string checkpointId;19}
These classes are intentionally boring. Unity's JsonUtility works best with simple serializable fields.
Step 3: Create the Save Manager
Create SaveManager.cs.
CSHARP
1using System.IO;2using UnityEngine;34public class SaveManager : MonoBehaviour5{6 public static SaveManager Instance { get; private set;}78 private string SavePath => Path.Combine(Application.persistentDataPath,"save.json");910 private void Awake()11{12if(Instance !=null && Instance != this)13{14 Destroy(gameObject);15return;16}1718 Instance = this;19 DontDestroyOnLoad(gameObject);20}2122 public void Save(SaveData data)23{24 string json = JsonUtility.ToJson(data,true);25 File.WriteAllText(SavePath, json);26 Debug.Log($"Saved to {SavePath}");27}2829 public bool TryLoad(out SaveData data)30{31 data =null;3233if(!File.Exists(SavePath))34{35returnfalse;36}3738 string json = File.ReadAllText(SavePath);39 data = JsonUtility.FromJson<SaveData>(json);40return data !=null;41}4243 public void DeleteSave()44{45if(File.Exists(SavePath))46{47 File.Delete(SavePath);48}49}50}
Create an empty GameObject named SaveManager and attach this script.
Step 4: Capture Player Data
Create PlayerSaveAdapter.cs.
CSHARP
1using UnityEngine;23public class PlayerSaveAdapter : MonoBehaviour4{5[SerializeField] private Health health;67 private string currentCheckpointId ="start";89 public PlayerSaveData Capture()10{11returnnew PlayerSaveData12{13 x = transform.position.x,14 y = transform.position.y,15 health = health.CurrentHealth,16 checkpointId = currentCheckpointId17};18}1920 public void Restore(PlayerSaveData data)21{22 transform.position =new Vector3(data.x, data.y, transform.position.z);23 currentCheckpointId = data.checkpointId;2425// Add SetCurrentHealth to your Health component or restore through a proper method.26 Debug.Log($"Restore health to {data.health}");27}2829 public void SetCheckpoint(string checkpointId)30{31 currentCheckpointId = checkpointId;32}33}
Attach it to the Player and assign the Health component.
If your Health component does not support setting health yet, add a controlled method: