How to make a Behaviour Tree Decorator cancel currently executing branch?

I am attempting to make a simple behaviour tree, one that follows the player but stops once it is within a certain radius.

It currently looks like this:

However the enemy will follow the player right up until it reaches them and goes idle. Whereupon the moveToPlayer returns and it waits until the player is further away than 500. Any Idea why the decorator isn’t aborting the move to player when the condition is filled? Is the condition check run every frame or do I need to put event tick into the decorator?

1 Like

This is easily solved, just make your own decorator to check for the condition. Here’s an example I made myself a few days ago:

http://stuff.pyrron.com/ue4-btcondition.jpg

In this Decorator asset, I’m checking if the State value is the same as the CheckState variable, and if yes, allow execution. Then when I add the decorator to a BT Node, I set the Blackboard key (State) to be the correct key from my Data Asset, and set the CheckState to the state I want to require.

You could easily do the same with just checking the value of a float! Hope that helps :slight_smile:

The isInRange decorator already does that (it looks almost identical to your example) However this doesn’t seem to cancel a currently executing task, only stopping a task from executing in the first place.

Perhaps I should be more clear about my decorators and services- The CheckPlayerRange service checks the distance to the player every tick and sets a blackboard bool that isInRange checks in EventReceiveConditionCheck. The service correctly sets the blackboard value as soon as the enemy comes into range. However the decorator seems unable to abort the currently executing task. I have set it to abort self and inverted it (so it only attempts to move when the player is out of range). Am I misunderstanding something about decorators or can they not be used for interrupts?

If you look at your behavior tree while it is executing, you’ll see that it is not calling it once and then stopping, but calling it over and over again each tick. So if in one tick suddenly the condition for its execution is no longer valid, it will stop doing that. Aborting a task that is already underway would be way more complicated… the execution path always completes first before returning to the tree, from what I understand.

I vaguely remember that they talked about callbacks in BT one of the livestreams, but for the task you’re trying to do, I don’t think you need that :slight_smile:

When I watch the execution, the tree falls down the MoveToPlayer path even after inRange is set to true. It doesn’t move to the lower priority path when this happens.It will only switch away from MoveToPlayer once it finishes execution, And then on re-entering it will only do so once the player moves out of range. It doesn’t seem to interrupt MoveToPlayer at all.

I have set it so abort self and put an event Receive Abort in MoveToPlayer that cancels the movement on receiving an abort. However it doesn’t seem to check the condition until the task finishes execution and it tries to start execution again. It only tests on first trying to enter the task.

It is worth noting I am using MoveToActor with the radius set to -1 and call finish execute when the MoveStatus is idle. I can solve this by setting the MoveToActor radius to the value in checkPlayerRange, however I wanted to cancel execution by decorators as a proof of concept.

Event Receive Abort never gets called, So I’m not sure that is a problem, I’ve changed it however.
Thanks for your help, I’ll look into behaviour tree callbacks and possibly doing something with event tick in the decorator.

Hmm, not sure I understand you correctly. Can you show the network of your MoveToPlayer task?

Actually, of the abort decorator as well?

Hmm, I only see one thing: Instead of calling Finish Execute at the end of your Abort exec chain, you should call Finish Abort. Other than that, I’m baffled.

Well, good luck in any case :slight_smile:

I have the same problem, so I checked the source code. It seems that condition check in the decorator is executed only during “entry” to the task node and when it “finishes”. In your case, before it executes MoveToPlayer and when it finishes.

I maybe wrong, but it doesn’t seem that we can do an additional “finish” condition on top of the task’s inner finish condition.

I find that using blackboard works much better than using your own condition. So in the sample above, instead of isInRange, change it to Blackboard that checks that “state” value.

Hey TinyAngryCrab, I’m also struggling with the same issue. Have you found out any methods to abort the task while it’s executing?

1 Like