Lograr que un enemigo persiga al jugador es uno de los comportamientos más comunes en videojuegos, y la matemática detrás es mucho más sencilla de lo que parece. Usando conceptos de vectores, resta de posiciones y normalización, se puede implementar un movimiento fluido y controlable en pocos pasos dentro de Unity.
¿Qué es un vector director y cómo se calcula?
Para mover un objeto hacia otro, necesitamos conocer la dirección entre ambos. Cada objeto en Unity tiene un componente transform con su posición representada como un vector (X, Y). El enemigo tiene una posición inicial y el jugador una posición final [00:24].
El vector director es el vector que va desde el centro del enemigo hasta la posición del jugador. Se obtiene con una operación muy directa:
- Vector director = posición final (jugador) − posición inicial (enemigo).
- Este vector apunta siempre en la dirección correcta.
- Su magnitud es proporcional a la distancia entre ambos objetos.
Esto significa que si el jugador está muy lejos, el vector será grande y el enemigo se moverá más rápido. Si está cerca, el vector será pequeño y el movimiento será lento [01:07].
¿Por qué necesitamos un vector unitario?
Para evitar que la velocidad dependa de la distancia, se utiliza un vector unitario. Este se obtiene dividiendo el vector director entre su propia magnitud, lo que produce un vector que siempre mide exactamente una unidad [01:20].
- Mantiene la dirección hacia el jugador.
- Elimina la variación de velocidad por distancia.
- Permite multiplicar por una variable de velocidad (speed) para tener control total sobre qué tan rápido se mueve el enemigo.
¿Cómo implementar la persecución en Unity con C#?
Dentro de Unity, se crea una carpeta llamada Enemy en la sección de scripts y dentro de ella un nuevo C# script llamado EnemyMove [01:49].
Las variables principales del script son:
public Transform target: referencia al transform del jugador, es decir, el objetivo al que el enemigo se dirige.
private Rigidbody2D rb: componente de física 2D del enemigo.
public float speed: velocidad configurable desde el inspector.
Usando el atributo [RequireComponent(typeof(Rigidbody2D))], al agregar el script como componente en el GameObject, Unity añade automáticamente el Rigidbody2D si no existe [02:16]. En el método Start, se asigna el valor del Rigidbody2D con GetComponent<Rigidbody2D>().
¿Cómo se aplica el movimiento en el código?
El cálculo del movimiento se realiza dentro de FixedUpdate, que es el método recomendado para operaciones de física [02:46]:
csharp
void FixedUpdate()
{
Vector2 direction = (target.position - transform.position).normalized;
rb.velocity = direction * speed;
}
target.position - transform.position genera el vector director.
.normalized lo convierte en vector unitario, asegurando magnitud igual a uno [04:08].
- Multiplicar por
speed permite definir la velocidad constante desde el inspector de Unity.
¿Qué configuración se necesita en el inspector de Unity?
Una vez creado el script, se arrastra al GameObject del enemigo (por ejemplo, un avión rojo). Los pasos de configuración son:
- Establecer la escala de gravedad (Gravity Scale) del Rigidbody2D en cero, ya que el enemigo se mueve libremente por el cielo [03:10].
- Asignar el player como target en el campo correspondiente.
- Definir un valor de speed, por ejemplo
1.5 [04:35].
Al presionar play, el enemigo persigue al jugador de forma constante. Sin importar la distancia, la velocidad se mantiene uniforme gracias a la normalización del vector [04:55].
Este enfoque funciona muy bien en espacios abiertos donde no existen obstáculos que el enemigo deba esquivar. Si hubiera paredes u otros objetos en el camino, se necesitaría un sistema de pathfinding diferente [03:35].
¿Has probado agregar varios enemigos con distintas velocidades para crear oleadas? Comparte tu experiencia y cómo ajustaste los valores.