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.