Para hacer un mundo complejo, necesitará agregar más agentes y también necesitará
agregar otros inventarios.
Actualmente, los inventarios que hemos creado están viviendo con el agente particular (en este caso, es solo
el Baker).
Así que está haciendo un seguimiento de cuánta harina hay en el mundo y cuánto pan hay
en el mundo, pero para que realmente pueda ir a recoger el pan del molino, necesita saber si hay
harina en el molino y, por lo tanto, El molino necesita tener su propio inventario.
Aquí puede ver que lo que he creado es una pequeña simulación que ahora incluye a un granjero que está entregando trigo al
molino y el panadero (cuando se queda sin harina y no hay harina en el molino) se queda inactivo y espera
a que el Agricultor para llenar el molino y luego volverá a su trabajo.
Así que vamos a recrear esto.
En primer lugar, voy a dejar de jugar. Voy a tomar mi Farmer que tengo y apagarlo para que
no sea realmente parte de la
ecuación en este momento, pero lo que tendrá que hacer es crear una granja o un paddock que acabo de hacer un
poco
cuadrado y he hecho la puerta (que es el punto donde se llevará a cabo la acción) para la cosecha, un poco más tarde.
También me quité los colisionadores sobre estas cosas, para que el agente no tuviera un
problema y pudiera caminar en el medio del paddock.
Entonces, lo primero que debe hacer es hacer un inventario para el molino de viento.
Tomé el Windmill y acabo de agregar el inventario que ya estaba usando para el
Baker.
Por lo tanto, el script de inventario se ha arrastrado y soltado en el molino de viento, pero no antes de algunos pequeños
cambios.
Vamos a echar un vistazo.
Entonces, aquí, lo acabo de aumentar agregando un 'drawOffset' y un 'nombre' también para que esto solo afecte el sistema GUI, de
modo que cuando lo dibuja en la pantalla, use el desplazamiento donde el inventario se posiciona y también
inserta el nombre, para que sepa de quién es el inventario y
esto aparecerá para el molino de viento. Entonces, si realiza esos cambios y solo los
guarda, regrese a Unity, luego en Windmill agregue ese script y el Desplazamiento de dibujo que tengo es 100 y
el nombre es Windmill.
Ahora eso significa que deberá configurarlo para su Baker.
Entonces, si va a su Baker y encuentra el script de Inventario, simplemente ponga el nombre de Baker y el Desplazamiento de Draw puede ser 0, de
modo que cuando presione Reproducir, obtendrá el Baker en la parte superior y el Molino de viento en la parte inferior y
usted puede realizar un seguimiento de lo que hay en cada uno de esos inventarios.
El script que necesita saber sobre el
inventario del molino de viento es
Worker, así que haga clic en el script de Worker C # y en la parte superior, vamos a pasar por el
inventario del Windmill.
Agregue eso y luego los niveles de harina en el molino de viento se usarán en el Estado mundial para inyectar
si 'hasStock' es verdadero o no y puede ver aquí
que estamos obteniendo molino de viento. flourLevel mayor que 4, lo que le
dirá a nuestro panadero que hay suficientes bolsas (son 5 bolsas, al menos, para que vaya y recoja allí).
Eso es todo lo que necesita agregar a la clase Worker.
Así que guarda eso.
La otra cosa que quiere saber sobre ese nivel de harina es su acción PickupFlour.
Entonces, además de eso, también desea pasar por el inventario del molino de viento aquí
y
luego para recoger harina, ahora tenemos otra condición previa. Entonces agregue Precondition ("hasStock", verdadero) para que cuando eso sea
cierto, podamos ir a recoger nuestra harina.
Así que solo lo haremos cuando haya stock en el molino
de viento y nos hayamos quedado sin harina. Entonces son nuestras primeras 2 condiciones iniciales.
Ahora, cuando finalmente realicemos el PickupFlour, debe recordar que desea agregar el nivel de harina a su propio inventario,
de modo que el panadero ahora lleve la harina y el molino de viento la pierda, por
lo que debe sacarla del Nivel de molino de viento para inventario.
Entonces, una vez que haya hecho eso, guarde todo eso y luego, cuando presione
Reproducir, podrá ver esto en acción.
El panadero va a hornear el pan, se va a quedar sin harina,
va a recoger algo de harina (que sacará todas las bolsas de harina del molino
que puedes ver en el inventario),
él regrese y hornee 3 panes más y luego tendrá suficiente para una entrega y lo entregará y una vez que
lo
haya entregado, se quedará sin pan, se quedará sin harina, el molino se quedará
sin harina, hay
sin harina en ningún
lado, por lo que no puede hacer nada y todos sus planes van a fallar.
Se sentará y esperará en los mercados hasta que consigan algo de harina en el molino
de
viento, para que podamos hacerlo un poco furtivamente. Si seleccionamos el molino de viento en la jerarquía (todavía estamos jugando) y pasamos al
nivel de harina y solo entregamos 10 lotes de harina ... y ahora puedes ver: se va.
Por lo tanto, ahora queremos agregar otro agente (un agente agricultor) que pueda tomar trigo del Paddock y entregarlo en el molino
de viento, para que cuando el molino de viento se quede sin harina, el panadero pueda obtener un poco más.
Entonces, para crear un nuevo agente de Farmer, dupliqué el Baker y lo hice verde y cambié su
sombrero, solo para que se vea diferente. Luego, debe quitar todos los guiones relacionados con Baker,
dejar al agente GOAP, el granjero no necesita su propio inventario (en realidad no está haciendo un seguimiento de todo, solo
está recogiendo trigo y llevándolo al molino de viento) .
Más adelante, si quieres complicarlo más, no dudes en hacerlo.
Vamos a agregar un script Farmer, que es el script de conducción del agente GOAP, como el script Worker
en el Baker y 2 acciones (1 Harvest y 1 DeliverWheat).
Veamos primero el guión de Farmer.
Deberá duplicar el script de Worker y simplemente renombrarlo a Farmer.
Así que en la parte superior tenemos a Farmer y luego todo lo demás es igual. El GetWorldState, no hay nada allí porque no necesita
hacer nada y luego el trabajo
en CreateGoalState es 'doJob' pero este 'doJob' para este agente se basa en las acciones que estarán en el agente, por
lo que no es va a estar horneando pan y recogiendo harina.
El resto del código es exactamente el mismo que para el script Worker que está en el otro agente.
Entonces son las únicas cosas allí.
Las 2 acciones que estamos agregando ...
En primer lugar, tenemos una acción de 'Cosecha' (que va a la granja y cosecha el trigo), por
lo que se llama Harvest. cs, la clase es Harvest.
La parte superior es la misma ... El
constructor, por supuesto, se llama Harvest.
Ahora Harvest no tiene condiciones previas, por lo que puede tener una acción sin condiciones previas
y también puede tener una acción sin ningún efecto.
Ahora, nada tiene que pasar para que el agricultor coseche.
Es posible que desees configurar algún tipo de ciclo diurno y nocturno en tu juego, para que el granjero
solo coseche durante el día y luego puedas ponerlo en las condiciones mundiales que están apareciendo en el código del
granjero, pero
en este caso, hay nada como eso.
Entonces, el efecto de la cosecha es que tendrá trigo, por lo que
'hasWheat' se establece en True. Ahora, el resto de esta
acción, realmente no está sucediendo nada en absoluto.
Entonces es solo el predeterminado.
No está actualizando ningún inventario en el método 'realizar' ni nada de eso.
Ok, entonces esa es la cosecha.
Ahora el otro que tenemos en Farmer es el DeliverWheat, que es llevar el trigo al
molino harinero.
Es un poco diferente.
Ábrelo y verás que tenemos un 'Inventario público' y este es
el inventario del Molino de viento. Eso es para que podamos actualizar el inventario del molino de viento cuando esta acción se haya completado.
Entonces se llama DeliverWheat, su constructor es DeliverWheat, su condición previa es 'hasWheat' es True, que se
establece en True cuando hacemos la cosecha y luego el
Efecto es ("doJob", verdadero) y esto es
lo
que está causando toda esta pequeña
cadena ejecutar porque 'doJob' es el objetivo principal del agricultor y el 'nombre' aquí (que no he cambiado)
también debería ser 'DeliverWheat'.
Esto es lo que obtienes cuando copias y pegas todas tus acciones.
Ahora el resto del código es más o menos el mismo ... bajando... aquí.
Lo único que verá es que cuando realicemos esta tarea de DeliverWheat, vamos a actualizar el nivel de
harina en el inventario por 1 bolsa.
Este inventario no es el inventario del agricultor.
El no tiene uno.
Es el inventario del molino de viento. Ok, así que guárdelos, luego
pasemos al Farmer y quiera adjuntar esos 2 scripts (esas 2 acciones) y el script de Farmer
también.
Ambas acciones (Harvest y DeliverWheat) necesitarán ubicaciones, por lo que la secuencia de comandos Harvest va a suceder en la
Puerta de la granja (que es nuestro Farm / Paddock) y luego la Entrega de trigo va a suceder en la Puerta del
molino de viento, donde dejamos caer eso fuera.
Ahora verá en la acción Entregar trigo, también hemos abierto ese 'inventario público', para que podamos pasarle el
inventario del Molino de viento, para que pueda arrastrar y soltar el Molino de viento en ese lugar
y recogerlo El inventario del molino de viento que este script ahora puede actualizar.
Ahora vamos a ejecutarlo y lo que veremos es que ambos agentes trabajan para alcanzar sus propios objetivos.
Ok, así que cuando Farmer entregue, verás que el molino de viento subirá 1 cada vez y el agente solo recogerá 5 bolsas, que ahora
las ha llevado de vuelta para hornear un poco de pan y él irá y entregará un poco de pan.
Ahora no podrá volver al Molino de viento hasta que haya 5 bolsas para recoger, por lo que está atascado
en el limbo en cuanto a hornear pan porque no tiene harina y no hay ninguna en el
Molino de viento.
Cuando el inventario de Windmill llegue a 5 harinas (lo que será ahora), hará que el Baker realice sus objetivos y
se irá, recogerá un poco de harina y luego podrá hacer el trabajo de hornear pan.
Ok, entonces puedes ver cómo esto puede volverse muy complejo, muy rápido y cómo puedes tener sistemas de
inventario que pertenecen solo a los propios agentes para que puedan hacer un
seguimiento de lo que tienen, pero también hay cosas en el mundo que
también necesita inventarios para poder mover productos. Lo que es realmente importante es que si tomas algo de
un inventario, lo agregas a otro y te aseguras de que lo menos del
valor en ese inventario anterior, de lo contrario tus números se saldrán del control y podría ser un
buena idea si realmente configura una hoja de cálculo o algo para hacer un seguimiento de todas
estas cosas que están sucediendo o incluso tiene variables globales en algún tipo de 'archivo de recuento de inventario' que puede mantener
los valores reales que va a agregue y disminuya, de modo que solo tenga que cambiarlos en
un lugar en su código.
Correcto.
Así que ese es
el sistema GOAP y espero que te haya inspirado con mucha creatividad para diseñar diferentes tipos de juegos de
simulación como este, pero también usando GOAP para juegos de rol y First Person Shooters. Entonces, si lees el enlace de la literatura de investigación
que te envié al principio, verás que esto se usó por primera vez
en juegos de tipo FPS, pero es muy adaptable.