Blackboard decorator node not aborting on result or value change

Hi,

I have a blackboard decorator node in my behavior tree that’s set to abort “Both”. It’s observing an Actor.

When the observed Actor is destroyed in the level, the associated Blackboard Key immediately updates to None. But the decorator node fails to abort. This is true when I have Notify Observer set to either “On Result Change” or “On Value Change”.

I tried this in 4.15, 4.16, and 4.17; it happens in all of them.

Is this expected behavior? If so, how should I properly handle informing my behavior trees that their observed Actors are no longer valid when those Actors get destroyed?

Steps to reproduce:

  1. Create a new Third Person project
  2. Create a new blackboard asset, then add a new key (Key Type: Object. Base Class: Actor)
  3. Create a new behavior tree asset (see image below)
  4. Create a new AIController and have it RunBehaviorTree (from Event BeginPlay)
  5. Create a Pawn, place it in the default level (ThirdPersonExampleMap), and set its AI Controller Class to the one created above
  6. Use the Level Blueprint to set the value of the blackboard key (from step 2) to be the ThirdPersonCharacter in the level.
  7. On the ThirdPersonCharacter, set the Initial Life Span to 10.0
  8. Press Play. After 10 seconds, the ThirdPersonCharacter (i.e. the observed value) will be removed. But the blackboard decorator node in the behavior tree will fail to abort.

Hi I made the same observation in 4.19 did you find a solution? Or is it a bug?

This post seems to describe a related problem: Decorator Ticking Regardless of "Check Condition Only Black Board Changes" - AI - Unreal Engine Forums

This issue started occuring in my project after upgrading to 4.19 as well. I am hoping for a fix since it causes crashes on my services.

I am running into the same issue in 4.19.

After testing, it seems that the hangup occurs only when the Blackboard value is updated/nulled externally. For example, in my project, the “Target” BB value represents an Actor which is killed and destroyed. The following has been observed:

1) The BB Value Decorator correctly states that the value is “None,” but it does not abort the node.

2) If the BB Value is directly set to null from within a task node, the Decorator appropriately reacts and aborts the node.

This seems to be a bug, and hopefully someone from Epic can jump in here and shed some light.

This seems to be happening again in 4.26. Is this a bug?

I also find this behavior.

Is there a known solution or workaround?

For anybody else experiencing this problem, I have found an extremely clunky workaround, but it works. I suddenly experienced this bug (or at least something similar to it) on a project in which I had previously been using Coqui’s Animal Behavior Kit for several months – with no problems at all – but I was having (for at least the past several weeks) this fatal game-breaking bug that would inexplicably cause some AI’s to just get stuck forever once one of their Blackboard needs had changed (from Roam to Eat, from Roam to Drink, from Roam to Breed, for example).

Unfortunately, the solution (though certainly not an answer by any means) I came up with involves at least a small amount of C++, so admittedly, it may not be feasible for anybody who is needing it to actually implement it – and as far as I know, there is no / are no other ways to get a BTNode object reference from within Blueprints.

The workaround in brief is that: instead of trying to get the aborting behavior to work properly from within the Behavior Tree, I exposed one of the CPP / C++ functions of the UBehaviorTreeComponent to Blueprints, so that I could get the exact node that was still in the middle of being executed (i.e. leading up to) the next Blackboard value enum change (again, Roam → Eat, Roam → Drink, Roam → Breed), and manually call Finish Execute on it at that exact moment when the (in my case) Behavior Tree Service sets the next BiggestNeed AKA the next Blackboard value enum – which (that is, the changing-of-the-value itself) is responsible for, and is supposed to cause the current Sequence / Selector AKA the Sub-Tree, to abort, but which for some mysterious reason, does not.

(the includes are kind of a mess because I have a lot of other helper / debugging functions in there)




Source Includes

UFUNCTION(BlueprintCallable, meta = (DisplayName = "GetActiveNode"), Category = "AI Debug")
			static const UBTNode* GetCurrentNode(const UBTNode* ActiveNode, UBehaviorTreeComponent* InputBehaviorTreeComponent);
const UBTNode* UAIDebugBlueprintFunctionLibrary::GetCurrentNode(const UBTNode* ActiveNode, UBehaviorTreeComponent* InputBehaviorTreeComponent)
{

	ActiveNode = InputBehaviorTreeComponent->GetActiveNode();
	if (ActiveNode != NULL)
	{
		return ActiveNode;
	}
	return nullptr;
}
#include "AIDebugBlueprintFunctionLibrary.h"
#include "GameFramework/Character.h"
#include "BehaviorTree/BehaviorTreeComponent.h"
#include "BehaviorTree/BehaviorTreeTypes.h"
#include "BrainComponent.h"
#include "AIController.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "BehaviorTree/BTNode.h"
#include "Kismet/KismetSystemLibrary.h"

Hope this helps someone.

:pray:

I found that if task dont have abort node, it can’t be aborted by decorator.
So if you implement abort, you need run Finish Abort yourself.

Maybe it will be helpfull…


1 Like