Hola. Bienvenido de nuevo a este tutorial sobre cómo crear una máquina de estados finitos NPC.
Hasta ahora, hemos creado la Patrulla para nuestro pequeño tanque verde.
Ahora creemos el Chase, sin embargo, antes de comenzar a hacerlo, quiero crear una Clase Base para nuestras máquinas de
estado porque necesitaremos información sobre dónde está el jugador y dónde está el NPC, para calcular distancias y
ángulos y cosas así, y podemos hacer eso en cada uno de los comportamientos de nuestra máquina de estado que
hemos agregado, pero tendremos que seguir haciéndolo una y otra vez.
Entonces, si creamos una Clase Base, podemos poner toda esa información en una sola vez.
Así que vamos a los Activos y nuestro proyecto. Crearemos otro script de C #, llamemos a
eso NPCBaseFSM.
Okay.
Ahora
abre eso y en él agregaremos este código.
Entonces, noten que no es un MonoBehaviour, es un StateMachineBehaviour y es NPCBaseFSM.
Dentro de aquí, voy a configurar un enlace a nuestro NPC y también uno para nuestro oponente y luego también estoy agregando
algunas propiedades de velocidad, velocidad de rotación y precisión también para que podamos cambiarlos a
nuestro gusto, en lugar de tenerlos codificados en el código anterior.
Ahora la función que realmente nos interesa anular y que estamos usando es OnStateEnter.
Entonces, cada vez que entramos en un estado, queremos agarrar al NPC y al oponente y notarás que el oponente
aquí está obteniendo un componente que está unido al NPC en sí llamado TankAI y escribiremos este bit en un momento, pero
esto se está apoderando del jugador y haremos que el personaje del tanque sepa sobre el jugador real,
para que pueda girar y disparar y moverse hacia él y ese tipo de
cosas.
Entonces esta es nuestra Clase Base y debido a que todavía no tenemos este script TankAI escrito, recibirá un
error que dice que no puede encontrarlo cuando lo guarda.
Así que vamos a escribir ese script TankAI ahora.
Entonces, de vuelta en nuestro proyecto, creemos otro archivo C # y lo llamaremos TankAI y lo
abrimos y en este código agregaremos esto.
Entonces, el comienzo de este script TankAI es que tiene un enlace al reproductor y
luego tenemos un método público llamado 'GetPlayer', que viste llamado antes, de nuestro código anterior y
que devolverá el 'jugador'.
Entonces podemos usar eso para calcular la distancia entre el tanque y el jugador un poco más adelante.
Así que guárdelo, regrese
a Unity, lo que quiere hacer con ese código es arrastrarlo y soltarlo en el tanque. Seleccione el tanque en la jerarquía
y verá el script adjunto.
Ahora tiene el espacio Player aquí, la variable expuesta que creamos.
Arrastre a su Jugador desde la Jerarquía a ese espacio, de modo que ahora que lo sabe y está vinculado a
él, podrá calcular su distancia.
Ahora con esa nueva Clase Base, necesitamos arreglar nuestra Patrulla, así que abre tu Patrulla
y en lugar de heredar de StateMachineBehaviour, vamos a heredar de NPCBaseFSM y eso incluirá nuestro NPC,
así que no necesitamos eso ... podemos eliminarlo desde adentro de aquí.
También podemos eliminar la configuración desde aquí porque ya va a suceder en nuestro OnStateEnter que está de
vuelta en nuestra Clase
Base, pero para garantizar que se ejecute, debemos llamarlo.
Así que agreguemos una línea de código y para volver a nuestras clases base OnStateEnter, llamamos base. OnStateEnter y pase a través de los
mismos parámetros que están llegando hasta aquí y que configurarán
nuestro NPC.
Ahora el NPC se usa en nuestro OnStateUpdate y ya está allí.
Las cosas que necesitamos cambiar
aquí, ¿recuerdan que agregamos precisión, velocidad y velocidad de rotación?
Entonces, en la rotación aquí, podemos poner nuestra rotSpeed allí (que proviene de esta clase, recuerda en la parte
superior.
Tenemos velocidad, velocidad de rotura y precisión) y esto va a ser velocidad y luego
nuestra precisión se usa aquí para determinar si necesitamos ir al siguiente punto de referencia, por lo que cambiaremos
eso a precisión.
Ahora, si usa esos valores para cualquier otra cosa en su código, puede
volver aquí y cambiarlos allí para su NPC.
En este punto, probablemente valga la pena guardarlo todo y simplemente probar que
todavía funciona, así que solo presionemos Reproducir y el código de Patrulla todavía funciona.
Muy bien, así que pasemos a hacer que nuestro estado Chase funcione. En su Animator, cree un nuevo estado.
Entonces, 'haga clic derecho> Crear estado> Vacío' y llamaremos a eso 'Chase', así
que vaya al Inspector y dele un nuevo nombre. Ahora 'Chase' pasará a Patrol, así que haga clic derecho en Patrol y vaya
a 'Realizar transición'.
Luego obtendrás una pequeña flecha con la que puedes hacer clic en otra cosa. Desea hacer clic en
'Chase'.
Esta es su
transición y si la selecciona, verá en el Inspector, un lugar donde podemos agregar nuestras condiciones.
La otra cosa a tener en cuenta aquí también es este 'Tiene tiempo de salida'. El tiempo de salida tiene que esperar hasta que la
patrulla haya
terminado lo que sea que esté haciendo en su actualización para pasar a Chase.
Ahora, si solo quiere que lo interrumpa por completo, deshágase de él, desactívelo y no esperará
eso.
Entonces, si descubre que tiene retrasos entre la transición, será porque todavía tiene este Tiempo de salida marcado
en todas sus transiciones y depende de usted si lo desea allí o no.
Ahora la condición para pasar de Patrulla a Chase, digamos que será cuando el jugador se encuentre
a una distancia de 20 unidades.
Entonces necesitamos un parámetro aquí para 'distancia'.
Entonces, en el Animador, a un lado, hay una Capa y hay una pestaña Parámetros. Desea hacer clic en Parámetros y luego hay un pequeño signo
+, haga clic en eso ... vamos a agregar un flotador.
Entonces agregue un flotador y lo llamaremos 'distancia'.
Inicialmente, queremos que el NPC esté muy lejos del jugador.
No queremos que esto se active de inmediato, por lo que si 'distancia' se establece en 0, se activará de inmediato.
Vamos a ponerlo en algo ridículo como 100 que está totalmente fuera del reino y luego
lo que hacemos aquí en la transición es hacer clic en él. En el Inspector, en Condiciones, presiona el + e
inmediatamente aparecerá la distancia porque eso es
lo único que sabe y luego 'Mayor' que 0. Estamos diciendo que esta condición es 'la distancia es inferior a 20'.
Entonces pondremos un 20 allí.
Entonces, cuando este valor llegue a menos de 20, la transición ocurrirá y comenzará el estado de Chase.
Lo siguiente que tenemos que hacer es actualizar cuál es esta
distancia aquí, de lo contrario nunca se reducirá
a menos de 20 y la distancia se basará en la distancia entre nosotros (nuestro jugador) y nuestro NPC.
Ahora puede calcular la distancia entre el jugador y el NPC dentro de su máquina de estado,
pero desea hacerlo una y otra vez y es una condición que se usa en toda
su máquina de estado y, por lo tanto, tiene sentido
hacerlo externamente para esto y
el código para eso irán en TankAI en su lugar. Hacerlo de esta manera también le mostrará cómo inyectar un valor de su MonoBehaviour
en el sistema de animación para que pueda cambiar esa condición.
En primer lugar, en el script TankAI, tendrá que agarrar el animador, por lo que crearemos un animador 'anim' en
la
parte superior aquí y luego en la función Inicio, configuraremos eso que apunta al Animador que está conectado a su objeto
de juego (o al tanque en este
caso), por lo que será anim = GetComponent para el Animador ... como eso.
Así que ahora tienes tu Animator configurado.
Ahora la distancia se calcula entre este objeto (el tanque) y el jugador que tienes aquí, por
lo que puedes inyectar eso en ese valor de 'distancia' en la Actualización, para que puedas calcular constantemente la
distancia y enviarla a la máquina de estado.
Entonces,
en Actualización, agreguemos este código ... y lo que está haciendo es tomar su Animator y llamar
al método SetFloat.
Lo que hará es establecer el valor de la distancia (asegúrese
de que esté entre comillas aquí y esté escrito exactamente igual que tiene su parámetro allí porque se refiere a
eso) y luego lo que ponga en la siguiente parte del método será el valor al que
va a cambiarlo.
Estoy usando un Vector3. Distancia para calcular la distancia entre la posición de nuestro
tanque y la posición del jugador.
Así que echemos un vistazo a cómo funciona esto.
Guarde eso y vuelva a Unity y presione Reproducir.
Ahora, si miras aquí a la distancia (mientras se está jugando), verás que cambia y eso es porque
el tanque se está moviendo.
También habrás notado que hubo una transición cuando esta distancia llegó a menos de 20.
Así que vamos a jugar eso de nuevo y solo mirarlo.
Así que voy a mover al jugador esta vez y cuando llegue a 20, la transición hacia Chase sucede y luego se
atasca en este Chase porque no tiene otro lugar a donde ir.
Tampoco hay código agregado como comportamiento allí, por lo que el tanque no va a hacer nada en absoluto, pero
sabemos que se activó porque lo vimos aquí y vimos que el tanque se detenía.
Así que es hora de agregar nuestro código de comportamiento Chase, así que seleccione Chase en su Animador y vaya al Inspector ...
haga clic en [Agregar comportamiento] ...
esta vez se llamará 'Chase', [Crear y agregar] y verás que Chase aparece en la parte inferior
y vamos a abrirlo y a Chase, vamos a abrir los mismos métodos que teníamos antes en
la Patrulla y agregue algún código en la Actualización.
Chase ahora se ve así (y
déjame sacar esto).
Solo te faltan en el
borde los corchetes, pero solo para que puedas ver el código por completo. Chase heredará de NPCBaseFSM para recoger los detalles sobre el
NPC y luego OnStateEnter llamará a nuestra base. OnStateEnter nuevamente, para configurarlo nuevamente porque recuerde,
no va a pasarlo de Patrol porque, en lo que a ellos respecta, ni siquiera
se conocen entre sí, por lo que no hay forma de
obtener eso a menos que lo obtenga de la base.
Ahora tenemos nuestro OnStateUpdate que hará todo el trabajo aquí y todo lo que
está haciendo es configurar el código Chase, que hará que el tanque gire hacia el jugador y siga al tanque del jugador.
Entonces, antes que nada, debes determinar cuál es la dirección entre el oponente (que es el jugador)
y el propio NPC.
Esa es la dirección.
Luego avanzamos en esa dirección usando nuestra velocidad de descomposición que tenemos dentro de nuestra Clase Base y luego ejecutamos
un Traslado aquí en función de la velocidad a lo largo del vector de avance del tanque.
Este código de movimiento aquí es más o menos el mismo que tenemos para girar hacia puntos
de referencia y empujar al NPC en esa dirección.
Todo bien.
Guarde todo eso y luego regrese a Unity y podemos probar esto.
Lo que debería suceder es que 'patrullaremos' hasta llegar a una distancia de
menos de 20 y luego comenzará la 'persecución' y en la persecución, el tanque seguirá siguiendo a nuestro jugador, así
que llevemos a nuestro jugador allí y
nosotros ahora estoy
en modo persecución y si sigo moviendo mi reproductor, verás que lo seguirá y lo seguirá para siempre porque no
hay forma de que vuelva a la Patrulla, pero eso se soluciona fácilmente porque
todos los El código está en su lugar para eso.
Entonces, dejemos de jugar y volvamos de Chase a Patrol, cuando la distancia sea mayor a
20, entonces queremos que el tanque regrese a Patrol.
Así que haga clic con el botón derecho en Chase, haga la transición y suelte la flecha en Patrulla,
seleccione la flecha
y luego pasemos al Inspector, desmarque 'Tiene tiempo de salida' y agregue la condición de 'distancia mayor que 20'.
Entonces ahora tenemos ... menos de 20
iremos de Patrulla a Chase y luego más de 20,
volveremos a patrullar y debido a que estos comportamientos de estado están configurados aquí, eso
es tan simple como parece.
Simplemente estamos inyectando la distancia constantemente desde nuestro TankAI
y la máquina de estado está haciendo el resto del trabajo. Entonces presionemos Play y moveré mi tanque.
Así que ahora estamos en modo Chase ... y el tanque seguirá y girará hacia mi jugador ...
pero luego si me alejo ... y más allá de 20, la patrulla volverá a entrar y el
tanque volverá a patrullar y recordará
que OnStateEnter for Patrol hace que el tanque regrese al primer punto de referencia cada vez en su configuración.
Bien, eso es lo que está configurando la persecución. En el siguiente
tutorial, veremos cómo agregar 'Ataque'.