my solution : I implemented a C++ service (subclass of UBTService) whose purpose is to reference the task currently holding it into the AI controller (see UBTAuxiliaryNode::GetMyNode() for how to get current holder node). I added such a referencer node as service on the MoveTo node. Then, when I detect I need to stop the MoveTo task (like when actor gets out of sight range using the perception system), I just need to get to the referenced task node in my AI controller and call UBTTaskNode::WrappedAbortTask() on it.
@eyosido Can you maybe send a Screenshot of your code? I don’t really know how you did it.
This is an old topic and there are many conflicting ideas for making this work spread across the forums. Here’s what I feel is the most elegant solution for UE5 using just a few very simple custom nodes.
Use case is the following: the AI agent should MoveTo a TargetActor. If during movement the TargetActor becomes unavailable, abort the MoveTo.
First of all, your MoveTo node needs “Observe Blackboard Value” enabled in the details panel. Here’s a simple node structure with just a single condition:
We use a SimpleParallel node with finish mode “Immediate”. The main branch of which executes the MoveTo.
The side branch has a custom Empty task which literally does nothing (=return succeeded). We Loop this task indefinitely until a given decorator condition evaluates to true. In my case, I am checking whether TargetActor cannot be equipped to the pawn’s equipment slot. If true, we want to abort.
Once this condition becomes true, the custom ClearBlackboardValue service node will be executed and it simply clears whatever value we have for TargetActor in the Blackboard. Thanks to “Observe Blackboard Value” the MoveTo will be aborted. You can also change the TargetActor to a different one, your AI agent will instead move towards the new TargetActor.
If the MoveTo finishes successfully then the looping of the Empty task will be aborted thanks to the SimpleParallel.
In case you still need the TargetActor after clearing, a simple copy of the blackboard key should be made beforehand.
You can add more AND conditions by adding more decorators to the Empty node.
You can add more OR conditions by adding more Empty tasks in a sequence and then looping the entire sequence.
just need a decorator that compare actor location of ai and character in your moveto task
Here I am a year later and find that when your condition for aborting the MoveTo is very simple then you’re better served just implementing an abort in your decorator (or use the existing abort functionality of built-in decorators).
This is the same MoveTo as posted above, but aborts itself without the need for all of those other nodes.
The thing I missed is twofold:
- Set the decorator’s “Observer aborts” to “Self”. This makes it so that if the decorator requests an abort the node it is attached to (=self) will be aborted. You could also set this to “Lower priority” to abort all lower priority nodes or to “Both” if that makes more sense for your use case.
- Make sure your custom decorators actually execute an abort when needed. This can for example be done in
TickNode
but for better performance you may want to bind an event inOnBecomeRelevant
instead.
Either way, this is what I did with my decorator:
void UBTDecorator_EquipmentQuery::InitializeFromAsset(UBehaviorTree& Asset)
{
Super::InitializeFromAsset(Asset);
// Only need to tick if we actually have a BTFlowAbortMode specified
bNotifyTick = FlowAbortMode != EBTFlowAbortMode::None;
}
void UBTDecorator_EquipmentQuery::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, const float DeltaSeconds)
{
// If this decorator's condition fails
if (!CalculateRawConditionValue(OwnerComp, NodeMemory))
{
// Abort this branch
OwnerComp.RequestExecution(this);
}
}
No clue whether this is exposed to Blueprint.
Also if you need complex AND/OR combinations of conditions then the previous SimpleParallel is likely still the way to go for flexibility. But this solution is better for anything else.