<html lang='es' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'></html> Scriptable Objects en Unity 3 - Variables Globales y Persistencia de Datos entre Escenas - Videojuegos con Unity

Scriptable Objects en Unity 3 - Variables Globales y Persistencia de Datos entre Escenas

Variables Globales y Persistencia de Datos entre Escenas

En las partes anteriores de esta serie vimos cómo almacenar datos estáticos con ScriptableObjects y cómo comunicar sistemas mediante eventos desacoplados. Hoy llegamos a una de las aplicaciones más potentes: Variables Globales y Persistencia de Datos entre Escenas usando ScriptableObjects.

Lo que aprenderás en la Parte 3:
  • Por qué las variables static en C# a veces se reinician o causan fallos al cambiar de escena.
  • Cómo crear una Variable Global reutilizable (FloatVariable o IntVariable) como ScriptableObject.
  • Cómo leer y escribir la vida o las monedas del jugador desde cualquier script y escena de forma limpia.


 

1. El problema del cambio de escena y las variables globales

Cuando cambias de una escena a otra en Unity (por ejemplo, de la escena de juego al menú de Game Over), los GameObjects de la escena anterior se destruyen y las variables locales mueren con ellos. Tradicionalmente se usa DontDestroyOnLoad, pero esto suele generar un caos de referencias duplicadas si el jugador reinicia el nivel.

Como los ScriptableObjects viven en los Assets del proyecto y no en la jerarquía de la escena, sobreviven al cambio de escenas de forma natural.

2. Paso 1: Creando el ScriptableObject de Variable (IntVariable)

Crea un script llamado IntVariable.cs. Este script almacenará un valor entero que persistirá de forma global:


using UnityEngine;

[CreateAssetMenu(fileName = "NewIntVariable", menuName = "ScriptableObjects/Variables/IntVariable")]
public class IntVariable : ScriptableObject
{
#if UNITY_EDITOR
    [Multiline]
    public string developerDescription = "";
#endif

    public int value;

    public void SetValue(int amount)
    {
        value = amount;
    }

    public void SetValue(IntVariable amount)
    {
        value = amount.value;
    }

    public void ApplyChange(int amount)
    {
        value += amount;
    }

    public void ApplyChange(IntVariable amount)
    {
        value += amount.value;
    }
}

3. Paso 2: Usando la Variable Global en el Jugador

Ahora, en lugar de guardar las monedas o la vida en una variable entera común dentro del script del jugador, usamos nuestro IntVariable. Crea o modifica tu script PlayerInventory.cs:


using UnityEngine;

public class PlayerInventory : MonoBehaviour
{
    [SerializeField] private IntVariable playerCoins;

    private void Start()
    {
        // Opcional: Reiniciar al iniciar la partida si es necesario
        // playerCoins.SetValue(0);
    }

    public void AddCoins(int amount)
    {
        playerCoins.ApplyChange(amount);
        Debug.Log($"Monedas totales: {playerCoins.value}");
    }
}

4. Paso 3: Mostrando el valor en la Interfaz de la UI (Cualquier Escena)

Crea un script llamado DisplayCoinsUI.cs y asígnalo a un componente de texto (TextMeshPro o UI clásica) en tu canvas. Como el ScriptableObject es global, funcionará exactamente igual tanto en el nivel de juego como en la pantalla de victoria/derrota:


using UnityEngine;
using TMPro; // O usa UnityEngine.UI si usas texto clásico

public class DisplayCoinsUI : MonoBehaviour
{
    [SerializeField] private IntVariable playerCoins;
    [SerializeField] private TextMeshProUGUI coinsText;

    private void Update()
    {
        if (coinsText != null && playerCoins != null)
        {
            coinsText.text = $"Monedas: {playerCoins.value}";
        }
    }
}

5. Configuración en el Editor de Unity

  1. Haz clic derecho en tu carpeta de proyecto: Create > ScriptableObjects > Variables > IntVariable y nómbralo PlayerCoinsData.
  2. Selecciona el archivo y, si quieres, escribe una nota en el campo de descripción para tener tu proyecto ordenado.
  3. Arrastra este archivo PlayerCoinsData tanto al componente del jugador como al script de la interfaz de usuario en tus diferentes escenas.
  4. ¡Listo! Ahora, cuando cambies de escena, el valor de las monedas se mantendrá intacto gracias a la persistencia del ScriptableObject.

6. Conclusión

Utilizar variables basadas en ScriptableObjects para el estado global del juego te ahorra escribir controladores globales gigantescos (Singletons) y previene errores molestos de referencias nulas al cambiar de escena.


¿Tienes alguna pregunta sobre cómo guardar estos datos en el disco duro (JSON / PlayerPrefs)? ¡Déjamela en los comentarios para una futura entrega!

No hay comentarios

Imágenes del tema: merrymoonmary. Con la tecnología de Blogger.