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<GameObject> 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.
privateboolclearMatch(Vector2[] directions){List<GameObject> matchingCandies =newList<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.}returntrue;}else{returnfalse;}}
¿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.
publicvoidfindAllMatches(){if(renderer.sprite ==null)return;// Guard clause.bool horizontalMatch =clearMatch(newVector2[]{ Vector2.left, Vector2.right });bool verticalMatch =clearMatch(newVector2[]{ 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.
voidonMouseDown(){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?
Muchachos para los que se sienten un poco confundidos, hay que entender los conceptos y las reglas básicas del juego. Por eso, la etapa del Game Design es muy importante porque es la que nos va a guiar a medida del desarrollo sobre lo que tenemos que hacer o no en código.
Principalmente es entender que jugamos con dos objetos siempre, Caramelo A y Caramelo B. El caramelo A es aquel que tu seleccionas de primero y el caramelo B es aquel con el que vas a hacer el cambio. Conociendo esto, casi toda la lógica se mueve en base a ambos.
El caramelo A lo vas a distinguir porque siempre tiene el color sombreado. Cuando esta sombreado quiere decir que es nuestro PreviousSelected.
Las combinaciones de tres caramelos o más se pueden dar por el Caramelo A o por el Caramelo B, de acuerdo a la dirección en la que se mueva.
Importantísimo repasar el concepto de Estructuras de Datos. En este curso las utilizamos bastante, listas, arrays, etc. Un curso que podría recomendar de platzi para eso y donde se puede practicar bastante, es el curso básico de algoritmos.
Ayudense bastante con las herramientas de debugging. En este caso, es bueno apoyarse de la consola y emplear el método Debug.log().
Aquí les dejo una función que conseguí por internet para imprimir el data de un gameObject en la consola de Unity:
Hola @vcardozof, la verdad solo dios recuerda lo que hice hace 4 años en este codigo. Te dejo el repositorio por si te sirve de algo: https://github.com/leosavvy/Crush-Invaders
Creo que estamos llevando muy lejos la "optimizacion" para movil a costa de los efectos graficos del juego, esta bien que no te consuma bateria, pero quitandole todo ese magico de animaciones y efectos de transicion vas a hacer que el usuario se aburra demasiado rapido.
Hola Fenix, tal vez se vea un poco abrasador porque esta medio condensado en comparacion con otros cursos de la carrera y del profesor, te recomiendo te eches un vistazo a los cursos:
Tengan cuidado con el codigo que escriban dentro del update del script Candy, tomen en cuenta que hay un monton de Caramelos instanciados, corriendo esa linea tantas veces su pc pueda por segundo y al sobrecargar feo a unity probablemente se les desconfigure algo, en mi caso se me desconfiguro la opcion que desmarcamos en la configuracion de fisicas 2D y estuve 5 horas con el juego crasheado hasta que se me ocurrio revisar eso.
Intenté hacer el efecto cascada de los caramelos aplicando físicas (RigidBody a los caramelos y un piso para que no se caigan al vacío) pero me temblaban los caramelos y después se me complicaba el efecto swipe. Vamos a ver en la próxima clase como lo solucionan 🚀🚀