Movimiento de personaje sobre hexágonos con seguimiento de cámara inteligente
En este segundo artículo vamos a ver cómo implementamos el sistema de movimiento para el personaje del jugador dentro de la cuadrícula de hexágonos. También explicamos cómo configuramos una cámara que lo sigue de forma inteligente, y se desacopla automáticamente si el jugador decide moverla manualmente.
Movimiento entre hexágonos adyacentes
Para que el personaje solo pueda moverse a tiles vecinos, usamos una función que calcula los vecinos adyacentes según el sistema odd-q offset:
public static Vector2Int[] GetNeighbors(Vector2Int coord)
{
int q = coord.x;
int r = coord.y;
Vector2Int[] evenQ = { ... };
Vector2Int[] oddQ = { ... };
return (q % 2 == 0) ? evenQ : oddQ;
}
Y en TryMoveTo
, verificamos que el destino sea vecino y que el tile sea navegable:
foreach (var neighbor in Character.GetNeighbors(currentCoord))
{
if (neighbor == targetCoord && HexMapManager.Instance.IsNavigable(targetCoord))
{
StartCoroutine(MoveToHex(...));
}
}
Movimiento suave con easing
El desplazamiento del personaje no es instantáneo, sino que se hace con una interpolación suave:
private IEnumerator MoveToHex(Vector3 targetWorldPos, Vector2Int targetHex)
{
Vector3 start = transform.position;
Vector3 end = targetWorldPos;
float elapsed = 0f;
while (elapsed < moveDuration)
{
float t = elapsed / moveDuration;
float easedT = easing.Evaluate(t);
transform.position = Vector3.Lerp(start, end, easedT);
elapsed += Time.deltaTime;
yield return null;
}
transform.position = end;
character.hexCoordinates = targetHex;
}
Cámara inteligente: seguir o no seguir
La cámara está controlada por un script CameraController
que permite:
- Seguir automáticamente al personaje si está en modo seguimiento.
- Desacoplarse si el jugador la mueve con WASD.
- Recentrarla manualmente con barra espaciadora.
if (!userOverride && IsPlayerControllingCamera())
{
DisableFollow();
}
if (followEnabled && followTarget != null)
{
FollowTarget();
}
Y cualquier clase puede pedir a la cámara que recentre al objetivo:
camController.RecentreOnTarget();
Delegando responsabilidades
Una parte importante del refactor fue mover toda la lógica de seguimiento y centrado a CameraController
. Esto nos permite que PlayerMovement
se mantenga simple:
yield return StartCoroutine(MoveSmoothlyTo(...));
camController.RecentreOnTarget();
La cámara decide si recentrar, con suavizado o instantáneo, y si reactivar el seguimiento.
En conjunto con el artículo anterior, esto nos deja con un sistema sólido, elegante y escalable de movimiento y navegación sobre la cuadrícula de hexágonos.