Módulo 5 — Colisiones y puntaje (25 min)¶
¿Qué vamos a lograr?¶
Que al destruir un enemigo de un disparo, se sumen puntos y se vean reflejados al instante en un marcador en la esquina de la pantalla.
5.1 Crear el GameManager (y por qué es un "Singleton")¶
Hasta ahora, cada vez que un script necesitaba usar otro (por ejemplo, PlayerController
necesitando el bulletPrefab), lo conectamos a mano arrastrándolo en el Inspector. Para
el puntaje vamos a usar un enfoque distinto: un Singleton, un único GameManager al
que cualquier script puede acceder desde código, sin que nosotros conectemos nada.
- En la Hierarchy, clic derecho > Create Empty. Renómbralo a
GameManager. - Arrastra el script
GameManager.cssobre él (todavía no le asignamos el campoTexto Puntaje, eso es el siguiente paso).
using UnityEngine;
using TMPro;
// Administra el estado general de la partida. Por ahora, solo el puntaje.
public class GameManager : MonoBehaviour
{
// Guardamos una única referencia estática a este GameManager (patrón "Singleton").
// Así, cualquier otro script puede sumar puntos con GameManager.instancia.SumarPuntos(...)
// sin que nosotros tengamos que arrastrar una referencia a mano en cada Inspector,
// como sí hicimos con bulletPrefab o firePoint.
public static GameManager instancia;
[Header("Puntaje")]
public TMP_Text textoPuntaje;
private int puntaje = 0;
void Awake()
{
instancia = this;
}
void Start()
{
ActualizarTextoPuntaje();
}
public void SumarPuntos(int cantidad)
{
puntaje += cantidad;
ActualizarTextoPuntaje();
}
void ActualizarTextoPuntaje()
{
textoPuntaje.text = "Puntaje: " + puntaje;
}
}
5.2 Crear el marcador de puntaje en pantalla¶
- En la Hierarchy, clic derecho > UI > Text - TextMeshPro. Si es la primera vez que
usas TextMeshPro en este proyecto, Unity va a ofrecer Import TMP Essentials —
acéptalo (es un paso único). Esto crea automáticamente un
Canvasy unEventSystemademás del texto. - Renombra el texto a
TextoPuntaje. - En su Rect Transform, ubícalo en la esquina superior izquierda (podés usar el selector de Anchor Presets y elegir la opción superior-izquierda).
- En el componente TextMeshPro - Text, escribe
Puntaje: 0como texto de prueba, y ajusta el tamaño de fuente para que se lea bien.
- Selecciona el GameObject
GameManagery arrastraTextoPuntaje(desde la Hierarchy) al campo Texto Puntaje del componenteGame Manager.
5.3 Definir cuántos puntos vale cada enemigo¶
using UnityEngine;
// Componente simple que solo guarda cuántos puntos vale destruir a este enemigo.
// Lo agregamos tanto a EnemyChaser como a EnemyShooter, para que la bala pueda
// preguntarlo sin necesitar saber de qué tipo de enemigo se trata.
public class EnemyPoints : MonoBehaviour
{
public int valorDePuntos = 10;
}
- Abre el prefab
EnemyChaser(doble clic enAssets/Prefabs/EnemyChaser) y arrastra el scriptEnemyPoints.cssobre él. Dejalo en10puntos. - Abre el prefab
EnemyShootery agrégale el mismo componenteEnemy Points. Como este enemigo es más peligroso (dispara), puedes subirle el valor a20.
Note
Al ser un componente separado (en vez de escribir el valor de puntos dentro de
EnemyChaser.cs y EnemyShooter.cs por separado), la bala va a poder preguntar
"¿cuántos puntos vale este enemigo?" sin importarle de qué tipo es.
5.4 Preparar la bala del jugador para impactar enemigos¶
- Abre el prefab
Bullet(doble clic enAssets/Prefabs/Bullet). - Add Component > Circle Collider 2D, con Is Trigger activado (igual que en la nave y los enemigos: queremos detectar el impacto, no que rebote físicamente).
El script Bullet.cs ya está actualizado con la lógica del impacto:
using UnityEngine;
// Controla el comportamiento de cada bala disparada por el jugador:
// se mueve hacia arriba y se destruye sola después de un tiempo.
public class Bullet : MonoBehaviour
{
[Header("Movimiento")]
public float moveSpeed = 12f;
[Header("Duración")]
// Cuántos segundos vive la bala antes de autodestruirse.
// Esto evita que queden balas acumulándose fuera de la pantalla para siempre,
// lo que iría gastando memoria de a poco.
public float tiempoDeVida = 2f;
void Start()
{
// Destroy(gameObject, segundos) programa la destrucción de este GameObject
// luego de que pase esa cantidad de segundos.
Destroy(gameObject, tiempoDeVida);
}
void Update()
{
// transform.Translate mueve el objeto en la dirección indicada.
// Vector3.up equivale a (0, 1, 0): hacia arriba de la pantalla.
transform.Translate(Vector3.up * moveSpeed * Time.deltaTime);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Enemy"))
{
// Le preguntamos al enemigo cuántos puntos vale (componente EnemyPoints)
// y se los sumamos al puntaje a través del GameManager.
EnemyPoints puntosDelEnemigo = other.GetComponent<EnemyPoints>();
if (puntosDelEnemigo != null)
{
GameManager.instancia.SumarPuntos(puntosDelEnemigo.valorDePuntos);
}
Destroy(other.gameObject);
Destroy(gameObject);
}
}
}
5.5 Probar todo junto¶
Presiona Play, dispara a los enemigos que van apareciendo, y confirma que:
- Al impactar a un enemigo, tanto la bala como el enemigo desaparecen.
- El marcador de puntaje sube (10 puntos por
EnemyChaser, 20 porEnemyShooter).
Checkpoint ✅¶
Al terminar este módulo, cada vez que una bala del jugador toque a un enemigo, ambos deberían desaparecer y el puntaje en pantalla debería aumentar según el tipo de enemigo destruido.



