Contenidos
- Empezar por la UI, porque todo entra por los ojos
- Modificar la clase Item para soportar cantidades
- Clonar ítems para dividir pilas o soltarlos
- Persistencia: guardar también cuántos ítems hay
- Recoger objetos sin llenar el inventario de basura
- Drag and drop con apilado real
- Dividir pilas con clic derecho
- Soltar ítems al suelo sin duplicaciones raras
- Límite máximo por slot
- Un sistema pequeño por fuera, enorme por dentro
- Frequently Asked Questions
Hay un momento en casi cualquier juego con inventario en el que te das cuenta de que algo chirría. Coges cinco pociones y, de repente, has ocupado cinco ranuras distintas como si cada botella necesitara una suite presidencial. Funciona, sí. Pero se siente regular.
La solución natural es un inventario apilable. Es decir, que los objetos del mismo tipo se agrupen en una sola casilla mostrando cuántas unidades hay. Exactamente esa sensación tan satisfactoria de juegos como Resident Evil 4, donde el inventario no solo guarda cosas, sino que además transmite orden, claridad y control.
Vamos a construir ese sistema en Unity con C#, añadiendo desde la UI hasta la persistencia, pasando por la lógica de drag and drop, división de pilas con clic derecho y un límite máximo por slot. Es una mejora enorme para cualquier juego top down, RPG o survival.
Empezar por la UI, porque todo entra por los ojos
Antes de tocar la lógica, conviene resolver cómo se va a mostrar la cantidad de objetos. Cada ítem del inventario necesita un pequeño contador visual, normalmente colocado en la esquina inferior derecha.
La idea es simple:
- Crear un texto hijo dentro del prefab del ítem.
- Colocarlo anclado abajo a la derecha.
- Reducir su tamaño para que no invada el icono.
- Mejorar la legibilidad con sombra u outline.
Este último detalle parece menor, pero no lo es. Si el número puede aparecer sobre fondos claros u oscuros, necesitas contraste. Una práctica muy habitual en videojuegos es:
- Texto blanco con borde oscuro si el fondo puede ser claro.
- Texto oscuro con borde claro si el fondo puede ser oscuro.
Con eso ya tienes una base visual mucho más profesional. Y además el inventario empieza a parecerse a un sistema serio, no a una tabla de pruebas.
Modificar la clase Item para soportar cantidades
El cambio de verdad empieza en la clase que representa un ítem. Si antes cada objeto era único, ahora necesita saber cuántas unidades contiene.
La clase Item debe incorporar al menos:
- Un campo Quantity para la cantidad actual.
- Una referencia al texto de cantidad en pantalla.
- Un método para actualizar la visualización.
- Métodos para añadir y quitar unidades de la pila.
- Un método para clonar un ítem con una cantidad concreta.
La regla visual más elegante aquí es no mostrar nada si solo hay una unidad. Si tienes una sola poción, ver un “1” no aporta demasiado. En cambio, a partir de dos sí interesa enseñar el número.
Por eso, al actualizar el texto, conviene aplicar esta lógica:
- Si Quantity > 1, mostrar la cantidad.
- Si no, dejar el texto vacío.
Luego vienen dos métodos clave:
- AddToStack, que incrementa la cantidad y refresca la UI.
- RemoveFromStack, que elimina unidades con seguridad para evitar cantidades negativas.
Ese control de seguridad importa más de lo que parece. Si intentas quitar 7 unidades de una pila que solo tiene 5, no puedes permitir que el sistema termine con un valor absurdo como menos 2. Lo correcto es eliminar como máximo lo que exista.
Clonar ítems para dividir pilas o soltarlos
En cuanto quieres separar una pila en dos, o soltar parte de ella al escenario, necesitas clonar el objeto. No basta con mover referencias de un lado a otro.
Por eso conviene tener un método como CloneItem, que cree una copia del GameObject y le asigne una cantidad nueva. Así puedes, por ejemplo:
- Pasar de una pila de 5 a dos pilas de 3 y 2.
- Soltar una unidad al suelo y dejar el resto en el inventario.
- Reubicar cantidades parciales entre ranuras.
Todo eso gira alrededor del mismo principio: la cantidad ya no está implícita en cuántos iconos ves, sino explícita en una propiedad del objeto.
Persistencia: guardar también cuántos ítems hay
De poco sirve tener un inventario apilable si al guardar la partida se pierde la cantidad y al cargar reaparece solo una unidad. El sistema de guardado debe ampliarse para incluir ese dato.
Si tu estructura de persistencia tenía algo así como:
- ID del ítem
- posición del slot
Ahora necesita un tercer campo:
- Quantity
Además, es buena idea inicializarlo con valor 1 por defecto. Así, incluso si en algún contexto no se especifica la cantidad, el comportamiento seguirá siendo razonable.
Después hay que tocar dos procesos:
- Guardar, copiando la cantidad actual del ítem a la estructura de datos.
- Cargar, restaurando esa cantidad y refrescando el texto visible.
Este paso suele olvidarse y luego llegan los bugs fantasma. El inventario parece funcionar, pero al cargar partida todo vuelve raro. Y claro, toca perseguir espectros por media escena.
Recoger objetos sin llenar el inventario de basura
Hasta aquí la estructura de datos ya soporta pilas. Ahora hay que enseñarle al Inventory Controller a comportarse como toca.
La lógica de añadir ítems cambia por completo. Antes seguramente hacías esto:
- Buscar el primer slot vacío.
- Instanciar ahí el nuevo objeto.
Ahora el flujo correcto es:
- Comprobar si ya existe un ítem del mismo tipo en el inventario.
- Si existe, aumentar su cantidad.
- Si no existe, buscar un hueco vacío y colocarlo.
La comparación se hace usando el identificador del ítem. Si el ID coincide, entonces es el mismo tipo de objeto y se puede apilar.
Conviene además mantener comprobaciones defensivas:
- Que el ítem a añadir no sea nulo.
- Que el slot exista realmente.
- Que el slot contenga un currentItem válido antes de acceder a él.
Puede parecer excesivo, pero este tipo de programación a prueba de balas te ahorra una cantidad indecente de dolores de cabeza cuando el proyecto crece.
Drag and drop con apilado real
La parte más divertida llega cuando quieres que el arrastrar y soltar no solo intercambie objetos, sino que también permita fusionar pilas.
En el manejador de drag and drop hay que contemplar tres casos distintos al soltar sobre un slot:
- Si el slot está vacío, mover el ítem allí.
- Si el slot contiene un ítem diferente, hacer swap.
- Si el slot contiene el mismo ítem, sumar cantidades y destruir la copia arrastrada.
Ese tercer caso es el que convierte un inventario normalito en uno mucho más satisfactorio. Arrastras 3 pociones sobre una pila de 5 y, en lugar de intercambiarse, pasan a ser 8. Exactamente lo que uno espera.
Aquí también es importante recentrar correctamente el RectTransform al cambiar de padre, para que el icono no quede descuadrado dentro del slot.
Dividir pilas con clic derecho
Una vez puedes apilar, lo natural es querer hacer la operación inversa. Es decir, separar una pila.
Para eso viene de maravilla implementar IPointerClickHandler y usar el botón derecho del ratón. La lógica es bastante elegante:
- Comprobar que el ítem existe y que tiene más de una unidad.
- Calcular la mitad de la pila.
- Restar esa cantidad de la pila original.
- Clonar un nuevo ítem con esa cantidad.
- Buscar el primer slot vacío para colocar la nueva pila.
- Si no hay hueco, revertir la operación y devolver la cantidad al origen.
Es una funcionalidad muy potente porque permite reorganizar el inventario con mucha precisión. Y además deja abierta la puerta a sistemas más avanzados, como compartir munición, almacenar objetos en cofres o dividir recursos antes de venderlos.
Soltar ítems al suelo sin duplicaciones raras
Otro punto delicado es dejar caer objetos fuera del inventario. Si la pila tiene varias unidades, no quieres tirar todas de golpe necesariamente. Lo habitual es soltar una unidad y dejar el resto en la casilla.
Eso obliga a:
- Reducir la cantidad de la pila original.
- Instanciar un nuevo objeto en el mundo con cantidad 1.
- Destruir el icono de UI solo si realmente era la última unidad.
Además, hubo un ajuste muy fino para evitar un bug clásico: que el objeto caiga justo encima del jugador, se recoja inmediatamente y termine duplicándose. La solución fue mejorar la lógica de drop y colocar el objeto en una posición controlada, validando colisiones y evitando que aparezca en sitios imposibles o problemáticos.
Ese tipo de detalles son los que separan un sistema que “más o menos funciona” de otro que se siente robusto.
Límite máximo por slot
Y ya que estamos, se puede rematar el sistema con una mejora muy útil: definir una capacidad máxima por ranura.
Esto se implementa añadiendo a la clase Item una propiedad como MaxQuantity. Así cada objeto decide cuánto puede apilarse:
- 99 si quieres un inventario permisivo
- 50 para munición
- 5 para pociones
- 1 para objetos únicos
Después solo hay que comprobar ese límite en dos sitios:
- Cuando recoges objetos.
- Cuando intentas fusionarlos con drag and drop.
Si al sumar ambas cantidades se supera el máximo, no se apilan. Se mantiene el comportamiento alternativo, normalmente swap o creación de una nueva pila si el sistema de recogida lo permite.
Incluso puedes mejorar la UX cambiando el color del número cuando una pila ha alcanzado su tope. Un texto rojo comunica de un vistazo que ahí no cabe ni una unidad más.
Un sistema pequeño por fuera, enorme por dentro
Lo bonito de este tipo de mejoras es que, al principio, parece que solo estás añadiendo un numerito en una esquina. Pero en realidad estás transformando por completo la sensación del inventario.
Ahora tienes un sistema capaz de:
- Apilar objetos iguales.
- Guardar y cargar cantidades correctamente.
- Fusionar pilas al arrastrar.
- Separarlas con clic derecho.
- Soltar unidades al escenario.
- Respetar límites máximos por slot.
Y eso ya se parece mucho a un inventario avanzado en Unity, listo para un juego top down 2D con cara y ojos.
Si quieres profundizar y montar un proyecto completo paso a paso, puedes echar un vistazo al curso de Unity Top Down 2D. Y si te interesa seguir mejorando sistemas de este estilo, también te puede venir genial la ruta de cursos de Unity o la colección de desarrollo de videojuegos.
Cuando una arquitectura está bien pensada, añadir nuevas funciones deja de ser una pesadilla y se convierte en una gozada. Y eso, en desarrollo de videojuegos, vale oro.
Este artículo forma parte de una serie sobre desarrollo de videojuegos en Unity. Si quieres aprender a crear un juego Top-Down 2D completo, con movimiento, inventario, NPCs, diálogos y una arquitectura escalable, echa un vistazo al curso completo.
Frequently Asked Questions
¿Qué es un inventario apilable en Unity?
Es un sistema que agrupa varios objetos iguales en una única ranura del inventario, mostrando la cantidad disponible y optimizando el espacio.
¿Cómo crear un sistema de stacks en Unity con C#?
Debes añadir una propiedad de cantidad al objeto, actualizar la interfaz, modificar la lógica del inventario y gestionar correctamente el guardado y la carga de las pilas.
¿Cómo dividir una pila de objetos en Unity?
Puedes implementar un clic derecho sobre el objeto para separar parte de la pila, crear un nuevo ítem con esa cantidad y colocarlo en otra ranura libre.
¿Cómo establecer un límite de objetos por ranura?
Añade una propiedad como MaxQuantity a cada ítem y comprueba ese valor al recoger objetos o fusionar pilas para evitar superar el máximo permitido.
¿Qué ventajas tiene un inventario apilable en un videojuego?
Mejora la organización del inventario, optimiza el espacio disponible y ofrece una experiencia de usuario más cómoda en juegos RPG, survival y top-down.