canMove overridden when using Behavior Designer Tactical pack

I’m using the Opsive Behavior Designer Tactical Pack with the A* Pathfinding integration, and all is working well except I’m not able to make the agent stop moving using _aipath.canMove = false, because canMove’s value seems to get overridden to be true. I check in the Update calls and it’s false for a few ticks but then suddenly turns true (even when I have no code that sets it to true). I’m assuming it’s reset by some logic in the integration code.

This is the behavior tree. The Attack task is from Add Task => Actions => Tactical => A* Pathfinding Project => Attack.

My use case is I want to make the agent stay in place during its attack animation. Currently, because canMove doesn’t stay false, the agent slides as it continues chasing the target.

I’ve also tried it in conjunction with _aipath.SetPath(null); and _aipath.canSearch = false;. _aipath.canSearch stays false, but the path still becomes populated (_aipath.hasPath returns true), _on the same tick_ that canMove` becomes true.

Should I assume that when I’m using the Behavior Designer A* integration to drive the pathing behavior, I’ve ceded control to it and won’t be able to manually call canMove? My current workaround is to use an AIDestinationSetter to set the target to the agent itself so it stops moving, then reset it to the actual attack target once the attack animation completes. This works, but seems like a hack. What is the proper way to handle my use case?

Hi

Since this is an issue with the integration itself, I think Opsive, who are the ones who have made the intergation, will be able to help you better. I am not very familiar with the integration code, I’m afraid.

Ok thank you, I will reach out to them!

Closing the loop here in case anyone has the same problem in the future. What I ended up doing was patching the Behavior Designer Tactical package code, because I figured it was fastest way to get a working solution. The package hasn’t been updated on the Unity Asset Store for over four years, so I’m not likely to run into any merge conflicts from package updates.

The two files I edited were the IAttackAgent interface and the Attack task (Behavior Designer Tactical\Scripts\Interfaces\IAttackAgent.cs and Behavior Designer Tactical\Integrations\Astar Pathfinding Project\Tasks\Attack.cs).

  1. To IAttackAgent I added an optional method bool CanMove() similar to the existing bool CanAttack(). Because the package already requires implementing IAttackAgent on whichever object is the attacker, managing both similar fields from that one interface seems sensible.

New code:

// Optional method that returns true by default, preserving any existing behavior,
// but allowing for new IAttackAgent instances to implement additional logic.
// For me, the IAttackAgent was a melee unit that needs to walk to the target to attack.
bool CanMove() { return true; }
  1. Then in the Attack task, I added a check in OnUpdate for whether the attacker can move, right before the MoveToAttackPosition() method is called.

Existing code:

if (MoveToAttackPosition()) {
  tacticalAgent.TryAttack();
}

New code:

// Short-circuit exits when CanMove() is false, so the move attempt won't be made.
if (tacticalAgent.AttackAgent.CanMove() && MoveToAttackPosition()) {
  tacticalAgent.TryAttack();
}

This is just the way I solved my problem. There may be a more “proper” way of doing it, but this was the fastest without digging deeper into the Behavior Designer package code and writing a custom task, or contacting their support.

1 Like