Sistema de patrulla para NPC Enemigos (Provisorio)

Por GameDevTraum

Introducción

En este artículo voy a mostrar una solución para hacer que los personajes no jugables (NPC) en Unity patrullen por una ruta compuesta por una serie de puntos.

Primero vamos a ver cómo agregar la solución al prototipo de inteligencia artificial para enemigos. Luego voy a explicar cómo funciona este sistema de patrulla en sí para poder adaptarlo a cualquier proyecto.

El título PROVISORIO se debe a que estoy pensando en construir una mejor versión para la inteligencia artificial de los NPC Enemigos. Cuando el nuevo prototipo esté listo, esta solución cambiará para adaptarse.

Solución a pedido de Whinsekk 2.0. 😀

Video 1: Funcionamiento de la solución.

Más Soluciones

Instrucciones y Descargas

Paso 1: Descargar el prototipo de IA para NPC

En primer lugar descargar el prototipo de inteligencia artificial para enemigos, en el video se explica cómo funciona.

Prototipo Inteligencia Artificial NPC Enemigo

177 Descargas

Paso 2: Descargar el nuevo Script Enemigo

Luego descargamos el Nuevo Script Enemigo que incluye la función de patrullar.

Script NPC Enemigo que patrulla

39 Descargas

Paso 3: Agregar y configurar el nuevo Script en el Prototipo

Seleccionamos uno de los enemigos en la jerarquía y en el inspector vamos a desactivar el Script Enemigo anterior y le asignamos el nuevo, como vemos en la figura 1.

Fig. 1.a : Nuevo Script Enemigo aplicado a uno de los prefabricados del enemigo dentro del prototipo.

Los campos se pueden a rellenar se pueden tomar del Script Enemigo anterior, asignando manualmente cada elemento.

Los nuevos campos están bajo el título “Estado de Patrulla” en negrita, en la figura 1.

El Array Puntos de Ruta no es necesario asignarlo, lo coloqué ahí para saber que se habían encontrado las referencias de los puntos de ruta.

Para definir una ruta para el enemigo vamos a crear un empty GameObject que llamaré “RutaDePatrulla1”. En el interior colocaré más empty GameObjects en los puntos pertenecientes a la ruta de patrulla. En la figura 1.b llamé a estos puntos “1” y “2”, el nombre en sí no es importante, pero el orden en el que están si lo es.

IMPORTANTE: asegurarse de que los puntos están al nivel del suelo.

Una vez que la ruta está definida la asignamos al campo “Ruta de Patrulla” en el inspector del nuevo enemigo.

Fig. 1.b : Se usan Empty GameObject para definir la ruta del enemigo.
Fig. 1.c : Asignación de la ruta de patrulla al enemigo.

Concretamente lo que se hizo es agregar un nuevo estado que se llama “Patrullando” y que cuando está activado es porque el NPC comienza a caminar del punto en el que está al siguiente punto.

Al llegar se pone en estado de guardia por los segundos que indiquemos en la variable “tiempoDeGuardiaEnPunto”, luego pasará al estado de patrulla nuevamente e irá al siguiente punto.

¿Cómo funciona la solución?

Ahora vamos a ver cómo funciona el sistema de puntos de ruta. Si entendemos esto podremos aplicarlo a cualquier proyecto.

Campos

En primer lugar necesitamos un GameObject serializado que se llama “rutaDePatrulla”. Aquí asignaremos un GameObject cuyos hijos serán todos los puntos que el enemigo recorrerá.

Luego definimos un vector de objetos Transform que llamamos “puntosDeRuta”, este no es necesario que aparezca en el inspector, pero aún así le añadí SerializeField para saber si las referencias se habían encontrado correctamente.

El entero “puntoDeRutaIndex” es el que indica el punto de la ruta de patrullaje al que el NPC debe ir.

Por último el float “tiempoDeGuardiaEnUnPunto” es el tiempo que el NPC esperará en cada punto antes de pasar al siguiente.

En la figura 2 vemos los campos definidos.

Fig. 2: Campos necesarios para la solución del NPC Enemigo que patrulla.

Métodos

El método ObtenerPuntosDeRuta se utiliza para encontrar las referencias de todas las componentes Transform de los hijos del objeto “rutaDePatrulla”. En la figura 3 vemos este método definido.

Artículo: ¿Qué es un método en programación?

Fig. 3: Método ObtenerPuntosDeRuta perteneciente a la solución.

El método anterior hay que ejecutarlo al comenzar la partida. En la figura 4 muestro la ejecución del mismo en el método Start del nuevo Script Enemigo.

Fig. 4: Ejecución del método ObtenerPuntosDeRuta perteneciente a la solución.

Cuando el enemigo debe pasar de un punto al otro debemos incrementar el índice (entero “puntoDeRutaIndex”) para pasar al siguiente punto. En el caso de que estemos en el último punto del vector debemos pasar al punto en la posición 0, así que para eso se utiliza el segundo if definido en la figura 5.

Fig. 5: Ejemplo de cómo recorrer el vector de puntos de ruta.

Noten como en la figura 4 también se le dice al agente que vaya hacia ese punto (con la ejecución de “SetDestination”).

Elementos necesarios en la Jerarquía

Para la ruta dijimos que necesitamos un GameObject cualquiera y que los puntos que definen la ruta de patrullaje serán los hijos de este GameObject.

Se pueden definir todos los puntos que se quieran y el algoritmo definido en el método ObtenerPuntosDeRuta los encontrará y se ajustará automáticamente.

Fig. 6: Ejemplo de una ruta para el NPC Enemigo.

Fig. 7: Asignación de la ruta creada en la figura 6 al NPC enemigo.

Extras

En el video 1 se veía en el Editor unas líneas blancas que unían los puntos de la ruta de patrullaje como para mostrar el camino que el NPC sigue.

Esto se consigue con la ejecución dentro de Update del método “DibujarRuta” que se ve en la figura 8.

Fig. 8: Método auxiliar para dibujar en el editor el camino que seguirá el NPC enemigo.