Parallel Composite locks up when child node keeps running

Hello,

I have a Parallel node that runs two child nodes:

  • A node that keeps following a target.
  • A node that keeps attacking a target.

Both nodes should continuously run as long as the target GameObject is valid in the blackboard.

The problem: The Parallel node locks up at the first child node and waits for it to finish. As a result, the second child node only runs initially, then never again. This behavior doesn’t seem right because the Parallel node should run both child nodes simultaneously.

I have tested the different Parallel node modes:

  • Until Any Complete
  • Until Any Succeed
  • Until Any Fail

None of these seem to fit my case. They don’t resolve the issue.

I also tried creating a custom Parallel node by inheriting from Composite, like the built-in ones, but I couldn’t get it to behave differently. If I set it to return Success, all child nodes get interrupted, while returning Running just leads to the first child node locking up.

In summary, no matter what I’ve tried, I’ve failed to make multiple child nodes (which return Running) execute in parallel. Either I’m missing something fundamental, or there’s a limitation in the Behavior Tree system.

My Behavior Tree setup:

Questions:

  • Is this expected behavior in Unity’s Behavior Tree system?
  • What am I doing wrong, or what is missing in my setup?

Hi @Kreesty

That is indeed a regression :cry:

Thanks for reporting it, I will open a ticket using the information you provided, sorry for the inconvenience :bowing_man:

Edit: Not it isn’t actually, sorry for the confusion. See answer below: Parallel Composite locks up when child node keeps running - #4 by MorganHoarauUnity

No worries, and thanks for the quick reply.

I’m overall liking the Behavior system so far, and I hope the issue with the Parallel node gets addressed soon so that I can resume work on my AI agents.

1 Like

Actually I was wrong sorry, bear with me, it’s my first day back from holiday :sweat_smile:

Parallel composite are indeed going to execute branches in parallel, but the branch won’t be running in repeat, only until they succeed once. If you want your behavior running in parallel to repeat, you need to add a Repeat composite above them.

This means you might need to change a bit the top of your tree, and use an Abort if composite to redirect the flow of your logic toward your “Sensor Look for closest Target” node.

Hope this helps!

Edit: Added screenshot

1 Like

Oh, I see. Adding the Repeat nodes does indeed seem to result in the desired behavior.

I’ll mark your reply as the solution, however I still don’t understand exactly why this works (and why it doesn’t without the Repeat nodes).

If you don’t mind, could you explain in a little more detail the logic behind this?

Thank you!

Sure :slightly_smiling_face:

Run In Parallel runs all the branches simultaneously, but a branch execution ends when a node of the branch fails or when all nodes of the branch succeed. In your case, it seems like you wanted your 2 actions to run both in parallel and forever.

For that you need to add an additional instruction that will make the branch repeat once it finishes (by either failing or succeeding).

Does that help?

I’ll also add this page of documentation that describe Modifiers:
https://docs.unity3d.com/Packages/com.unity.behavior@1.0/manual/behavior-graph.html#modifier-node

I see, thank you for the explanation!

After further investigation, I’m facing another issue where my Sight looks for closest Target won’t get reached. Even if placed to the left, It only runs at first, finds the target and then the whole Tree hangs on the Parallel node.

This is important because Sight looks for closest Target also takes care of setting the target to null when losing sight of it, which would abort the parallel node.

This setup doesn’t work:

And putting a Repeat node before Sight looks for closest Target doesn’t work either, instead it makes the Tree hang on it.

It’s possibly an issue with my implementation, but I’m not sure how to address it.

It would take a bit to unfold your particular scenario. I’m leaving the office for the day soon but I can try to help tomorrow.

However, if you haven’t already, you might be interested into looking at the Webinar we did last year.
We also released a Behavior Demo that showcase implementation of similar AI brain using an hybrid FSM-BT approach.

Thank you for the link to the Webinar. You did a great job on the presentation and I learned a few new things.

After some more playing around, it seems that this setup does the trick:

The main change was replacing the Abort nodes with Conditional Guards parented to Repeat nodes. The Abort nodes didn’t work in this situation because they would fail once and the Tree would remain stuck on Sight Sense and repeat forever, not giving the others the chance to run again. Whereas the Conditional Guard is under Repeat nodes as well so it checks continuously.

I could be wrong and the Abort nodes might work just the same under Repeat nodes, but for now this does the trick.

Hopefully I won’t encounter any further issues.

Once again, thank you for the help!

P.S: Perhaps introducing a Repeating Parallel node could be a good idea, or adding it as another option to the current Parallel node if it makes any sense design-wise.

P.S #2: The Repeat While node seems to completely block the child from running when the conditions are not met.
Wouldn’t it make sense to still allow the flow from parent nodes to go through, but just not enter the repeating loop, so it basically acts like it doesn’t exist?
I don’t think it’s a good idea for this node to also act as a Conditional Guard.

Hi @Kreesty

There are so many different way you could achieve the same outcome with behavior tree, a Repeating Parallel might be too specific to your specific use case. Also, there are other way to achieve the same result, such as splitting all your repeatable parallel actions with their own OnStart node (right of the picture).

If you want the same conditional guard for several action, you could also use an AbortIf node and do like you do. The Abort will also act as a Conditional Guard and prevent execution of the RunInParallel in case the condition is not met when AbortIf is executed (left of the picture).

Finally, you could also use an EventChannel that send a state (enum) and use a Switch statement to emulate a state machine and have a behavior defined in states. Often easier to author and maintained. EventChannel can be a bit hard to grasp at first, so I recommend the documentation and having a look at the Behavior Demo. There is also a document in the demo that describe use case of different possible approach using the Behavior package.

Hope this helps :slight_smile:

1 Like