Has anyone had any experience in writing custom BTTasks?
I’m currently working on some flying AI and I’ve setup my aicontroller to handle flying movement, but I’m not sure how to handle moving from EBTNodeResult::InProgress to EBTNodeResult::Succeeded.
My current task code is below:
#include "MyGame.h"
#include "DragonController.h"
#include "BTTask_FlyTo.h"
UBTTask_FlyTo::UBTTask_FlyTo(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
, arriveDistance(50.f)
{
NodeName = "Fly To";
}
EBTNodeResult::Type UBTTask_FlyTo::ExecuteTask(UBehaviorTreeComponent* OwnerComp, uint8* NodeMemory)
{
UBehaviorTreeComponent* MyComp = OwnerComp;
FBTFlyToTaskMemory* MyMemory = (FBTFlyToTaskMemory*)NodeMemory;
ADragonController* MyController = MyComp ? Cast<ADragonController>(MyComp->GetOwner()) : NULL;
if (MyController == NULL)
{
return EBTNodeResult::Failed;
}
const UBlackboardComponent* MyBlackboard = OwnerComp->GetBlackboardComponent();
if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass())
{
const FVector targetLocation = MyBlackboard->GetValueAsVector(BlackboardKey.GetSelectedKeyID());
const FVector currentLocation = MyComp->GetOwner()->GetActorLocation();
float distance = FVector::Dist(currentLocation, targetLocation);
if (distance <= arriveDistance)
{
return EBTNodeResult::Succeeded;
}
//AI messaging stuff? I Assume
const FAIRequestID RequestID = MyController->GetCurrentMoveRequestID();
MyMemory->MoveRequestID = RequestID;
WaitForMessage(OwnerComp, UBrainComponent::AIMessage_MoveFinished, RequestID);
MyMemory->MoveRequestID = RequestID;
MyController->FlyToTarget(targetLocation, arriveDistance);
return EBTNodeResult::InProgress;
}
return EBTNodeResult::Failed;
}
And my Ai Controller function for flying is:
void ADragonController::Tick(float DeltaTime)
{
UpdateMovement();
}
void ADragonController::FlyToTarget(FVector newTarget, float newArriveDistance)
{
target = newTarget;
flying = true;
arriveDistance = newArriveDistance;
}
bool ADragonController::GetFlying()
{
return flying;
}
void ADragonController::UpdateMovement()
{
if (flying)
{
const FVector currentLocation = GetPawn()->GetActorLocation();
const float distance = FVector::Dist(currentLocation, target);
if (distance <= arriveDistance)
{
flying = false;
}
else
{
FVector direction = target - currentLocation;
direction.Normalize();
MoveInDirection(direction);
}
}
}
void ADragonController::MoveInDirection(const FVector moveDirection)
{
ADragon* MyBot = Cast<ADragon>(GetPawn());
if (MyBot)
{
MyBot->AddMovementInput(moveDirection, 10000.0f);
}
}
Is there a way to fire off a message from the controller to indicate that the task has finished executing? The only way I can think right now would be providing the controller with a reference to the task and having the controller manually call OnFinishExecute.
Any help would be greatly appreciated.