Devlog: Fixing Squad AI Freezing in Combat: A Deep Dive into Task Instancing and Delegate Binding - Keegen Love


This week I ran into an interesting and frustrating problem with our squad-based AI. The issue was that, while the first unit in the squad was working fine in combat, some of the other units would freeze during the AttackEnemy task in their Behavior Trees. This left them unresponsive, which, as you can imagine, wasn’t great for gameplay!

The issue got weirder when I noticed that it only happened after the first unit had completed its delegate binding/unbinding process. It was like the first unit was fine, but everything that came after that would break. To make things trickier, the problem didn’t seem to affect the EnemyChaserAI, so I thought there might be something unique happening with how the squad was set up.

Before diving into the fix, here's how we were originally handling delegate binding in the squad's behavior tree. This was using a flag (bAreDelegatesBound) to determine whether the delegate was bound to each squad unit's task. The idea was that when the flag was set to true, the task would bind to the unit and handle the actions.

Delegate Binding Segment in AttackEnemy

Task Resolution & Delegate Unbinding Segment in AttackEnemy

After digging around, I figured out the problem. The main culprit? The BTTask_AttackEnemy task. It turns out, we were only instantiating one BTTask_AttackEnemy object for the whole squad. And that single object was being shared across all the units.

The bAreDelegatesBound flag was set to true for the first unit to start the task binding, but because everyone was using the same task object, that flag stayed true for all subsequent units. This meant only the first unit could successfully bind to its delegate, while the others were stuck in a broken state.

At first, this seemed pretty cryptic, but I realized that the solution didn’t have to be complicated. Instead of relying on a flag system, I switched over to a MessageNotify system. Now, each squad unit could independently bind and unbind their delegates without interfering with others. Better yet, the task would no longer even need to manage delegates at all! It was like flipping a switch, and the AI stopped freezing!

Here’s the new approach. In this updated system, each squad unit listens for a message notification rather than relying on a global flag. This ensures that the units operate independently and can be bound/unbound without any interference from other units in the squad.



Now, when a unit's delegate is bound, the task instance properly handles the behavior of that specific unit without affecting the others. This change made a world of difference in fixing the freezing behavior.

Once I made the change, everything worked as expected. The squad AI stopped freezing, units could attack targets, and the camera tracking worked again. But looking back, it’s easy to see how the issue snuck past us. The core problem was that the BTTask_AttackEnemy task wasn’t properly instanced for each unit, and the shared reference led to a cascade of issues with delegate binding.

This problem made me realize just how far we’ve come in our development. We’re not dealing with basic issues like improper object references anymore, but with complex things like custom task instancing and inter-object communication. It’s a sign of the depth our systems have reached.

I also learned a lot about the power of message-based systems. Sometimes the solution isn’t about adding complexity, but simplifying the way objects interact with each other.

While it was a bit of a tricky bug to solve, I’m happy with how it turned out. It’s fascinating to work on AI at this level, where we need to think about things like how tasks are shared and how delegates bind. Looking back, it was one of those moments where the cause of the issue was something simple (but sneaky) that had a huge impact on the game.

I’m looking forward to tackling even more complex issues as we continue building our systems. Stay tuned for more updates!

Get Return to Divinity

Leave a comment

Log in with itch.io to leave a comment.