Scriptable Objects Unity 4 ¿Cómo poder estructurar un inventario basado en listas de ScriptableObjects?

 ¿Cómo poder estructurar un inventario basado en listas de ScriptableObjects?

En las entregas anteriores de nuestra serie sobre ScriptableObjects aprendimos a estructurar datos de armas, crear sistemas de eventos desacoplados y manejar variables globales entre escenas. Hoy aplicaremos todo esto para construir un Sistema de Inventario Modular y Base de Datos de Ítems completamente escalable.

Lo que aprenderás en la Parte 4:
  • 1º) Cómo crear una clase base abstracta o genérica para diferentes tipos de ítems (Pociones, Armas, Llaves).
  • 2º) Cómo estructurar un inventario basado en listas de ScriptableObjects.
  • 3º) Cómo programar un objeto interactivo en el mundo (Pickup) que entregue el ítem al jugador con una sola línea de código.



 


1. Paso 1: El ScriptableObject Base para los Ítems (ItemData)

Crearemos un ScriptableObject base que defina las propiedades comunes de cualquier objeto del juego (nombre, descripción, icono y tipo). Crea un script llamado ItemData.cs:


using UnityEngine;

public enum ItemType { Potion, Weapon, Key, Material }

[CreateAssetMenu(fileName = "NewItem", menuName = "ScriptableObjects/Inventory/ItemData")]
public class ItemData : ScriptableObject
{
    [Header("Configuración del Ítem")]
    public int id;
    public string itemName;
    [TextArea(3, 5)] public string description;
    public Sprite icon;
    public ItemType itemType;
    
    [Header("Apilamiento")]
    public bool isStackable;
    public int maxStackSize = 99;
}

2. Paso 2: El Contenedor del Inventario (InventoryData)

En lugar de guardar los ítems dentro de un script de componente en el jugador, crearemos un ScriptableObject que actúe como la mochila o inventario global. Crea un script llamado InventoryData.cs:


using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class InventorySlot
{
    public ItemData itemData;
    public int stackSize;

    public InventorySlot(ItemData item, int size)
    {
        itemData = item;
        stackSize = size;
    }

    public void AddToStack(int amount)
    {
        stackSize += amount;
    }
}

[CreateAssetMenu(fileName = "Inventory", menuName = "ScriptableObjects/Inventory/InventoryData")]
public class InventoryData : ScriptableObject
{
    public List container = new List();

    public void AddItem(ItemData item, int amount)
    {
        bool hasItem = false;

        // Si es apilable, buscamos si ya existe en el inventario
        if (item.isStackable)
        {
            foreach (var slot in container)
            {
                if (slot.itemData == item)
                {
                    slot.AddToStack(amount);
                    hasItem = true;
                    break;
                }
            }
        }

        // Si no existe o no es apilable, creamos una nueva ranura
        if (!hasItem)
        {
            container.Add(new InventorySlot(item, amount));
        }
        
        Debug.Log($"Añadido al inventario: {item.itemName} (Cantidad: {amount})");
    }

    public void ClearInventory()
    {
        container.Clear();
    }
}

3. Paso 3: El Objeto Recogible en el Mundo (ItemPickup)

Ahora creamos un script físico que se colocará en los cofres o en los objetos tirados en el suelo del escenario. Crea un script llamado ItemPickup.cs:


using UnityEngine;

public class ItemPickup : MonoBehaviour
{
    [SerializeField] private ItemData itemToPickup;
    [SerializeField] private int amount = 1;
    [SerializeField] private InventoryData playerInventory;

    private void OnTriggerEnter2D(Collider2D collision) // Usa OnTriggerEnter si es 3D
    {
        if (collision.CompareTag("Player"))
        {
            if (playerInventory != null && itemToPickup != null)
            {
                playerInventory.AddItem(itemToPickup, amount);
                Destroy(gameObject); // Destruimos el objeto del suelo al recogerlo
            }
        }
    }
}

4. Configuración en el Editor de Unity

  1. Haz clic derecho en tu carpeta de proyecto: Create > ScriptableObjects > Inventory > InventoryData y nómbralo PlayerInventory.
  2. Crea tus primeros ítems haciendo clic derecho: Create > ScriptableObjects > Inventory > ItemData (por ejemplo, crea una poción de vida y una llave dorada).
  3. Configura los valores de cada ítem en el Inspector (marca `Is Stackable` si deseas que se acumulen).
  4. Crea un Prefab en tu escena para representar el coleccionable, asígnale un collider con *Is Trigger* activo, colócale el script ItemPickup y arrastra tu ítem junto al inventario del jugador.

5. Conclusión

Gracias a este enfoque, la lógica del inventario queda completamente desacoplada de la interfaz gráfica y de las reglas de movimiento del jugador. Para mostrar el inventario en pantalla, simplemente puedes leer la lista container desde un script de UI sin alterar las mecánicas de recolección.


¿Te gustaría ver en la Parte 5 cómo conectar este sistema visualmente a una interfaz de cuadrícula (Grid UI) con casillas? ¡Déjamelo saber en los comentarios!

No hay comentarios