How to achieve "Active" selector node functionality in UE4 Behavior Trees?

When working in behavior trees in the past, I’ve taken advantage of what I’ve seen termed as “Active” selector nodes - that is, selector nodes that constantly re-evaluate children in order, even if one child was stuck “InProgress”. This would allow a higher priority child branch to immediately execute and stop execution of lower priority children. Basically, a scheme that handles this scenario as detailed here https://docs.unrealengine.com/latest/INT/Engine/AI/BehaviorTrees/HowUE4BehaviorTreesDiffer/index.html

To illustrate what I’m talking about, here’s a setup I created in UE4 that mimics how I would naively approach this problem given my past behavior tree usage (I can send any .uassets upon request):

19ee3f120a6df87879aabb765080f8ed8c5a370d.jpeg

Now I know this setup isn’t “supposed” to work with UE4’s event-driven behavior trees. Further down in the documentation, it seems the desired solution is to do something like this:

The problem is I’m having trouble visualizing exactly what this means, and any attempts to implement this solution (as I was able to discern, with or without Simple Parallel nodes) did not work - at the very least, not the way I expect. One big hurdle I’m seeing is that Decorators do not seem to evaluate every frame, only upon a node’s initial execution. The implication being if a child node is set to be “InProgress” for a time (as in my example, with the giant Wait nodes), the Decorators will not evaluate during this period so there’s no way to kick a node out of an undesired behavior immediately.

I’m sure I’m missing something! Any help you can provide would be amazing. Again, I can provide any .uassets for my test scenarios and what I expect to see happen. Thanks.

Our event-driven approach requires you to use a blackboard along with your BT. You can add a boolean key to your blackboard labeled “IsMouseValidTarget” (for example) and then have a blackboard-based decorator that checks this specific BB key.

With such a decorator you can specify if sub-branch guarded by this decorator should be aborted on condition values change (“AbortSelf”), and you can even request that lower-priority behavior gets aborted if said decorator is “available” again after failing previously (the “Abort lower priority” mode). You can also request both behaviors as well.

Regarding Decorators not ticking there’s also a special BTNode category that does that actually: Services. A service will tick with a specified frequency and run some code. The ideal use case is that you have a service calculate some data an put it into the Blackboard and then have decorators using that data to control BT flow.

The less ticking the better :wink:

–mieszko

Thanks for your reply! I wasn’t having any issue with the decorator itself (I didn’t need to use a blackboard in this case because that custom decorator was checking a variable on the casted controller); my question was more about the decorator check on every frame, which is what I need.

I am aware of services for ticking, but I don’t think I fully understand what you’re proposing. I know how I can make a service calculate some data and put it on a Blackboard value(s). But the decorator would have no chance to operate on this information every frame, because its condition check only seems to occur upon a node’s execution having started. So in my example above, my child “Wait” node keeps it “InProgress” and the decorator will not be able to continually check any blackboard data, whether it’s calculated per-frame in a Service or not. Am I understanding this properly?

I was kind of able to get some of the behavior I was desiring by adding a Service on the base Selector node. This Service would every frame query direct child decorators to see if they need to subvert any currently executing branch. What I ran into, unfortunately, was that certain functions weren’t publicly exposed on the BehaviorTreeComponent to fully control the execution flow from that point on (e.g., UBehaviorTreeComponent::AbortCurrentTask()), and since I did not want to modify engine source, I was forced to try some hackery to get an approximation of what I wanted.

Thanks again for your response.

The BB-based decorator gets notified on changes to the key he’s observing and reevaluates his condition (provided it’s set to abort self, lower priority or both). No ticking required :smiley:

Ah, interesting. I’ll give this a try (and at the very least, inspect the blackboard decorator code to see what I can learn about forcing re-evaluation). Thanks!