Coroutines son ideales para esto, ya que puede mantener todas las variables de estado locales sin problemas. Es decir. sin tener que almacenarlo manualmente en un contexto en algún lugar.
Pero no veo un sistema de eventos como alternativa. Más como un complemento que probablemente desee tener además de un sistema de secuencias de comandos basado en Coroutine.
Ejemplo (en algo coherente C++):
Ha implementado un comportamiento usando corrutinas lo largo de estas líneas:
class EnterHouse : public NPCBehavior
{
EnterHouse(House theHouse) { _theHouse = theHouse; }
void Begin() { _theHouse.AddNPC(NPC()); }
void Update()
{
NPC().WalkTo(_theHouse.GetDoor().Position());
NPC().FaceObject(_theHouse.GetDoor());
NPC().PlayAnimation(NPC().Animations().Get(eAnimKnockOnDoor));
Sleep(1.0f);
NPC().OpenDoor(_theHouse.GetDoor());
}
void End() { /* Nothing */ }
private House _theHouse;
}
imaginar que los métodos en los NPCs a sí mismos crear objetos NPCBehavior, pulsadores ellos en algún tipo de pila de comportamiento y regresan de la llamada cuando esos comportamientos se completan.
La llamada Sleep(1.0f)
dará lugar a su programador de scripts y permitirá que se ejecuten otros scripts. El WalkTo
, FaceObject
, PlayAnimation
y OpenDoor
también llamarán al Sleep
para ceder. Ya sea basado en una duración de animación conocida, para despertarse periódicamente para ver si el Pathfinder y el sistema de locomoción terminan de caminar o lo que sea.
¿Qué sucede si el NPC encuentra una situación que tendrá que enfrentar de camino a la puerta? No desea tener que verificar todos estos eventos en todas partes en su código basado en coroutine. Tener un sistema de eventos que complemente las corutinas facilitará esto:
Un bote de basura se cae sobre: El bote de basura puede transmitir un evento a todos los NPC cercanos. El objeto NPC decide empujar un nuevo objeto de comportamiento en su pila para ir a arreglarlo. El comportamiento WalkTo
está en una llamada Sleep
rindiendo en alguna parte, pero ahora el comportamiento FixTrashcan
se está ejecutando debido al evento. Cuando FixTrashcan
complete el comportamiento WalkTo
se despertará desde Sleep
y nunca se sabe sobre el incidente de la papelera. Pero todavía estará en camino hacia la puerta, y debajo todavía estamos corriendo EnterHouse
.
Una explosión ocurre: La explosión difunde un evento al igual que el cubo de basura, pero esta vez el objeto de la APN decide restablecer funcionando comportamientos y empujar un comportamiento FleeInPanic
. Él no regresará al EnterHouse
.
Espero que entiendan lo que quiero decir con eventos y corutinas viviendo juntos en un sistema de inteligencia artificial. Puedes usar coroutines para mantener el estado local mientras te rindes al programador de scripts, y puedes usar eventos para manejar las interrupciones y mantener la lógica para tratarlos centralizados sin contaminar tus comportamientos.
Si aún no ha visto this article by Thomas Tong sobre cómo implementar corutinas de subproceso único en C/C++, lo recomiendo encarecidamente.
Utiliza solo el más mínimo bit de ensamblaje en línea (una sola instrucción) para guardar el puntero de la pila, y el código es fácilmente transferible a un montón de plataformas. Lo he estado ejecutando en Wintel, Xbox 360, PS3 y Wii.
Otra cosa agradable acerca de la configuración del programador/script es que resulta trivial matar de hambre a los caracteres AI/ajenos a la pantalla o lejanos si necesita los recursos para otra cosa. Simplemente combínelo con un sistema de prioridad en su programador y estará listo.
La alternativa a corutinas, FSM y programación basada en eventos son CSP (comunicación de procesos secuenciales).Consulte la implementación de LuaCSP (en la parte superior de coroutines) aquí: https://github.com/loyso/LuaCSP NB: lo que las personas suelen perder es el aspecto de coordinación y comunicación. –