En esta conferencia, veremos el concepto de 'Huida'.
Es una técnica común utilizada en A. YO. por conseguir que un NPC se aleje de una ubicación.
La técnica se puede usar en cualquier tipo de NPC. En este caso, lo aplicaremos a nuestra multitud
en la que hemos estado trabajando. Matemáticamente, huir funciona así ... Un objeto o ubicación se introduce
en un entorno.
El NPC determina dónde está el objeto en relación con su propia posición. Luego calculan una nueva ubicación de objetivo
que está lejos del objeto.
En este caso, utilizaremos la dirección exactamente opuesta.
Esto se puede calcular usando el vector hacia el objeto y quitándolo de la posición de los NPC.
Con la nueva ubicación del objetivo,
el agente puede darse la vuelta y comenzar a dirigirse hacia él, y así ser alejado del objeto en cuestión. Otros factores que podemos
considerar son el "radio de influencia del objeto" y el "período de enfriamiento". El radio determina qué tan cerca debe
estar un PNJ de un objeto para verse afectado por él y el tiempo de reutilización es
cuánto tiempo huye el PNJ, antes de volver al comportamiento normal. Para implementar la huida en la multitud actual de tu
ciudad y llegar al punto en el que estoy ahora, deberás agregar un cilindro y hacer una prefabricación.
Entonces, lo que he hecho es ir a la Jerarquía y hacer clic con el botón derecho> Objeto 3D> Cilindro 'y no cambié
el tamaño del mismo, pero lo que hice fue hacer un material verde y conectarlo a ese cilindro.
Luego tomé ese cilindro de la Jerarquía y lo arrastré y lo solté en los Activos y eso creará una
prefabricación de ese cilindro para usted. Solo eliminaré mi segunda versión.
Ahora este cilindro no hace más que marcar la ubicación donde vamos a hacer clic.
Por lo tanto, necesitamos un código para colocar el cilindro en NavMesh, donde hacemos clic con el mouse.
Así que creemos un nuevo código C # y llamemos a eso 'DropCylinder', luego abrámoslo y
agregaremos este código.
Entonces, antes que nada, tenemos un objeto de juego expuesto al público que llamamos 'obstáculo'.
Aquí es donde pasaremos por nuestra prefabricada del cilindro.
Luego vamos a mantener una serie de todos los agentes que están en la escena y,
por lo tanto, en el Inicio, recopilaremos todos esos agentes al encontrar los objetos del juego que tienen
la etiqueta 'agente'.
Esto significa que tendrá que crear la etiqueta 'agente' y agregarla a sus personajes.
Entonces tengo mis personajes. Los puse en 'Multitud' y los dupliqué. Creé algunos de ellos. No tenga demasiados porque
cuanto más tenga, más lento se ejecutará, pero desea
lo suficiente.
Ahora, bajo esta 'Multitud', si solo hace clic en todos ellos, puede agregar una etiqueta de 'agente'.
Así que creé una nueva etiqueta llamada 'agente', con una 'a' minúscula y solo la configuré para todos los personajes que están
en la multitud.
Entonces, volvamos al código y esos agentes estarán sentados en esta matriz de 'agentes' y eso significa
que cuando soltamos el objeto, podemos enviar un mensaje a todos ellos diciendo que ese objeto
está allí. Es como
el Agent Manager que hemos tenido en conferencias anteriores. Ahora en la actualización es donde se probará el botón
del mouse para ver si está presionado y luego haremos un RaycastHit en el mundo desde la posición de la pantalla
usando la posición del mouse en la cámara principal.
Eso significa asegurarse de que su cámara esté etiquetada
como 'MainCamera'.
Así que recuerda dónde está eso ... vaya a
la cámara y la etiqueta debe ser 'MainCamera' aquí para que lo tome.
Ahora, estamos haciendo nuestro Raycast de física al mundo, descubriendo dónde impacta ... donde golpea, vamos a instanciar una
copia de nuestro cilindro.
Así que ese es el obstáculo, lo colocaremos en la ubicación del golpe y luego utilizaremos la
rotación predeterminada del prefabricado porque realmente no es tan importante.
Luego tenemos una declaración 'foreach' que solo recorrerá todos los agentes en la
escena y llamará a un método sobre ellos (que aún no hemos escrito), pero se llamará 'DetectNewObstacle'
y nosotros ' Le pasaré el hitInfo. punto, que es la ubicación de donde estamos colocando el cilindro.
Entonces, esto básicamente le dice a nuestro agente que hay un obstáculo que se está colocando y ahora es
su trabajo huir de él. Así que guarda eso ... le dará un pequeño error porque aún no hemos
escrito este DetectNewObstacle,
pero eso es lo que haremos a continuación.
Abra el script de AIControl y este es el script que debería haber adjuntado a cada agente en
la escena,
por lo que siempre es una buena idea crear uno y
luego duplicarlo para que no tenga que agregarlo. Mi código de AIControl es un poco diferente de lo que dejé
en la última conferencia, así que lo revisaré rápidamente y le mostraré los cambios.
En primer lugar, he creado este 'speedMult' en la parte superior aquí. Estaba incrustado en el código más abajo, como una variable local,
pero ahora
lo vamos a usar en un par de lugares diferentes.
Entonces, el objetivo ahora es tener 2 tipos diferentes de animaciones y 2 tipos diferentes de velocidad. Caminamos y también correremos,
de
modo que cuando se caiga el obstáculo y el personaje
huya, entonces queremos que huyan.
Así que pon eso en la parte superior. Luego,
he creado una función llamada 'ResetAgent' porque iba a restablecer la velocidad del agente aquí y allá, dependiendo de si estás huyendo o
si estás deambulando y, por lo tanto, es bueno tener todo
de esto en un solo lugar para que sea fácil cambiar y actualizar.
Ahora aquí puede ver en ResetAgent, cuando suceda, establecerá el multiplicador de velocidad en un valor aleatorio.
Antes, estaba haciendo esto y la función de Inicio para que el agente siempre tuviera la misma velocidad.
Ahora va a cambiar la velocidad
del agente cada vez que se reinicie.
Esa es una buena manera de hacer que sus personajes sean un poco más aleatorios en sus movimientos
para que no siempre estén a la misma velocidad para el mismo personaje.
Ahora, ahora tenemos la velocidad del agente establecida aquí.
Recuerde que es 2 por defecto en los caracteres, multiplicado por el valor de speedMult.
Entonces eso solo se asegura de que esté configurado en 2
y también estoy configurando la velocidad angular.
Si echas un vistazo a la velocidad angular predeterminada en el NavMesh Agent en uno
de tus personajes, verás que es 120.
La velocidad angular es qué tan rápido se dará la vuelta el personaje.
Ahora lo que quiero es aumentar eso cuando el personaje tiene que huir.
Entonces, quieres que vean algo de lo que tienes que huir y que giren muy rápido, así
que eso significa que debes aumentar la velocidad angular y eso también significa que cuando vuelvan a caminar, debes
volver a bajarlo .
Así que lo vuelvo a poner aquí a 120. En ResetAgent, cuando se
restablece, establecerá el valor de speedMult que está en el sistema de animación en speedMult y volverá a
configurar
la animación de caminata y luego haré un ResetPath aquí que borra la ruta actual que tiene el agente
calcula y básicamente lo vuelve a establecer en 0 para que pueda estar
listo para generar otra ruta en el sistema NavMesh.
Ahora, la función de Inicio ... lo que hace es más o menos lo que teníamos antes.
Entonces, toma todas las ubicaciones de objetivos en el
mundo, los agentes NavMesh, establece el destino en un valor aleatorio (este código
es exactamente el mismo código que antes, lo haré más grande para
que pueda verlo), ubicación aleatoria fuera de la matriz goalLocations, agarra el animador que está en el personaje y
luego también establece el desplazamiento de la caminata (para que no todos caminen en el tiempo entre sí) a un
valor entre aquí y luego ejecutamos el ResetAgent (que continuará y establecerá todos estos valores que están
aquí para nosotros).
Ahora en la Actualización, es lo mismo que teníamos antes, excepto que estamos haciendo un Agente de reinicio antes
de establecer el próximo destino.
Lo que eso significará es que si estamos corriendo hacia una ubicación porque estamos huyendo de
ella, entonces, una vez que la hayamos alcanzado, volveremos a caminar y tomaremos
otra ubicación de objetivo y seguiremos deambulando. alrededor. Las nuevas cosas que agregaremos para este código para facilitar la huida ...
En primer lugar, necesitamos un flotador, que será el 'detecciónRadio' y esa es la distancia desde 'donde se deja caer
el objeto' hasta 'qué tan lejos deben estar los agentes cercanos para poder escucharlo'.
Ahora si tiene eso bastante grande, entonces todos los agentes en el área responderán. Si es más pequeño, solo responderán los que
se encuentren en el 'dentro de 5', lo cual es bueno porque puedes tener una
pequeña distracción fugaz o puedes tener algo que es bastante grande como una distracción fugaz.
Luego, también necesitamos un flotador para el 'fleeRadius' y esto
es qué tan lejos quieres que los personajes huyan del objeto antes de que lo olviden y comiencen
a regresar y buscar una nueva ubicación de objetivo.
Así que configuremos eso en 10, en este caso.
Bien, ahora con eso, lo que vamos a hacer es crear ese método del que
hablé antes (DetectNewObstacle) que se llama desde la caída de los objetos en el otro script de clic.
Entonces el nuevo método se verá así.
Por lo tanto, será público porque se está llamando desde otro lugar y estamos pasando por
la posición del obstáculo que está cayendo en la escena.
Luego haremos una prueba de distancia de la 'posición del objeto' y la 'posición del agente'.
Ahora, si esto está dentro del radio de detección, entonces el agente reaccionará a él.
Si el agente va a huir, necesita determinar en qué dirección
va a huir, que está lejos de la posición del obstáculo y para determinar eso, es la
posición del agente menos la posición del obstáculo. Observe que luego lo estoy normalizando para que tenga un
vector de longitud de 1 y lo usaré como 1 para multiplicarlo por el fleeRadius, que puede ver aquí.
Entonces, es el fleeDirection para una longitud de fleeRadius, agregado a la posición actual del agente y
ahí será donde está el nuevo objetivo.
Ahora con esa nueva información de objetivos, podemos establecer el destino del
agente, pero de antemano, veremos si podemos llegar a esa ubicación.
Entonces podrías tener un agente. setDestination newgoal pero en este caso, es
posible que pueda calcular una ubicación que esté fuera de NavMesh del agente por completo o que no
sea del todo accesible y eso significa que aún desea que el agente intente llegar a
ella, si es posible.
Así que esta es una forma diferente de elaborar el camino.
Lo que hacemos es crear un objeto de ruta NavMesh y este objeto de ruta se puede calcular con
CalculatePath.
Entonces creamos este valor para la ruta y lo pasamos para calcular la ruta, dada la nueva posición del objetivo.
Ahora este camino mantendrá el camino que el agente va a seguir para llegar
a la meta, pero si solo puede hacer parte del camino o no puede hacerlo, puede probar
el camino. estado.
En este caso, si el camino. el estado no es igual a una ruta no
válida, entonces establecerá el destino al final de la ruta que se calcula. Entonces, la 'ruta' en sí misma termina con una matriz llamada 'esquinas' y esa es una matriz
de todos los puntos de referencia, esencialmente, que el personaje va a seguir a medida que avanza desde donde
está hasta su ubicación objetivo.
Ahora, si no puede llegar hasta la ubicación del objetivo, todavía tendrá esta matriz de esquinas, pero solo le
llevará una parte del camino, lo que significa que si obtiene el último valor en
la matriz de esquinas (que es esto uno aquí), entonces habrá llegado al final de la ruta
que se calculó, incluso si no ha llegado al objetivo exacto. Por lo tanto, hará que el agente se mueva al menos un poco lejos de donde
ha colocado el obstáculo.
En ese punto, configuramos la animación para que se ejecute y luego aceleramos el agente con el agente. velocidad y subimos la velocidad angular bastante alta porque
queremos que el agente gire muy rápido y luego se vaya
en la dirección completamente opuesta.
Muy bien, así que guárdelo y luego volveremos a la Unidad. Lo que tendrá que hacer para probar esto (puede ver que
he eliminado todos los edificios, duplicado mis agentes)
Tengo cuatro objetivos y los acabo de colocar en un cuadrado alrededor del área, por lo
que los agentes cuando presiono Reproducir simplemente voy a deambular aleatoriamente entre esos objetivos.
Ahora para configurar el clic para el cilindro, tenemos nuestro script DropCylinder aquí. Solo voy a agregarlo a la cámara
(arrastrarlo y soltarlo en la cámara).
Solo necesita estar en la escena para que se ejecute y luego ese script DropCylinder requiere nuestro cilindro prefabricado
que creamos antes.
Así que toma eso y déjalo allí. Ahora, cuando presionamos Reproducir, si dejamos caer un cilindro, verá que
los agentes huyen de él y luego regresan porque solo huyen lo más lejos que necesitan
para encontrar su ubicación objetivo y luego simplemente comenzarán a vagar.
de vuelta y buscando otros objetivos. Por lo tanto, todavía se mueven al azar alrededor
de esos 4 objetivos diferentes que se encuentran en estas 4 esquinas donde tienden a agruparse.
Bien, así que si quieres cambiar esto para que todos reaccionen, si volvemos a nuestro AIControl, vamos a la parte
superior aquí y si cambiamos esta detecciónRadius a 20, eso probablemente debería cubrir a
todos en esa escena. Guárdalo
Regrese y presione Reproducir. Cuando dejemos esto aquí, todos huirán.
Ahora todavía no están huyendo muy lejos porque solo tienes ese radio de 10 (o lo que sea que tengamos
allí) y puedes cambiar eso si quieres empujarlos directamente a los bordes de NavMesh.
Ahora es probable que, cuando esté haciendo esto, haya un agente extraño que aparentemente ignorará el obstáculo y
eso será porque en su script AIControl aquí abajo, donde está calculando el camino, puede ser posible
si tiene un muy, muy grande fleeRadius para tratar de calcular un nuevo objetivo que está tan
lejos del NavMesh actual que solo devolverá un camino no válido y realmente no
puede hacer nada al respecto.
Entonces tienes que vivir con eso.
La otra alternativa es que tendrías que programar manualmente como una parte 'más' para esto aquí, el agente
gira y sale en la dirección opuesta, lo que significa que luego pierdes el
control del agente y el agente ya no estará navegando. a través de NavMesh
y eso podría causarle problemas.
Entonces, depende de usted si desea hacer eso o no,
o simplemente está feliz de soportar el hecho de que eso no funciona.
De lo contrario, realmente debe asegurarse de que su fleeRadius estará dentro de NavMesh o al menos no
ridículamente lejos de NavMesh para que no calcule una ruta válida para usted.
Así es como hacer que tus NPC huyan de un espacio.
Esto está utilizando el método NavMesh, pero el cálculo del vector para huir y la nueva ubicación del objetivo es exactamente
la misma si desea implementar esto en su propio sistema de waypoint manual.
Simplemente crearía un nuevo waypoint sobre la marcha y le daría esa nueva posición de objetivo, con ese vector matemático que se
encuentra en este programa en particular.