Contenido del curso

Mecánica Principal

Corrutinas para animar piezas en Match 3

Resumen

Cerrar la mecánica principal de un Match 3 en Unity requiere dos detalles que marcan la diferencia entre un prototipo tosco y un juego pulido: animar la aparición de las piezas con un retraso controlado y bloquear el input del jugador mientras el tablero está en movimiento. Aquí verás cómo lograrlo usando corrutinas, IEnumerator y una variable booleana de estado.

¿Cómo crear piezas con retraso usando corrutinas en Unity?

La idea es sencilla: en vez de poblar el tablero de golpe, queremos que cada pieza aparezca con una pequeña pausa para dar sensación de animación.

En la clase Board declaramos una variable public float timeBetweenPieces = 0.05f. Ese valor controla cuánto esperamos entre la creación de una pieza y la siguiente [00:13].

Para que la espera funcione, la función SetupPieces deja de ser void y pasa a ser de tipo IEnumerator. Dentro del bucle agregamos:

csharp yield return new WaitForSeconds(timeBetweenPieces);

Así cada iteración pausa la ejecución antes de instanciar la siguiente pieza [00:32].

¿Qué es una corrutina en Unity? Es una función que puede pausar su ejecución con yield return y reanudarla después. Se usa para animaciones, esperas y procesos por pasos sin bloquear el juego.

¿Por qué validar si el espacio está desocupado antes de crear una pieza?

Si una casilla ya tiene una pieza, no debemos sobrescribirla. Por eso agregamos un if que consulta si pieces[x, y] es null. Solo cuando el espacio está vacío ejecutamos el código de creación dentro de ese if [00:55].

Al final de todos los for loops, cerramos con un yield return null. Esto le indica a Unity que la corrutina terminó y puede limpiarse de memoria correctamente [01:18].

¿Cómo se llama una corrutina desde Start?

No puedes invocarla como una función normal. En Start reemplazas la llamada directa por:

csharp StartCoroutine(SetupPieces());

Ese cambio es obligatorio cada vez que conviertes una función a IEnumerator [01:30].

¿Cómo rellenar el tablero después de un match en Match 3?

Cuando las columnas colapsan y ya no se detectan nuevos matches, el tablero queda con huecos. Toca repoblarlo.

Dentro de FindMatchesRecursively, cuando la cuenta de nuevos matches no es mayor a cero, agregamos un else. Ahí esperamos medio segundo con yield return new WaitForSeconds(0.5f) y volvemos a llamar a la corrutina SetupPieces para rellenar la cuadrícula [01:48].

Al probar en Unity, las piezas aparecen animadas, los matches se eliminan, las columnas colapsan y luego el tablero se rellena. Si la animación se siente lenta, basta con bajar los tiempos:

  • timeBetweenPieces de 0.05 a 0.01 segundos.
  • La espera previa al rellenado de 0.5 a 0.1 segundos.

Con esos ajustes la sensación de fluidez mejora notablemente [02:30].

¿Cómo bloquear el input del jugador mientras se animan las piezas?

Mientras el tablero mueve piezas, colapsa columnas, revisa matches y crea combos, el jugador no debería poder iniciar otro movimiento. Si lo permites, vas a coleccionar bugs difíciles de rastrear.

La solución reutiliza una variable que ya habíamos creado: swappingPieces. Funciona como una bandera de estado.

¿Para qué sirve la variable swappingPieces? Es un booleano que indica si el tablero está en medio de una animación. Mientras sea true, el juego ignora cualquier input del jugador.

¿Dónde colocar los if statements para ignorar el input?

En las funciones que reciben input del jugador (TileDown, TileOver y TileUp) agregamos una validación con el operador de negación:

  • En TileDown, ejecutar el código solo si !swappingPieces.
  • En TileOver, lo mismo: si swappingPieces es falso, recibe el input.
  • En TileUp, envolver el segundo if dentro de la misma condición.

Así los tres puntos de entrada quedan bloqueados durante la animación [03:25].

¿Cuándo cambiar swappingPieces a true y cuándo volverlo false?

El ciclo de vida de la bandera es claro:

  1. Al iniciar SwapTiles, asignamos swappingPieces = true.
  2. La bandera permanece activa durante todo el proceso de matches, colapsos y rellenado.
  3. En FindMatchesRecursively, justo después de llamar a StartCoroutine(SetupPieces()) para crear las piezas nuevas, asignamos swappingPieces = false.

Con ese flujo, el jugador queda bloqueado desde que mueve la primera pieza hasta que la cuadrícula vuelve a estar completa [04:00].

Ya tienes una mecánica principal de Match 3 funcional: animación de aparición con corrutinas, repoblado automático tras los matches y control de input para evitar errores. ¿Qué animación te gustaría agregarle primero a tu juego? Cuéntalo en los comentarios.