Use case with multiple AIs

Is there a way to pause the behavior tree at each action node without making use of Async or Coro action nodes?

I’m currently working on a game AI application of BehaviorTree.CPP
There is one problem; the code seems to be made to be a “frame” of decision for a single robot, while in my case, I plan to have multiple AIs with different Behavior Trees being executed at the same time.

Since they share and act in/on the environment, I don’t see the actions being resolved as asynchronous since they won’t have access to all the information necessary in a different thread. Coroutines seems to be a workaround, but it does not seem “clean” in my eyes.

Any advice and ideas are welcome, currently going the coroutine way, but I’d like to avoid it.

Thanks in advance! :slight_smile:

let’s see if I understand this correctly.

  1. You have multiple agents, each of them has its own behavior tree running.
  2. The agents share some information about the environment.

My opinion is:

  • All your Actions must be either atomic (blocking with very fast execution) or asynchronous (they take a while, but they return immediately RUNNING to avoid blocking the tree).

  • In your main gaming loop you should tick each of the individual trees in a for-loop. None of those tree should block!!!

  • you should definitively NOT use Actions with their own thread, to avoid overhead and problems of thread safety.

Refer to this article to learn more: Concurrency and Asynchronous Nodes - BehaviorTree.CPP

I don’t see the actions being resolved as asynchronous since they won’t have access to all the information necessary in a different thread.

I am not sure I understand this, but it sound as a bad design.
You should define how to make the environmnet information available to the agent in a thread-safe way.

Coroutines seems to be a workaround, but it does not seem “clean” in my eyes.

I disagree. They are probably what you should consider using.

currently going the coroutine way, but I’d like to avoid it.

Not really sure why.

Yes you did understand!

Returning RUNNING is exactly what I had in mind and tested in the toy example. It’s exactly what I’m going to do.

Yep.

Being called out on it, I agree. The state or the information available for the decision should be passed to the agents. Currently in the figuring out how I’m going to do it part of coding, nothing is really set in stone yet.

As to why I’d like to avoid coroutines, it’s mostly because of setStatusRunningAndYield();. In the example available, this function is used instead of a return BT::NodeStatus::RUNNING in an asynchronous action. I project that someone returning to the code would find it unclear. Returning NodeStatus::RUNNING instead of having a macro do it for me seems more direct. That’s it really.

Lastly, I went back in the source code and found that there are IfThenElse nodes. Is there a reason why they’re not mentionned in the documentation on the website, or is it simply something that hasn’t been documented yet?

Thanks for your reply, it kind of cements what I had in mind.