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 ids7Â 8Bad 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;3Â 4[Serializable]5public class SaveData6{7 public int version =1;8 public PlayerSaveData player =new PlayerSaveData();9 public List<string> inventoryItemIds =new List<string>();10}11Â 12[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;3Â 4public class SaveManager : MonoBehaviour5{6 public static SaveManager Instance { get; private set;}7Â 8 private string SavePath => Path.Combine(Application.persistentDataPath,"save.json");9Â 10 private void Awake()11{12if(Instance !=null && Instance != this)13{14 Destroy(gameObject);15return;16}17Â 18 Instance = this;19 DontDestroyOnLoad(gameObject);20}21Â 22 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}28Â 29 public bool TryLoad(out SaveData data)30{31 data =null;32Â 33if(!File.Exists(SavePath))34{35returnfalse;36}37Â 38 string json = File.ReadAllText(SavePath);39 data = JsonUtility.FromJson<SaveData>(json);40return data !=null;41}42Â 43 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;2Â 3public class PlayerSaveAdapter : MonoBehaviour4{5[SerializeField] private Health health;6Â 7 private string currentCheckpointId ="start";8Â 9 public PlayerSaveData Capture()10{11returnnew PlayerSaveData12{13 x = transform.position.x,14 y = transform.position.y,15 health = health.CurrentHealth,16 checkpointId = currentCheckpointId17};18}19Â 20 public void Restore(PlayerSaveData data)21{22 transform.position =new Vector3(data.x, data.y, transform.position.z);23 currentCheckpointId = data.checkpointId;24Â 25// Add SetCurrentHealth to your Health component or restore through a proper method.26 Debug.Log($"Restore health to {data.health}");27}28Â 29 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: