C++ BTTask Finish Execute

Cast(GetOuter()) fails for your node because it’s not instanced (bCreateNodeInstance set to true). So one solution would be to mark it as such. Another solution would be to get your hands on BTComponent instance in a case-specific way (depending on your specific code). You need find you BTComp first, since the only way to finish a node is to call function on it (OnTaskFinished in this case). Our BTs are not instanced per user, it’s just the BTComponent operating on the BT as a skeleton instantiating only the runtime data - this way it scales better with number of agents.

Cheers,

–mieszko

The “case-specific” approach depends on the case :slight_smile: You just need to supply your code with some kind of a reference to the agent being controlled/affected by the task, get it’s controller and extract the brain component from it. The brain component in this case should be a BT component.

Hey so I’m creating an AI using behaviour trees and recently got stuck on a problem where I need to finish execution of a BT task after a certain point in time.

I created a task where it makes the enemy perform an attack. Using an anim-notify I fire off an attack complete event that broadcasts the attack-complete event. When it receives this, I want the task to end successfully.
The code I’m trying to execute is this:

I’ve scrounged around at the BTTask_BlueprintBase code to see how to use FinishTask, which basically calls ontaskfinished on the ownercomp. They get the ownercomp by basically casting the object that is retrieved from GetOuter(), but when on execution, casting that object returns a null pointer (in my code). This leads to the task never being able to complete. However, the task works fine when I create the blueprint version as shown below:

Anyone know how I may go about implementing FinishExecute in C++?

Hello Mieszko, thank you so much for the answer. Setting bCreateNodeInstance to true, and making a few other minor changes seemed to work.

As a side note, which is a better practice, to create a node instance or to handle it in a case specific manner? Also if it were a case-specific manner what would you need to do find the BTComp?

Also, to any others who might see this and try the same thing as I, in the code I supplied above I called GetOwner()->GetOwner() (Because I was experimenting on making it work), you only need to call it once. Also, dont call OwnerComp->OnTaskFinished() directly, since it seemed not to work. Instead call FinishLatentTask(*OwnerComp, EBTNodeResult::Succeeded); Furthermore, if you use event dispatchers like I did, you’ll need to remove the binded function from the event dispatcher, or you’ll run into problems.

1 Like

Cool, thanks for the information :slight_smile:

Thank you @MieszkoZ, in this case, let’s say that I prefer not to create a node instance, would it be ok to store the BTComp received from the ExecuteTask and access it from the AttackComplete implementation later, or are there any risks that the BTComp is deallocated ?