En esta conferencia, veremos cómo crear un sistema de puntos de referencia que
se pueda navegar con el algoritmo A *. Para comenzar, descargue el archivo de recursos que viene con esta conferencia y en ella encontrará
esta escena con el tanque.
Si ha hecho alguno de los otros tutoriales proporcionados por Unity, habrá visto estos modelos antes y los
uso con bastante frecuencia porque son agradables de ver y son convenientes y fáciles, por lo que no tenemos para
armar nuestro propio mapa.
Por supuesto, si desea armar su propio mapa, hágalo.
Esta bien.
Ahora tenemos un mapa y también tenemos un pequeño tanque.
El tanque será nuestro personaje NPC.
Lo que vamos a hacer es colocar algunos puntos de referencia alrededor del mapa y luego los enlazaremos con los bordes y colocaremos
algunos botones en la pantalla para dar órdenes al tanque de dónde ir. Lo primero que haremos es colocar algunos
puntos de referencia.
Lo importante a recordar aquí es que no hay detección física o de colisión en este proyecto, lo
que significa que debe colocar puntos de referencia donde el tanque pueda moverse.
Entonces serán los caminos. En el proyecto, he
creado un activo de objeto de juego WayPoint aquí.
Entonces, este prefabricado, si lo arrastro y lo dejo caer en la escena, verá que automáticamente se le asigna
un número
y cada vez que agrega un waypoint, contará para usted.
Esto es para que pueda realizar un seguimiento de qué waypoint es cuál, sin tener que hacer clic en él
en la Jerarquía cada vez.
Entonces, alejémonos. Voy a colocar algunos puntos de referencia alrededor de este
mapa para llegar
al helipuerto, que está aquí abajo y uno para llegar aquí y recorrer este edificio,
pero puedes colocarlos donde quieras. Así que seguiré adelante y lo haré rápidamente.
Con todos los puntos de referencia en su lugar, se convertirán en los nodos en nuestro gráfico.
Por lo tanto, ahora debemos determinar dónde estarán los bordes y los bordes son las líneas que conectan los nodos
y nos dirán dónde puede viajar el tanque.
Como dije al principio, estos puntos de referencia también van a especificar dónde no puede viajar el tanque,
por lo que no queremos poner ningún camino a través de la geometría.
Por lo tanto, también funciona como un sistema para evitar colisiones.
Puedes poner puntos de referencia como este a través de los edificios si quieres
que tus NPC viajen allí y parezcan inteligentes porque evitan los obstáculos.
Entonces, en este caso, podemos conectar el punto de referencia '1 con 2' y '2 con 3' y '1 con 3', en cualquier lugar donde
haya una línea de visión clara, podemos unirnos a ellos. Así que no podemos pasar de aquí al número 7 en la parte posterior, yendo por ese
camino.
Así que pondremos líneas aquí y aquí e incluso podría poner un camino unidireccional que vaya hasta aquí, de modo que
el tanque, si está por aquí y quiera regresar, tenga que dar la vuelta de esta manera.
Con todos sus caminos planeados, es posible que desee escribirlo para que tenga una
referencia de cuándo vamos y volver a poner esta información en Unity.
Ahora es el momento de comenzar
a crear algo de código, pero justo antes de hacerlo, necesitamos un objeto en la escena que gestionará todos los puntos de referencia.
Entonces, en la Jerarquía, haga clic derecho y Crear vacío y llamaremos a este objeto WPManager.
Así que este es nuestro administrador de waypoints. En eso, pondremos algo de código.
Así que vayamos al proyecto y creemos un nuevo script de C # y también lo llamaremos WPManager.
No importa si no son
lo mismo, solo me gusta mantenerlo consistente.
Ahora con ese WPManager, voy a arrastrarlo y soltarlo en nuestro objeto de juego vacío y
luego lo abriremos y comenzaremos a editarlo. Por encima de la clase WPManager, vamos a agregar una pequeña estructura
y eso está ahí para ayudar a facilitar la entrada de datos y el almacenamiento de nuestro gráfico.
El gráfico está yendo a otro sistema, pero aún necesitamos poder poner el gráfico en el WPManager de
alguna manera y la
forma más simple en este momento es hacer que el Inspector se
vea bien para facilitar esto, esencialmente.
Así que este es un enlace y un enlace será básicamente el borde.
Por lo tanto, define los nodos en cualquier extremo de un borde, la dirección del mismo y si es unidireccional, lo que significa que va en una dirección,
o si es bi, lo que significa que viaja en dos direcciones ... y eso se almacena aquí abajo en la
variable de dirección.
Entonces, solo hay tres cosas aquí esencialmente.
A continuación, definiremos los puntos de referencia, los enlaces y también haremos un gráfico a partir de ellos.
Entonces, en la parte superior aquí, agregue esto.
Entonces tenemos una matriz GameObject que contiene nuestros puntos de referencia.
Estas serán todas esas esferas que hemos colocado en nuestro mapa.
Luego tenemos una serie de enlaces, que también definiremos y esto nos permite
decir 'este se conecta a ese' y 'este se conecta a ese' y si puede
viajar en ambas direcciones o no y si
no hay enlace para waypoints, entonces obviamente no están conectados. Luego, con todo eso,
crearemos un nuevo gráfico de tipo 'Gráfico'.
Ahora el código gráfico y el algoritmo A * han sido escritos para usted y lo he provisto dentro de esta carpeta
'Gráficos' en Activos. Si echas
un vistazo allí, encontrarás 3 clases. Hay uno para Graph, uno para Node y otro para Edge, y todos
son muy elementales.
Por lo tanto, eche un vistazo a ellos, pero no entraré en detalles de su funcionamiento interno, excepto para
decirle que usan el algoritmo A *.
De vuelta en el código WPManager, trabajaremos en la función Inicio para configurar todo.
Así que aquí, solo agregue este código. Vamos a recorrer la matriz de puntos de referencia que está en la parte
superior y esta es la que alimentamos nuestros puntos de referencia manualmente.
Si hay puntos de referencia en esa matriz, vamos a recorrer cada uno y alimentarlo en nuestro gráfico
que hemos creado aquí.
El código del gráfico tiene un método AddNode y puede alimentar los objetos del juego hasta allí, por
lo que cada nodo debe existir.
Cada objeto del juego debe agregarse a ese gráfico antes de que pueda hacer algo con sus enlaces.
Después de eso, vamos a hacer lo mismo con los enlaces y
recorrerlos y usar el gráfico. Método AddEdge para crear un borde entre un nodo y el otro.
Ahora este AddEdge solo hace bordes unidireccionales (de manera unidireccional). Si el borde que hemos definido es bidireccional, entonces tengo una pequeña prueba
aquí solo para verificar que lo haya hecho bidireccional y, si es
así, agrega otro borde y simplemente intercambia los dos nodos.
Todo bien.
Entonces, eso es todo lo que necesita para construir el gráfico y ahora puede poner tantos puntos de referencia y definiciones de
borde en estas cosas a través del Inspector y
si lo construye todo por usted.
Ahora, una última cosa que será realmente agradable es si podemos ver los bordes porque ya podemos ver los nodos en
el mapa.
Pero si podemos ver los bordes, nos ayudará a depurar el programa. En el gráfico, tiene un
método debugDraw como ese. Si lo ponemos en la Actualización, entonces podemos ver los bordes que hemos creado.
Todo bien.
Así que guarde todo eso e iremos
a llenar el Inspector con nuestros nodos y bordes. En el WPManager
ahora encontrará Waypoints y Enlaces.
Entonces tenemos 11 puntos de referencia (así que pon 11 aquí para abrir eso) y estos son todos los puntos
de referencia separados y quiero que estén en orden.
Eso significa que necesito arrastrarlos uno por uno, así que lo haré rápidamente ...
Lo siguiente para completar son los enlaces. Tengo 13 enlaces y esa es la cantidad de rutas individuales
entre cada uno de sus nodos.
Así que pondré 13 allí, lo que expondrá todos los elementos.
Así que ahora voy a crear estos enlaces uno por uno.
El primer enlace que tengo es el que está entre el punto de referencia 1, aquí y el punto de referencia 2, allá abajo.
Así que agarraré el waypoint 1 de la Jerarquía y lo arrastraré hacia allí y el waypoint 2 hacia allí.
Ahora, si tiene un enlace unidireccional, que solo va en una dirección, entonces desea poner el nodo de inicio primero
y el segundo nodo a continuación. Con este ajuste en UNI,
solo dejará que el tanque vaya en esta dirección.
No podía volver de nuevo.
Así que voy a configurar eso en BI porque quiero que el tanque pueda ir y venir entre
esos dos.
El siguiente elemento que pondré, solo para mostrarle lo que está sucediendo con el enlace entre 8 y 9.
¿Recuerdas que dije que quería ponerlo solo en una dirección?
Así que quiero que pase de 8 (que será el primero) a 9 (que será el siguiente aquí) y
luego lo deje en unidireccional en lugar de cambiarlo.
Entonces solo irá en una dirección.
Muy bien, entonces revisaré y haré el resto
de estos y probablemente sea más fácil si tuvieras todo esto escrito en un papel como el que
tengo y luego puedes cruzar cada camino como lo has hecho , lo que lo hará mucho más simple.
Cuando creas que has terminado con todos tus caminos, puedes presionar Reproducir y luego volver a la vista
de Escena y podrás ver esos caminos.
Así que están dibujados donde has creado un enlace y puedes verlos allí.
Ahora, si te acercas un poco más, la línea o el borde tiene una marca azul al final.
Eso te muestra en qué dirección va.
En este caso, puede ver que hay una marca azul en ambos extremos de esa línea.
Eso significa que puede viajar hacia adelante y hacia atrás.
Ahora nuestro único unidireccional en este momento, si
vengo por aquí, es esta línea aquí y puedes ver allí (espero que puedas
ver, es bastante pequeña, ¿no? Déjame subir ... ) Entonces, tiene un poco de
azul y en el
otro extremo, no tiene azul, lo que significa que está viajando en esta dirección en
nuestra unidirección.
Entonces, si nuestro tanque termina aquí, la única forma en que podrá regresar a cualquier
lugar aquí es rodear este cobertizo o lo que sea.
Ok, ahora que tenemos nuestros puntos de referencia,
solo tenemos que informar a nuestro tanque sobre ellos.
Crearemos un código de manejo para el tanque.
Vaya a 'Crear> Script de C #' y llamaremos a este FollowPath y este código se basa en el código
MoveLocal que hemos usado antes.
Entonces, aquí vamos a agregar algo de código.
Lo pondré todo de una vez y luego lo revisaré contigo.
Okay.
Asi que aqui esta. Al igual que antes, tenemos una meta, pero esta vez
no está expuesta porque no la estamos pasando como algo que el NPC puede alcanzar.
El objetivo vendrá de nuestro algoritmo A *.
A continuación tenemos los sospechosos habituales.
Tenemos nuestra velocidad, precisión y velocidad de rotación, por lo que necesitamos esos valores nuevamente.
Después de eso, necesitaremos un valor expuesto al público para WPManager porque el WPManager contiene todos los puntos de referencia
y la información del gráfico y el NPC necesita saber sobre eso.
Así que lo pasaremos a este código en el Inspector. A continuación, estoy creando algunos valores locales, así que
aquí hay un 'wps', que tomará todos los puntos de referencia del administrador y luego tenemos un
GameObject que representa el nodo actual al que estamos tratando de llegar y eso, Supongo que, esencialmente, es nuestro objetivo en
cualquier momento en particular.
Después de eso hay un int llamado currentWP.
Ahora este es el índice del waypoint a lo largo del camino que estamos siguiendo.
Entonces, si vamos por un camino y digamos que hay tres puntos de referencia en él, entonces el
primer punto de referencia sería
0, el siguiente será 1 y el siguiente será 2.
Entonces, esto es solo para hacer un seguimiento de cómo nos hemos movido a lo largo del camino que
el algoritmo A * ha calculado para nosotros. No tiene nada que ver con la posición del punto de referencia en
nuestra matriz de puntos de referencia.
Entonces es una cosa completamente diferente.
Ahora, después de eso, también he declarado Graph y estas cosas, estos
'wps' y 'Graph' son solo para hacer nuestro código un poco más corto más adelante y verán por
qué inmediatamente porque en Start es donde configuro hacia arriba.
Si no tuviera estas dos cosas, tendríamos que escribir este código
cada vez que quisiéramos obtener algo del administrador de waypoints.
Entonces, es mucho más fácil asignarlo a estas variables aquí donde podemos obtenerlo.
Luego, necesitamos establecer el nodo actual que es este objeto del juego aquí que apunta al nodo físico, la esfera
del objeto del juego físico que está en nuestro mundo.
Esto está configurado en 7 en este caso porque mi tanque (si echamos un vistazo aquí) está cerca de 7.
En realidad NO está cerca de 7, estaba cerca de 7, ahora está cerca de 1.
Mis puntos de referencia se han vuelto a numerar.
Así que cambiemos eso a 0 porque para el punto de referencia 1 en la matriz, estamos posicionados en 0.
Entonces, sea cual sea el punto de referencia de su tanque, eso es lo que desea
para su inicio, por lo que tiene algún tipo de referencia sobre dónde se encuentra actualmente y luego cómo va a calcular cómo se
moverá a través del algoritmo A *.
Así que ese es el comienzo.
Ahora, después de eso, hay dos funciones a las que volveré ... Bajemos aquí.
Ahora, en LateUpdate, hay una declaración 'if'
que nos pregunta si la longitud de la ruta de nuestro gráfico (entonces if
(g. getPathLength ()
== 0) que esencialmente dice que no hay una longitud de ruta o que el índice del punto de ruta actual es igual a la
longitud de la ruta.
Si tienes una ruta con 3 nodos y estás hasta el tercer nodo y la longitud de tu ruta también
sería 3
porque tiene tres cosas.
Si estos dos son iguales, significa que estás al final.
Entonces, si tiene un camino vacío o está al final del camino, simplemente regrese.
No quieres seguir avanzando hacia ninguna meta porque no hay meta.
Después de eso, configuramos el nodo actual para obtener el punto de ruta en el valor del punto de ruta actual.
Entonces, si nos estamos moviendo a lo largo de un camino y estamos arriba para decir la posición número 3, entonces decimos que queremos el
tercer nodo a lo largo de este camino y nos dará el nodo físico al que debemos dirigirnos hacia aquí.
Después de eso, tenemos una declaración de 'si' muy familiar, que prueba nuestra precisión.
Entonces, si la distancia entre el tanque (que es esta transformación. posición) y el punto en el punto de referencia actual es menor
que nuestra precisión, entonces estamos lo suficientemente cerca como para haber alcanzado nuestro punto de referencia, al igual que los
otros algoritmos que ya hemos escrito.
En este caso, solo incrementamos el conteo actual a lo largo de nuestro camino y esto nos permitirá calcular el
siguiente punto y dirigirnos hacia el siguiente punto.
A continuación, estamos haciendo otra prueba para asegurarnos de que no hemos llegado al final del camino
(porque este código aquí arriba podría significar que hemos llegado al final del camino), entonces podemos mover nuestro tanque
hacia adelante y nosotros ' está moviendo el tanque usando el mismo código exacto (que es este aquí) que encontrará que desarrollamos en
nuestro script MoveLocal previamente para moverse y girar hacia un punto.
Entonces, esto es exactamente
lo mismo y el objetivo que estoy estableciendo para ser igual a la transformación de la esfera actual que está en
la posición 'currentWP' en la ruta.
Entonces exactamente el mismo código, el mismo tipo de movimiento.
Todo lo que estamos haciendo ahora es seguir un camino que nos dan los puntos de referencia en lugar de que le
demos al agente una posición para seguir porque está siguiendo algo en el mapa.
Por último (y porque me estoy quedando sin tiempo en este video de 20 minutos) necesita agregar estas dos
funciones públicas que le mostraré cómo usar en la próxima conferencia.
Son funciones públicas que podrían ejecutarse en el exterior, por lo que conectaremos botones en la pantalla hasta
estas.
Lo que están haciendo es ejecutar el algoritmo A *, por lo que este es el bit que hace todo el trabajo.
Si queremos ir al helipuerto, entonces el helipuerto está en el punto de referencia 2.
Todavía tengo mis viejos sistemas de waypoints aquí. El punto de referencia 2 será el punto de referencia 1 en la matriz
porque recuerde que las matrices comienzan a contar en cero.
Y la Ruina es el punto de referencia 7 para mí, que sería 6 en la matriz allí.
Por lo tanto, toma el nodo actual en el que se encuentra, el destino y lo ejecuta a través del algoritmo A * que
le dará la ruta que ahora se usa en LateUpdate. Después de cada una de las llamadas A *, asegúrese
de volver a establecer su contador de waypoints en 0, para que pueda comenzar en el punto 0
en el mapa y luego continuar.
Entonces ese es todo el código para FollowPath. Guarde eso y lo alcanzaré en la próxima conferencia, donde
implementaremos esto con algunos botones.