How to abort an action asynchronously

MeisterDerMagie

New member
I'm trying to achieve the following behavior:

1. As long as the "alert level" of an NPC is low -> be in an idle activity (reading a book).
2. As soon as the alert level hits a certain threshold -> stop the idle state asynchronously (put book away) and only then start chasing the player

I set up the following interface that defines an activity:
public interface IActivity
{
public async UniTask Begin(); //example: pick up a book to read
public async UniTask End(); //example: put book away
}

My goal is to have self contained activities/actions that the NPCs can perform. Reading a book, cooking, chasing the player... whatever. In order to proceed to another activity the current one should gracefully be stopped: put the book away, turn off the stove, be mad for a second because they couldn't catch the player...

This is my current attempt of the behavior tree, or at least how I imagined it to work:
1777543087817.png

Is there a way to delay a conditional abort, until the async End() of the idle activity has finished. What would be the intended way to deal with Actions or Sequences that need a non-immediate clean-up?

If I don't go the async way, but instead would create a separate action for BeginIdle, PerformIdle, EndIdle I would still have the issue that a conditional abort (alert level is high) would stop PerformIdle immediately without running the EndIdle action. Or is there a way to complete a sequence before handling the abort? (I would very much prefer the async way because it would mean less overhead for our designers when building the behavior tree. The tree would define which activities are executed under which circumstances, but not define the animations and transitions between activities.)

Another issue I face:
When the alert level raises from "Ignore" to "Become Aware", the idle activity is restarted. I had imagined that the selector would just keep going, as long as one of the children is successful. Why does it restart when one child fails but another stays successful?

Let me know if my problem is unclear and thanks in advance for any hints in the right direction, much appreciated!
 
Last edited:
If I don't go the async way, but instead would create a separate action for BeginIdle, PerformIdle, EndIdle I would still have the issue that a conditional abort (alert level is high) would stop PerformIdle immediately without running the EndIdle action. Or is there a way to complete a sequence before handling the abort? (I would very much prefer the async way because it would mean less overhead for our designers when building the behavior tree. The tree would define which activities are executed under which circumstances, but not define the animations and transitions between activities.)
The behavior tree traversal does not occur asynchronously so you cannot use async. You can tick the tree manually which will then give you more flexibility over when the abort logic runs, but unless you modify the source code there isn't a way to run the abort code separately from the rest of the traversal.

When the alert level raises from "Ignore" to "Become Aware", the idle activity is restarted. I had imagined that the selector would just keep going, as long as one of the children is successful. Why does it restart when one child fails but another stays successful?
For this you likely want to use the stacked conditional task.
 
Thank you for your quick answer!
I see. In that case I might use the tree as a way to determine the target action and implement transitions between activities with custom logic then.
Just out of curiosity: How would you handle the mentioned situation where the NPC needs to put the book away before chasing the player? Would this even be possibly in any way (even if it's not elegant) with Behavior Designer?

For this you likely want to use the stacked conditional task.
Ah thanks, I didn't know about that.
 
Last edited:
How would you handle the mentioned situation where the NPC needs to put the book away before chasing the player? Would this even be possibly in any way (even if it's not elegant) with Behavior Designer?
This is handled a lot better in Behavior Designer Pro. In the pro version you can add an event branch that triggers when a conditional abort occurs, You could run the return book actions, and then use a bool or event to signal that those are complete and the rest of the tree can run.
 
Okay, that would make the whole tree event driven, which wouldn't be ideal in our case. I'll implement custom logic then. Thanks for clarifying things!
 
Back
Top