Comments on: Data-Oriented Streams Spring Behavior Trees Thanks for your persistence in reading it and your friendly feedback! Thanks for your persistence in reading it and your friendly feedback!

]]>
By: Cam Jackson/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-5438 Cam Jackson Thu, 09 Jun 2011 23:36:02 +0000 Thanks Alex, for taking the time to read through this tutorial-style article. I can't wait to hear more of your thoughts - what's new, what's well known, and what isn't thought out completely or just silly ;-) The general inputs are indeed missing. As this is an experiment I try to stick to a few constraints (that should ease adaption to heterogeneous platforms like the Cell) and to learn about the impact. The ongoing implementation already opened my eyes a few times for cases I didn't had on my plate. Currently the main idea is to have persistent actions that extract infos from "general input" and make this data available via anactor blackboard. Until know the "blackboard" is merely a void-pointer - without real limitationa. Once "bt" is open source (planed for the coming weeks) anyone could simply create a "blackboard" that contains pointers to actor-scpecifc data and to more general data. Porting to Cell would be complicated - but not everyone targets a PS3 or a GPU to run behavior trees. For example, the way Halo 3 stores goal-based data (involves linked lists) wouldn't be very suited for SPUs but (seemingly) work fine on Xbox 360. Cheers, Bjoern Thanks Alex, for taking the time to read through this tutorial-style article. I can’t wait to hear more of your thoughts – what’s new, what’s well known, and what isn’t thought out completely or just silly ;-)

The general inputs are indeed missing. As this is an experiment I try to stick to a few constraints (that should ease adaption to heterogeneous platforms like the Cell) and to learn about the impact. The ongoing implementation already opened my eyes a few times for cases I didn’t had on my plate.
Currently the main idea is to have persistent actions that extract infos from “general input” and make this data available via anactor blackboard. Until know the “blackboard” is merely a void-pointer – without real limitationa. Once “bt” is open source (planed for the coming weeks) anyone could simply create a “blackboard” that contains pointers to actor-scpecifc data and to more general data. Porting to Cell would be complicated – but not everyone targets a PS3 or a GPU to run behavior trees. For example, the way Halo 3 stores goal-based data (involves linked lists) wouldn’t be very suited for SPUs but (seemingly) work fine on Xbox 360.

Cheers,
Bjoern

]]>
By: Alex J. Champandard/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3221 Alex J. Champandard Mon, 25 Apr 2011 20:56:34 +0000 Thanks for your in-depth explanations - lot's to chew on for me and very valuable! I'm looking forward to hear about your refactoring findings and experience! Your rich performance-instrumentation should come in even more handy during the changes - great idea and technique. Cheers, Bjoern Thanks for your in-depth explanations – lot’s to chew on for me and very valuable!

I’m looking forward to hear about your refactoring findings and experience! Your rich performance-instrumentation should come in even more handy during the changes – great idea and technique.

Cheers,
Bjoern

]]>
By: Bjoern Knafla/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3204 Bjoern Knafla Mon, 25 Apr 2011 12:32:03 +0000 "Turbine used multiple trees per actor? Does that mean you had different levels of decision making and control (coop vs actor-centric, strategical, tactical, etc)? I didn’t expect that behavior trees would span up to 2000 nodes – sounds like they had a very detailed view and control over their actors and the environment." We were using behavior trees for more than just AI. For instance, one tree might be an animation controller, mapping input data into movement animations. Tree's also had channels, allowing for inter-tree interruption. So you might have one behavior tree that responds to being hit by an arrow, which could be on a higher level than the movement tree, causing it to be temporarily interrupted when the character is attacked. The behavior tree nodes there also abstracted client/server syncronization into options ("I want this to wait for the server to make the decision, I'd like the client to make this decision, and I'd like the client to make this decision but correct if the server says I'm incorrect"). "I don’t get your second example completely but it’s what interest me the most currently: how to handle interruptions?" I have an option on the node that lets the user decide. Lets say we have a very simple tree that just plays an animation when an event happens in the game. The animation is a persistent action, so what do we do if that event happens again? The user can specify to ignore the event, queue the event for when the animation is finished, have the event stop the animation, or finally have the event ask the animation to stop and execute the event when it finally does. Our tree looks like so: - EventNode (listens for something to happen and runs child) ---- Animation (plays animation) In the last case, when the second event comes in the animation gets a RequestStop() call. It's up to the animation to decide when to stop, allowing the person writing the tree to make sure the animation reaches some safe spot to end. Going back to the first case I described: - When (some value) --- True ------ Animation1 --- False ------ Animation2 Imagine this is a stage curtain opening and closing. If the animation was set to stop immediately, the curtain could oscillate back and forth undesirably. But if the animation is set to wait until the last frame, then the curtain would open completely before shutting again. And if the state flipped back to open before the opening animation finished, the curtain would simply remain open. I also have the concept of Fire and Forget on action nodes; for instance, a sound may want to be fired but not tracked by the system for interruption. This was pretty easy in our system because the nodes themselves never do any work; that's always farmed out to our existing systems (Animation task managers, playing sound instances, etc). "Would it make sense to allow to see the hierarchy and the flattened behavior stream inside of the GUI to better grasp what is going on in the game?" I think this is only really interesting to you as a potential debuging tool. The user is thinking in tree's and nodes, the fact that it's all a linear array isn't really interesting to them, and would likely just confuse them. One thing that I did do was implement a pretty robust performance tracking system. These types of systems create unexpected consequences; what is the cost of changing a property? It depends on how many things are listening to it and reacting. So my perf monitor does several things; first, it separates out the cost of the language from the tasks the language creates. How long do we spend processing node behavior vs. how long does it take to spawn that sound or animation. Second, it orders this data based on the events which cause things to happen, so the most expensive events are obvious. As an example, I was monitoring performance a few days ago and would see the occasional spike frame taking 0.5ms. It was immediately obvious what the issue was, as it showed me which property was changing and which script was taking the time. Turns out someone had simply mapped the score to a UI element to display the score, but set up the UI element wrong. I could see this because the script processing time was basically nothing, and the action was taking all the time. Anyway, have to run, kids; I'll get back to the thread soon. I'm still trying to figure out how to best refactor my system for instances and data centric design, so I might hit you up for some advice. “Turbine used multiple trees per actor? Does that mean you had different levels of decision making and control (coop vs actor-centric, strategical, tactical, etc)? I didn’t expect that behavior trees would span up to 2000 nodes – sounds like they had a very detailed view and control over their actors and the environment.”

We were using behavior trees for more than just AI. For instance, one tree might be an animation controller, mapping input data into movement animations. Tree’s also had channels, allowing for inter-tree interruption. So you might have one behavior tree that responds to being hit by an arrow, which could be on a higher level than the movement tree, causing it to be temporarily interrupted when the character is attacked. The behavior tree nodes there also abstracted client/server syncronization into options (“I want this to wait for the server to make the decision, I’d like the client to make this decision, and I’d like the client to make this decision but correct if the server says I’m incorrect”).

“I don’t get your second example completely but it’s what interest me the most currently: how to handle interruptions?”

I have an option on the node that lets the user decide. Lets say we have a very simple tree that just plays an animation when an event happens in the game. The animation is a persistent action, so what do we do if that event happens again? The user can specify to ignore the event, queue the event for when the animation is finished, have the event stop the animation, or finally have the event ask the animation to stop and execute the event when it finally does. Our tree looks like so:

- EventNode (listens for something to happen and runs child)
—- Animation (plays animation)

In the last case, when the second event comes in the animation gets a RequestStop() call. It’s up to the animation to decide when to stop, allowing the person writing the tree to make sure the animation reaches some safe spot to end.

Going back to the first case I described:

- When (some value)
— True
—— Animation1
— False
—— Animation2

Imagine this is a stage curtain opening and closing. If the animation was set to stop immediately, the curtain could oscillate back and forth undesirably. But if the animation is set to wait until the last frame, then the curtain would open completely before shutting again. And if the state flipped back to open before the opening animation finished, the curtain would simply remain open.

I also have the concept of Fire and Forget on action nodes; for instance, a sound may want to be fired but not tracked by the system for interruption. This was pretty easy in our system because the nodes themselves never do any work; that’s always farmed out to our existing systems (Animation task managers, playing sound instances, etc).

“Would it make sense to allow to see the hierarchy and the flattened behavior stream inside of the GUI to better grasp what is going on in the game?”

I think this is only really interesting to you as a potential debuging tool. The user is thinking in tree’s and nodes, the fact that it’s all a linear array isn’t really interesting to them, and would likely just confuse them. One thing that I did do was implement a pretty robust performance tracking system. These types of systems create unexpected consequences; what is the cost of changing a property? It depends on how many things are listening to it and reacting. So my perf monitor does several things; first, it separates out the cost of the language from the tasks the language creates. How long do we spend processing node behavior vs. how long does it take to spawn that sound or animation. Second, it orders this data based on the events which cause things to happen, so the most expensive events are obvious.

As an example, I was monitoring performance a few days ago and would see the occasional spike frame taking 0.5ms. It was immediately obvious what the issue was, as it showed me which property was changing and which script was taking the time. Turns out someone had simply mapped the score to a UI element to display the score, but set up the UI element wrong. I could see this because the script processing time was basically nothing, and the action was taking all the time.

Anyway, have to run, kids; I’ll get back to the thread soon. I’m still trying to figure out how to best refactor my system for instances and data centric design, so I might hit you up for some advice.

]]>
By: shareisevolve/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3166 shareisevolve Sun, 24 Apr 2011 13:27:32 +0000 Hehe, thanks Christian, Curious to hear your feedback if the "epic" length carried enough quality and was easy to understand or if it was just too long to keep reading till the end ;-) Cheers, Bjoern Hehe, thanks Christian,

Curious to hear your feedback if the “epic” length carried enough quality and was easy to understand or if it was just too long to keep reading till the end ;-)

Cheers,
Bjoern

]]>
By: mcmuttons/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3164 mcmuttons Sun, 24 Apr 2011 11:48:49 +0000 Thank you for your kind words! What aspects of behavior trees are you working on? Cheers, Bjoern Thank you for your kind words!

What aspects of behavior trees are you working on?

Cheers,
Bjoern

]]>
By: Bjoern Knafla/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3160 Bjoern Knafla Sun, 24 Apr 2011 10:38:10 +0000 Hey Jason, Thank you for your detailed and insightful comment! Highly appreciated! I'm amazed to learn where and how behavior trees are used - and that you have so much experience in deploying them. Turbine used multiple trees per actor? Does that mean you had different levels of decision making and control (coop vs actor-centric, strategical, tactical, etc)? I didn't expect that behavior trees would span up to 2000 nodes - sounds like they had a very detailed view and control over their actors and the environment. In regard to cancellation of actions: - Your first example is what I primarily strive for: the components/systems that execute actions also detect action "collisions" and resolve them. - I don't get your second example completely but it's what interest me the most currently: how to handle interruptions? What happens if a higher-up selector node abandons a "running" child and runs another one? One way to treat this situation could be to let the action-executing system detect that an action isn't refreshed via a request and cancel it. Another way could be to detect in the behavior tree that running actions have been abandoned and need explicit cancellation. This could happen by looking at the last action result states and if "running" actions aren't requested again to cancel them. Or, a selector node that doesn't stick with "running" children could be marked to use the cleanup phase per actor to watch out for abandoned actions. Thank your for recommending a tree-view instead of a graph-view! Actually, I looked up how Cocoa's NSOutlineView interfaces with a controller for hierarchical models to understand how the behavior tree should be modeled for a GUI. Would it make sense to allow to see the hierarchy and the flattened behavior stream inside of the GUI to better grasp what is going on in the game? Your way to handle references is very interesting - I need to think about that a bit longer to fully grasp how it'll look in my case. Thanks you so much and cheers, Bjoern Hey Jason,

Thank you for your detailed and insightful comment! Highly appreciated!

I’m amazed to learn where and how behavior trees are used – and that you have so much experience in deploying them.

Turbine used multiple trees per actor? Does that mean you had different levels of decision making and control (coop vs actor-centric, strategical, tactical, etc)? I didn’t expect that behavior trees would span up to 2000 nodes – sounds like they had a very detailed view and control over their actors and the environment.

In regard to cancellation of actions:
- Your first example is what I primarily strive for: the components/systems that execute actions also detect action “collisions” and resolve them.
- I don’t get your second example completely but it’s what interest me the most currently: how to handle interruptions? What happens if a higher-up selector node abandons a “running” child and runs another one?
One way to treat this situation could be to let the action-executing system detect that an action isn’t refreshed via a request and cancel it.
Another way could be to detect in the behavior tree that running actions have been abandoned and need explicit cancellation. This could happen by looking at the last action result states and if “running” actions aren’t requested again to cancel them. Or, a selector node that doesn’t stick with “running” children could be marked to use the cleanup phase per actor to watch out for abandoned actions.

Thank your for recommending a tree-view instead of a graph-view! Actually, I looked up how Cocoa’s NSOutlineView interfaces with a controller for hierarchical models to understand how the behavior tree should be modeled for a GUI.

Would it make sense to allow to see the hierarchy and the flattened behavior stream inside of the GUI to better grasp what is going on in the game?

Your way to handle references is very interesting – I need to think about that a bit longer to fully grasp how it’ll look in my case.

Thanks you so much and cheers,
Bjoern

]]>
By: shareisevolve/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3158 shareisevolve Sun, 24 Apr 2011 09:12:58 +0000 Wow, epic article, now I see why it took a while to get here! Going to have to save this one for the train ride this week. I look forward to it! Wow, epic article, now I see why it took a while to get here!
Going to have to save this one for the train ride this week. I look forward to it!

]]>
By: Jason Booth/2011/04/24/data-oriented-streams-spring-behavior-trees/#comment-3152 Jason Booth Sun, 24 Apr 2011 03:19:01 +0000