Behavior Trees sequencer

Hey guys, so I was wondering if someone could clear something up for my regarding the sequencer in the behavior tree. I’ve read through the manual and I’m basing my question off of this nice little sample project:

Here’s my understanding so far. A sequencer will execute all of its children nodes from left to right and will return false when one of the children return false.

So essentially, it’s: try to execute the first task, if it returns successfully move on to the next task.

Here’s the part that confused me a bit. In the above project, he posted a picture of his final behavior tree


Let’s just use the very first child node as an example. If the ball is in the goal, the character should either celebrate or shrug depending on if was the actor’s goal or not. But according to how a sequencer works, the leftmost action is to celebrate. If that returns true, the actor should then…shrug? Because a sequencer moves on to the next task if the first task returns successfully. So the actor would celebrate and shrug? Doesn’t a sequencer run until a task fails, in which case you would never reach the shrug option without celebrate succeeding first…

I’m trying to figure out why you would use a sequencer instead of another selector. The way he has it set up is a lot more concise than what I was thinking, which would require two selectors (check if ball is in the goal, check if it’s your own goal). I think I’m misunderstanding something trivial here…

EDIT: So I downloaded the project itself and realized that he put some of the extra logic in the blueprint for the celebrate task itself (namely, check if the actor’s team scored). I guess my new question is, is there a preferred convention? It seems like keeping most of the logic checks (true/false, less than, equal to, etc) in the behavior tree itself and out of the blueprints would be the simplest route. Is it basically sequencer = two selectors? Kind of how like 3 NAND gates is an OR gate (non-EE people ignore me)

I was about to respond, that there might be a hidden logic in the task implementations, and that would be a reason this worked. Just like you commented :slight_smile:

This is a bad thing to do mainly because it’s confusing, and it’s distributing logic to multiple places. Using sequence here doesn’t make much sense - does the “celebrate” task can fail? If so, does this mean no “shrug” neither? Unless this behavior tree relies solely on task return values to control BT flow which is again confusing since I don’t see “condition tasks”, just tasks that can succeed or fail. I guess the only reason this is structured this way is that this one BT controls both teams in some way?

To sum up, I highly encourage using decorators for conditioning BT control flow, or at least having dedicated tasks for condition checking rather then secretly embedding them inside the tasks.

Cheers,

–mieszko