The blackboards of behavior trees

Started by
5 comments, last by IADaveMark 5 years, 6 months ago

I really like to add AI to my game in the form of behavior trees and have been reading about them. The primary thing I am "stuck" with is how to pass data. Some articles mention a blackboard that should be passed down the tree nodes so they can set fields on it, but this means for each leave task that needs some form of data the blackboard gets a field. I imagine a lot of leave leave tasks and some need many fields to set on this blackboard and this deviates from my perception of clean and scalable code. Are there other ways to handle this?

Advertisement

My understanding of behavior trees is that you define a whole bunch of functions in your game code that return a boolean. These can be functions that get information about the situation (Is there an enemy nearby? Do I have ammo? Is my health above 60%?) or functions that actually do something and return whether they succeeded (Move to take cover. Shoot at the weakest enemy within range. Say "Halt!"). A behavior tree is then an expression that joins these functions with the equivalent of the operators || and && from C.

The strength of this paradigm is that it's impossible for the game designer to go crazy with the complexity of the behaviors. If you need to define a whole bunch of variables in a blackboard, perhaps this very simple architecture is not a good fit for your task.

Well I did a bit more research and tried implementing my own to at least understand BT's better. Using the actual object that the behavior tree controls looks like a much better alternative then some examples show. This however makes it mandatory to have to have references of everything the behavior tree might need inside it. But I have always found that a creature should be aware of the map and it's surroundings itself instead of having some kind of handler class for it.

Another way I have been trying is to just pass a Map<String, Object> along the tree, an attack task would be run after a SearchEnemyTask task in sequence. The SearchEnemyTask tries to find an appropriate enemy and sets something along the lines of blackboard.put("target", targetEntity). Now this is a little less "safe" but does seem to be more versatile, if I ever want to create an automatic door using a BT I can just reuse openDoorTask on it instead of the above method where I would need to create a new Task with a Door as a blackboard.

It's still hard to wrap my head around the complete concept but I'm getting there, but I was hoping for some more input here.

This sounds like you are making it a bit more complicated than it should be. Also, there really is little difference between the way a BT process its environment and some other architectures.

Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play

"Reducing the world to mathematical equations!"

10 hours ago, IADaveMark said:

This sounds like you are making it a bit more complicated than it should be.

That happened before ?. But how would you pass data around then? I am currently playing around with the behavior tree library of GdxAI. In the example they are using the object itself as a blackboard, it gets passed to every task in the behavior tree so it can manipulate it or use it's methods. It is also working with a Map<String, Object> where I would test the data needed for a task in the start() method and immediately return failure when data is incomplete, like when there is a AttackTask without a prior task that sets an enemy for it in the Map. Then there is the blackboard I spoke about earlier, a class specially catered to that and grows in size when the amount of task and needs grow. I could pass this as well along the tree but it does not seem a good choice compared to the other two.

Well a lot of the world info isn't going to need to get passed. Passing copies of the data isn't a great idea for a lot of reasons. Just look it up from the behavior objects as needed. Same thing for the character's data... just look it up. You can pass in a reference to the world or character if needed, too.

 

Methinks you skipped a few parts of the behavior tree tutorial.

Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play

"Reducing the world to mathematical equations!"

This topic is closed to new replies.

Advertisement