Event-Handling Strategies for Juggling Purposeful Behaviors

Alex J. Champandard on November 11, 2007

Assume you have a long-term AI behavior controlling a character in a game. It could be implemented as a script, a behavior tree, or any other sequence of actions to follow. How do you deal with events happening in the world in a way that’s coherent with this active behavior?

The AI logic needs to make two major decisions when receiving incoming events from the wold. It must work out:

  1. Whether to terminate the running behaviors or just suspend them.

  2. If new behaviors should start, or resume existing ones from suspension.

Obviously, in special cases, events should trigger both operations. However, you can simplify the AI tremendously by separating the logic into two types of event handlers.

Handling Broken Assumptions

Generally when you build AI, it’s useful to make behaviors goal-oriented, so they each solve a specific problem. As you design behaviors to reach their goals, you’ll find yourself relying on certain conditions about the context they run in.

Then, to make sure that the AI responds to events in a logical way, you need to capture these assumptions using some custom logic. For example:

  • In a script, you could monitor your assumptions by writing a custom event handler for all the facts that could change and break the behavior.

  • In a behavior tree, you would use parallel conditions high-up in the tree to check those assumptions regularly and bail out if necessary.

Once each behavior can monitor its own pre-conditions and make sure it terminates immediately once its assumptions are wrong, you can start thinking about handling other events.

Responding to New Opportunities

To react to potential opportunities, you need a global handler to take care of all the events (including those which also invalidate certain assumptions). This type of handler is much harder to implement, as there are many more cases to handle, but you can keep things simple by:

  • Only deciding what new behaviors to start.

  • Establishing priorities of the new behaviors.

  • Letting other behaviors suspend or terminate themselves.

Basically, this approach makes it a bit easier to deal with the huge matrix of possible choices that grows with the number of active behaviors. Instead, you just select new behaviors, give them a priority, and if there’s a clash over resources, let other behaviors bail out if their assumptions are broken.


It’s hard to capture all the subtleties in this problem without writing a whole dissertation on the subject, but at least now you have the basics of a solid system for handling events. It’s best to separate event handlers into two groups: one for monitoring running behaviors and shutting them down if assumptions are broken, and the other as a global event handler for starting new behaviors and working out their relative priorities.

Do you use any particular tricks for handling events in the context of purposeful behaviors?

Discussion 7 Comments

Ian Morrison on November 12th, 2007

I am going to reread this article when my brain isn't primed to explode from dealing with deadlines. The idea of a custom event handler inside actions is neat, though..

bknafla on February 18th, 2008

Angel, your "context" gets me thinking if a programmer should be able to tag certain sub-trees with a symbol or a tag or an enumeration. Is this what you meant? A new opportunity handler could possible be implemented like an array of conditions as childrens of a parallel node (like Alex describes all the time). However if a condition is triggered it gets sort of a introspection of the state of the tree through the currently active symbols - and might therefore be able to decide what to do next in a more appropriate matter. Where does this lead? While currently the traversal state of a tree is implicitly represented by the way it is executed. By adding symbols or contexts or tags (or however you want to name them) there is also an external description of the tree state which can be used for introspection (a meta view). I am not sure how much this would complicate the implementation or even the use of a BT. There certainly is a balance to strike between flexibility and power and ease of use because of well known limits and patterns of using a BT. Though only experimentation will show where to strike this balance ;-) Cheers, Bjoern

bknafla on February 18th, 2008

Hey Angel, thanks for your helpful explanation - your context idea sounds really interesting and inspiring! Cheers, Bjoern

bknafla on February 19th, 2008

The context idea keeps nagging at the back of my mind: a context would get even more useful if it can be queried for some attributes describing the subtree is represents or the state of the subtree it represents. Such attributes could be: - the currently active conditions and actions - if it is interruptible ind principle and in the current moment - how long it might take to evaluate it (to get knowledge about animations that need to run for a certain amount of time) - sub-contexts it holds Perhaps different contexts for different purposes would be helpful (one context just for "is active" tagging, on to inform about animation capabilities, etc.). Cheers, Bjoern

bknafla on February 19th, 2008

Hey Angel, yeah, balancing power with ease of use and a good interface is the high art of software development and a constant struggle. While I am browsing through the tutorials and the sources of Game::AI++ I get the impression, that the "context" idea as a meta tag to the BT is something that Alex could use easily or which is already implicitly present because of the way a tree might be interpreted as a solution space for a planner... though after 10 minutes of source code reading I don't have a real understanding of all the things going on in Game::AI++ ;-) I am opting for an article that brings together the BT idea, the task idea and the interpreter idea to explain how trees are traversed, how tasks are really scheduled and how trees could be interpreted in different ways. :-) Cheers, Bjoern

alexjc on February 19th, 2008

I think tags are a cool idea. I've never used them, but I think it helps modularity: [URL=]Game Design 2.0: Learning from Social Networks[/URL] Anyway, I like to keep tasks in a central place (like a scheduler or interpreter) so they can be iterated over easily. You can then have multiple behavior trees running in parallel, and have them check each other to decide the best course of action. This is a bit like a blackboard architecture combined with behavior trees, which Max Dyckhoff mentioned his 2007 talk at GDC. It works to keep all the parts of the logic simpler... Bjoern, you're right, there's lots to tie together here! Alex

chot on February 8th, 2009

Hey, I'm just starting to get into behaviour trees and AI programming in general, so I might be completely wrong here, but anyway here's something I thought of when I read this; I like the idea of the first type of event handling, but the second kind, seems to me it kind of breaks the idea with behaviour trees? I mean, if you take it further, you might want these event's to be handled different depending to where we are in the tree and all of a sudden we're kind of back into a state machine? So I thought about this for a while, and an idea that I came up with was; why not make event handling a decorator as well? The idea is that once an event is issued, it's directed to the node(s) currently in process. If these doesn't know how to handle the event, they send it back up the tree until it finds a node which can handle events. This node in turn gets to choose if it should abort the subtree executing and start going down another tree instead to handle the event. I guess this would kind of extend to conditions also, though they would probably have to be implemented as filter decorators (otherwise the event has to not only go up the tree, but also down at each node to find the conditions). Any thoughts? Cheers, Fredrik

If you'd like to add a comment or question on this page, simply log-in to the site. You can create an account from the sign-up page if necessary... It takes less than a minute!