Anular sprites en lugar de destruir objetos
Clase 18 de 31 • Curso de Desarrollo de Videojuegos para Móviles con Unity
Contenido del curso
Sprite Atlas y Generación de Caramelos
- 5

Sprite Editor y cámaras en Unity para móviles
11:53 min - 6

Sprites múltiples en Unity con slice automático
12:06 min - 7

Script base de Candy en Unity C#
10:57 min - 8

Configuración y Gestión del Tablero en Unity con C#
10:08 min - 9

Inicializar tablero 2D con bucles anidados
10:27 min - 10

Configuración de slice por tamaño en Unity
05:22 min - 11

Creación y Configuración de Tablero en Unity para Videojuegos
08:22 min - 12

Sprites aleatorios de prefabs en Unity
07:18 min
Diseño de Game Play
- 13

Arreglar bug de tripletes en tablero Candy Crush
12:33 min - 14

OnMouseDown para seleccionar caramelos
12:14 min - 15

Swap de caramelos sin mover GameObject
10:17 min - 16

Configuración de Física en Unity para Movimiento de Caramelos
13:30 min - 17

Detección y Eliminación de Coincidencias en Candy Crush
12:06 min - 18

Anular sprites en lugar de destruir objetos
Viendo ahora - 19

Caída en cascada para match-3 con corrutinas
13:23 min - 20

Generar caramelos sin crear matches accidentales
09:09 min - 21

Último bug visual: rebotes y recálculos
10:55 min
Retos finales
- 22

Diseño de Interfaz Gráfica en Unity para Videojuegos
11:20 min - 23

Variables autocomputadas en Unity GUI Manager
07:31 min - 24

Implementación de Singleton en Gestor de Interfaz de Usuario
08:13 min - 25

Corrutinas para pantalla Game Over sin interrupciones
06:55 min - 26

Multiplica puntuación con combos inteligentes
04:46 min - 27

Integra tres audios en tu videojuego de caramelos
01:47 min - 28

Animación y Destrucción de Caramelos en Videojuegos
02:00 min - 29

Menú principal para tu videojuego móvil
03:28 min
Cierre del curso
Domina la detección y limpieza de coincidencias en un juego tipo Candy Crush con Unity y C#. Aquí se construye un flujo claro con clearMatch y findAllMatches, se reduce código duplicado y se aplica una optimización clave en móvil: anular la parte visual en lugar de destruir objetos.
¿Qué resuelve clear match y por qué es clave en móvil?
clearMatch comprueba si, desde el caramelo actual, hay suficientes vecinos en una o varias direcciones para formar un match. Si los hay, anula la componente visual de todos los implicados en lugar de destruirlos.
- Usa una List
temporal para recolectar vecinos coincidentes. - Suma colecciones con AddRange en lugar de Add para eficiencia.
- Compara con el umbral de boardManager.minCandiesToMatch.
- Anula el sprite con null en cada caramelo afectado.
- Devuelve true si limpia, false si no hay match.
private bool clearMatch(Vector2[] directions)
{
List<GameObject> matchingCandies = new List<GameObject>();
foreach (Vector2 direction in directions)
{
matchingCandies.AddRange(findMatch(direction));
}
if (matchingCandies.Count >= boardManager.minCandiesToMatch)
{
foreach (GameObject candy in matchingCandies)
{
candy.GetComponent<SpriteRenderer>().sprite = null; // Optimización móvil.
}
return true;
}
else
{
return false;
}
}
¿Por qué es óptimo en móvil? Porque evita instanciaciones y destrucciones constantes. Anular el SpriteRenderer hace invisible el caramelo y permite la futura caída en cascada sin penalizar CPU y batería.
¿Cómo buscar todas las coincidencias con find all matches?
findAllMatches coordina la detección en horizontal y vertical. Primero se protege con una guard clause para no comparar si el caramelo ya no tiene imagen.
- Comprueba horizontalMatch con Vector2.left y Vector2.right.
- Comprueba verticalMatch con Vector2.up y Vector2.down.
- Si hay match en cualquiera, anula también el sprite del caramelo central.
public void findAllMatches()
{
if (renderer.sprite == null) return; // Guard clause.
bool horizontalMatch = clearMatch(new Vector2[] { Vector2.left, Vector2.right });
bool verticalMatch = clearMatch(new Vector2[] { Vector2.up, Vector2.down });
if (horizontalMatch || verticalMatch)
{
GetComponent<SpriteRenderer>().sprite = null; // El centro también desaparece.
}
}
¿Por qué no mirar direcciones opuestas?
Antes se consultaban vecinos en ambos sentidos dentro del mismo método. Ahora, al separar en horizontal y vertical, ya no hace falta duplicar consultas. El resultado: menos líneas, más claridad y mantenimiento sencillo.
¿Qué patrón de control evita errores?
El retorno explícito de true y false en clearMatch asegura que todas las rutas devuelvan valor. La guard clause en findAllMatches previene comparaciones inválidas si el sprite ya está null.
¿Dónde invocar find all matches tras el swipe?
La invocación correcta ocurre al gestionar el intercambio en onMouseDown. Se llama dos veces para cubrir ambos casos: cuando destruye el caramelo movido y cuando destruye el caramelo previo.
- Invoca en el caramelo previamente seleccionado antes de deseleccionarlo.
- Invoca en el caramelo actual tras el intercambio.
- Ambos son necesarios para no perder matches válidos.
void onMouseDown()
{
if (canSwipe)
{
swipeSprite();
previousSelected.findAllMatches(); // Caso 1: el anterior provoca el match.
deselectCandy(); // Deselección segura.
this.findAllMatches(); // Caso 2: el actual provoca el match.
}
}
Sugerencia práctica: comenta la llamada anterior o la posterior a findAllMatches (línea 68 o 70 en el guion original) y verifica cómo se pierden situaciones de destrucción. Así se evidencia por qué ambas llamadas son imprescindibles.
¿Qué resultados verás y qué falta por implementar?
- Con tres, cuatro o cinco alineados, todos se vuelven invisibles por la lógica de limpieza.
- Aún no caen en cascada. Falta programar el desplazamiento visual de piezas superiores para ocupar los huecos. No habrá gravedad física; se moverán sprites.
¿Te gustaría compartir cómo modularías la cascada o cómo estructurarías la actualización del tablero tras cada match?