1. Pon el estado guardado en una clase
No guardes GameObjects ni MonoBehaviours. Guarda datos simples: números, cadenas, vectores y listas. Una sola clase facilita versionar más adelante.
using UnityEngine;
[System.Serializable]
public class SaveData
{
public int version = 1;
public int coins;
public Vector3 checkpoint;
public Color playerColor = Color.white;
}2. Escribe y lee el archivo
Application.persistentDataPath apunta a una carpeta que sobrevive a las actualizaciones en todas las plataformas. Escribe primero en un archivo temporal y luego cámbialo, para que un fallo a mitad de escritura nunca corrompa la partida del jugador.
using System.IO;
using UnityEngine;
public static class SaveSystem
{
static string FilePath => Path.Combine(Application.persistentDataPath, "save.json");
public static void Save(SaveData data)
{
string tmp = FilePath + ".tmp";
File.WriteAllText(tmp, JsonUtility.ToJson(data, true));
if (File.Exists(FilePath)) File.Replace(tmp, FilePath, null);
else File.Move(tmp, FilePath);
}
public static SaveData Load()
{
if (!File.Exists(FilePath)) return new SaveData();
return JsonUtility.FromJson<SaveData>(File.ReadAllText(FilePath));
}
public static void Delete()
{
if (File.Exists(FilePath)) File.Delete(FilePath);
}
}3. ¿Archivo JSON o PlayerPrefs?
| Archivo JSON | PlayerPrefs | |
|---|---|---|
| Mejor para | Progreso del juego, inventarios, mundos | Ajustes: volumen, calidad, última pestaña del menú |
| Tamaño | Cualquier tamaño | Valores pequeños |
| Inspeccionar y hacer copia | Abre el archivo en cualquier editor | Oculto en el registro o en un plist |
| WebGL | Necesita sincronizar con IndexedDB | Funciona sin más |
Una configuración habitual es usar ambos: JSON para el juego, PlayerPrefs para los ajustes. Para guardar JSON en PlayerPrefs, llama a PlayerPrefs.SetString("save", json) y luego a PlayerPrefs.Save().
4. Decide cuándo guardar
- En eventos: recoger una moneda, llegar a un checkpoint, terminar una misión. El jugador nunca pierde más que un instante.
- Al salir:
OnApplicationQuityOnApplicationPause(true)en móvil, donde las apps se cierran sin aviso. - No en cada frame: escribir a disco es lento. Marca los datos como sucios y guarda una vez al final del frame o con un temporizador.
Conserva el campo version del paso 1. Cuando añadas campos en una actualización, las partidas antiguas siguen cargando: los campos que faltan reciben sus valores por defecto, y puedes migrar según el número de versión.
Sáltate la configuración: un sistema de guardado listo
El Sistema de Guardado y Carga para Unity es este patrón ya terminado: un controlador, una casilla JSON/PlayerPrefs, checkpoints, monedas, plataformas de color y un nivel de demostración, con todo el código C#. Combina bien con el Sistema de Inventario y el Personalizador de Personaje, que guarda atuendos de la misma manera.
Preguntas frecuentes
En Application.persistentDataPath. En Windows está bajo AppData/LocalLow/<empresa>/<producto>; cada plataforma tiene su ubicación.
JsonUtility es nativo y rápido, pero limitado (sin diccionarios ni propiedades). Newtonsoft Json.NET maneja tipos complejos; Unity lo distribuye como el paquete com.unity.nuget.newtonsoft-json.
No puedes impedirlo del todo en su máquina. En juegos de un jugador suele estar bien; si importa, añade un checksum o cifra el archivo.
Quién lo escribió
Imersa Studios crea los sistemas Unity, los packs low poly y las guías que se venden en itch.io. El código y las técnicas de aquí salen de publicar esos productos. Más sobre el estudio.

