I’m learning Smart Objects and have a simple set up where on BeginPlay my NPCs scan for smart objects and pick one at random to move to and use. The behavior tree runs one task to find the SO and get its claim handle, then the next task handles moving-to-and-using:
Everything has been working as expected. My NPCs move to the claimed SO, and run the Gameplay Behavior I’ve configured.
But, I noticed that this “Move to and Use Smart Object with Gameplay Behavior” node always returns “On Failed” even though my NPCs are successfully “moving to and using” my objects.
So while it’s not impacting anything in a player facing way yet, it’s still unexpected behavior that I worry could lead to problems later, but I can’t find anything in the docs about this node. I am wondering if anyone can point me in the right direction or has a deeper knowledge of the C++ side and what conditions should be triggering these outputs?
TLDR: why is “Move To And Use Smart Object With Gameplay Behavior” node only ever returning as “failed” when it seems to be succeeding?
Inside the smart object’s Gameplay Behavior class, inserting a delay anywhere before calling EndBehavior allows the "Move To and Use Smart Object with Gameplay Behavior" node (the one run by the BTTask, shown in my first post) to return Succeeded.
I discovered this because I had changed my code for other reasons, making it so that EndBehavior wasn’t triggered anyway until receiving an event dispatcher from elsewhere (thus creating a “delay” incidentally).
But I also tested this with a barebones set up inside the Gameplay Behavior and got the same results:
-Same as in my first post, my NPCs will still correctly claim, use, then release my smart objects even without the enforced delay, so I still don’t know what specifically under the hood is “failing” there, but at least now it’s possible to detect successes.
**
**
(btw, in testing, this type of delay node did not work, only the “Set Timer By…” types did):
I ran into this issue while following the Smart Object Quick Start from the docs inside a Lyra project using 5.6. I only have a slight idea as to why this happens, in AITask_UseGameplayBehaviorSmartObject.cpp it only calls OnFailed in one place in OnDestroy():
if (TaskState != EGameplayTaskState::Finished)
{
if (GameplayBehavior != nullptr && bBehaviorFinished)
{
OnSucceeded.Broadcast();
}
else
{
OnFailed.Broadcast();
}
}
The only thing I can think of is that OnDestroy() is getting called before the BP has called EndBehavior (BP VM shenanigans). So far, using the SetTimerForNextTickByEvent node seems to work since I want to reduce the amount of delays being used which might run longer than one tick.