Guardar progreso en Unity con PlayerPrefs

Resumen

Guardar el progreso del jugador en Unity es una de esas funciones que parecen mágicas hasta que entiendes cómo funcionan. Con clases serializables, JSON y PlayerPrefs puedes hacer que tu juego recuerde lo que pasó antes de cerrarse, sin que el jugador tenga que apuntar nada en un papel.

Esta guía es para ti si ya manejas propiedades públicas y privadas en Unity y quieres dar el siguiente paso: comunicar componentes entre sí y persistir información entre sesiones de juego.

¿Cómo se comunican dos componentes en Unity?

La forma más directa de que un componente le hable a otro es mediante variables públicas que referencian al otro componente. En el ejemplo de la clase, tenemos a María (un cubo) y a Bob (una esfera), cada uno con su propio script.

María declara una variable pública de tipo Bob llamada esposo. En el inspector de Unity, ese campo aparece vacío hasta que le dices a quién apunta. Tienes dos formas de asignarlo:

  • Hacer clic en el círculo del campo y elegir el objeto de la escena que tenga el componente compatible.
  • Arrastrar directamente el objeto desde la jerarquía hasta el campo del inspector.

¿Para qué sirve el candado del inspector en Unity? Bloquea la vista del inspector en un objeto específico, así puedes arrastrar otros objetos sin perder de vista el script que estás configurando. Si arrastras objetos y el inspector cambia, probablemente olvidaste activar el candado.

Una vez referenciado, María puede modificar propiedades de Bob desde su propio script. Por ejemplo, en el método OnEnable, María asigna su antojo al campo almuerzo de Bob: esposo.almuerzo = antojo. Cuando activas el componente de María, Bob cambia su plan de lentejas a hamburguesas al instante [05:20].

¿Qué es OnEnable y cuándo se ejecuta?

OnEnable es un método de Unity que se ejecuta cada vez que el componente se activa. Si lo desactivas y lo vuelves a activar, el código dentro de OnEnable corre de nuevo, lo cual lo hace perfecto para inicializar valores o cargar datos guardados.

¿Qué es una clase serializable y cómo se convierte en JSON?

Una clase serializable es aquella que Unity puede convertir en un formato de texto plano para guardarla, enviarla o reconstruirla después. En el ejemplo, la clase Mascota es serializable y tiene tres campos: nombre, juguete preferido y un nivel de aburrimiento que, al llegar al 20%, hace que la mascota destroce un mueble [07:45].

El truco está en que cualquier objeto serializable puede transformarse en un JSON, que es básicamente una cadena de texto estructurada. Los JSON se usan en todas partes: páginas web los envían a servidores, servidores los devuelven a páginas web, y los videojuegos los usan para guardar estados.

Para convertir un objeto a JSON en Unity usas:

csharp jsonDePepito = JsonUtility.ToJson(pepito);

Esto te devuelve un string con el nombre, juguete y aburrimiento de la mascota. Para hacer el camino inverso, es decir, reconstruir el objeto desde el texto, usas el método genérico FromJson:

csharp if (jsonDePepito != "") { pepito = JsonUtility.FromJson<Mascota>(jsonDePepito); }

El if es importante porque si el string está vacío, no tiene sentido intentar deserializarlo.

¿Qué es un JSON en Unity? Es una cadena de texto que representa un objeto serializable. Permite guardar, enviar o reconstruir el objeto manteniendo todos sus valores originales.

¿Cómo persistir datos con PlayerPrefs?

Guardar el JSON en una variable está bien mientras el juego corre, pero en cuanto cierras Unity, ese dato se pierde. Aquí entra PlayerPrefs, una especie de base de datos clave-valor que vive en la memoria persistente del dispositivo y funciona en builds de Android, computadora y consolas [13:30].

PlayerPrefs acepta tres tipos de datos:

  • Strings con SetString y GetString.
  • Integers con SetInt y GetInt.
  • Floats con SetFloat y GetFloat.

Para guardar el JSON de la mascota en OnDisable:

csharp PlayerPrefs.SetString("MascotaDeMaria", jsonDePepito);

La clave (MascotaDeMaria) puede llevar tildes o espacios, pero la convención entre programadores es escribirla en PascalCase, sin espacios, para evitar errores y mantener consistencia.

¿Cómo leer un PlayerPrefs sin que arroje error?

Antes de leer una clave, necesitas confirmar que existe. Si intentas leer una clave inexistente, Unity puede comportarse de forma inesperada. Para eso usas HasKey:

csharp if (PlayerPrefs.HasKey("MascotaDeMaria")) { string json = PlayerPrefs.GetString("MascotaDeMaria"); pepito = JsonUtility.FromJson<Mascota>(json); }

Este flujo completo hace que cuando el jugador cierre el juego, abra de nuevo y María ya tenga a Pepito con su hamburguesa chillona y su nivel exacto de aburrimiento, igualito a como lo dejó.

¿Cómo borro los PlayerPrefs en Unity para hacer pruebas? Ve al menú Edit y selecciona Clear All PlayerPrefs. Esto reinicia toda la memoria persistente como si el juego se ejecutara por primera vez.

Conceptos y habilidades clave de la clase

Dominar estos elementos te da las bases para sistemas de guardado más complejos:

  • Comunicación entre componentes mediante variables públicas que referencian otros scripts [01:30].
  • Clases serializables como estructuras que Unity puede convertir a texto [07:00].
  • JsonUtility.ToJson y FromJson para convertir objetos a string y viceversa [09:40].
  • PlayerPrefs.SetString, GetString y HasKey para guardar y recuperar datos persistentes [13:50].
  • OnEnable y OnDisable como puntos de entrada y salida del ciclo de vida de un componente.

¿Qué tipo de progreso te gustaría guardar primero en tu juego: inventarios, posiciones de personajes o configuraciones del jugador? Cuéntame en los comentarios.