Cómo crear NPCs con movimiento aleatorio

Clase 42 de 60Curso Avanzado de Creación de RPGs con Unity

Resumen

Aprende a configurar NPCs (Non-Player Character) en Unity con un flujo sencillo y efectivo. Reutiliza sprites, configura colisiones y física, y programa un movimiento errático aleatorio con pausas para simular vida en un RPG. Sin animaciones adicionales y con pocas líneas de código, obtendrás resultados claros y escalables.

¿Cómo crear un NPC en Unity con movimiento aleatorio?

Coloca en escena un sprite existente y distínguelo del personaje con un tinte de color. La idea es reutilizar gráficos (por ejemplo, un conejo) y evitar animaciones: el NPC no rota ni anima, solo se desplaza en cuatro direcciones.

  • Reutiliza el sprite del personaje y aplica un color distinto para identificar al NPC.
  • Nómbralo de forma genérica (por ejemplo, “NPC”) para crear luego un prefab reutilizable.
  • El movimiento será aleatorio en 4 direcciones (sin diagonales) y con pausas intercaladas.

¿Cómo definir variables clave para el movimiento?

Gestiona velocidad, estados y tiempos con contadores. Usa Vector2 para las direcciones.

  • Velocidad: public float speed = 1.5f;.
  • Estado: public bool isWalking para saber si camina o espera.
  • Tiempos: public float walkTime; public float waitTime = 3f;.
  • Contadores: private float walkCounter; private float waitCounter;.
  • Física: referencia a Rigidbody2D como npcRigidbody.
  • Direcciones: arreglo de Vector2 con las cuatro direcciones cardinales.

¿Qué lógica alterna caminar y esperar?

Alterna entre caminar y esperar con contadores que decrecen con Time.deltaTime. Selecciona dirección con Random.Range(0, 4).

  • Al iniciar caminar: activa isWalking, elige currentDirection y ajusta walkCounter.
  • Al parar: desactiva isWalking, reinicia waitCounter y pone la velocity a cero.
  • En Update: si camina, mueve según dirección por speed. Si espera, queda en reposo.
using UnityEngine; public class NPCMovement : MonoBehaviour { public float speed = 1.5f; public bool isWalking; public float walkTime; // editable en el editor. public float waitTime = 3f; // pausa entre movimientos. private float walkCounter; private float waitCounter; private Rigidbody2D npcRigidbody; private Vector2[] walkingDirections = new Vector2[] { new Vector2(1, 0), // derecha new Vector2(0, 1), // arriba new Vector2(-1, 0), // izquierda new Vector2(0, -1) // abajo }; private int currentDirection; // 0..3 void Start() { npcRigidbody = GetComponent<Rigidbody2D>(); waitCounter = waitTime; walkCounter = walkTime; } void Update() { if (isWalking) { walkCounter -= Time.deltaTime; npcRigidbody.velocity = walkingDirections[currentDirection] * speed; if (walkCounter < 0f) StopWalking(); } else { waitCounter -= Time.deltaTime; npcRigidbody.velocity = Vector2.zero; if (waitCounter < 0f) StartWalking(); } } private void StartWalking() { isWalking = true; currentDirection = Random.Range(0, 4); walkCounter = walkTime; } private void StopWalking() { isWalking = false; waitCounter = waitTime; npcRigidbody.velocity = Vector2.zero; } }

¿Qué componentes y ajustes evitarán problemas de física y render?

Para que el NPC se comporte bien en escena, combina colisión, física y orden de render.

  • Colisión: añade un BoxCollider2D un poco más grande de lo habitual.
  • Física: añade Rigidbody2D y configura:
    • gravityScale en 0 para evitar caída.
    • Bloquea la rotación en eje Z para que no gire con choques.
  • Render: usa la misma sorting layer y order in layer que el personaje, con z = 0.

¿Cómo evitar que el jugador empuje al NPC?

Si al chocar el jugador lo mueve, aumenta la masa del NPC para resistir empujes.

  • Aumentar masa dificulta el arrastre por colisiones.
  • Alternativa posible: definir capas sin colisión entre jugador y NPC.

¿Qué buenas prácticas mejoran la escalabilidad del sistema?

Pequeñas decisiones aceleran el trabajo y reducen errores al crecer el proyecto.

  • Crea un prefab del NPC para replicarlo con la misma lógica y parámetros.
  • Mantén nombres claros: npcRigidbody, walkCounter, waitCounter, walkingDirections.
  • Controla errores al autocompletar variables con nombres similares (por ejemplo, waitTime vs walkTime).
  • Ajusta walkTime y waitTime desde el inspector para tunear el ritmo del mundo.
  • Recuerda: el motor de físicas mueve al NPC al asignar velocity; no multipliques por Time.deltaTime en ese caso.

¿Te animas a ampliar el comportamiento, añadir diálogos o más gráficos para tus habitantes? Cuéntame qué misiones te gustaría que entregaran tus NPCs.