MoveTo is not working!

Hello I am trying to move AI using ACharacters AIController class. It runs the behavior tree but it says the path is invalid even tho I have set the path to be just meter away from the character!

Critter.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/BehaviorTree.h"
#include "Components/SphereComponent.h"
#include "GameFramework/Character.h"
#include "Perception/PawnSensingComponent.h"
#include "Critter.generated.h"

UCLASS()
class LVL_RUSALKA_API ACritter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ACritter();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	

	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AI")
	UBehaviorTree* BehaviorTree;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AI")
	UPawnSensingComponent* PawnSensingComponent;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	UFUNCTION()
	void PawnSighted(APawn* pawn);
};

Critter.cpp:

// Fill out your copyright notice in the Description page of Project Settings.


#include "Critter.h"

#include "AIController.h"

// Sets default values
ACritter::ACritter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	PawnSensingComponent = CreateDefaultSubobject<UPawnSensingComponent>("Pawn Sensing");

	
	PawnSensingComponent->SightRadius = 60;
	PawnSensingComponent->SensingInterval = 0.25f;
	

	PawnSensingComponent->OnSeePawn.AddDynamic(this, &ACritter::PawnSighted);
}

// Called when the game starts or when spawned
void ACritter::BeginPlay()
{
	Super::BeginPlay();
	
		
		
	AAIController* aiController = Cast<AAIController>(GetController());
	aiController->RunBehaviorTree(BehaviorTree);


}

// Called every frame
void ACritter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void ACritter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

void ACritter::PawnSighted(APawn* pawn)
{
	
	FString message = TEXT("Saw Actor ") + pawn->GetName();
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, message);

	//UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
	
}

Behavior tree task:

H:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_FollowWaypoints.generated.h"

/**
 * 
 */
UCLASS()
class LVL_RUSALKA_API UBTTask_FollowWaypoints : public UBTTask_BlackboardBase
{
	GENERATED_BODY()

public:
	UBTTask_FollowWaypoints(const FObjectInitializer& ObjectInitializer);
	
	
	virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory);

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Waypoints")
	TArray<FVector> Waypoints;
	
};

CPP:

// Fill out your copyright notice in the Description page of Project Settings.


#include "BTTask_FollowWaypoints.h"

#include "AIController.h"
#include "GameFramework/CharacterMovementComponent.h"


UBTTask_FollowWaypoints::UBTTask_FollowWaypoints(const FObjectInitializer& ObjectInitializer)
{
	bCreateNodeInstance = true;
	NodeName = "Pathfinding";
}

EBTNodeResult::Type UBTTask_FollowWaypoints::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	

	FPathFollowingResult result = OwnerComp.GetAIOwner()->MoveTo(Waypoints[0]);


	if(result.Code == EPathFollowingResult::Type::Success)
	{
		UE_LOG(LogTemp, Warning, TEXT("Waypoint arrived to : %f"), Waypoints[0].X);
	}
	else if(result.Code == EPathFollowingResult::Type::Blocked)
	{
		UE_LOG(LogTemp, Warning, TEXT("Waypoint blocked to : %f %f %f"), Waypoints[0].X, Waypoints[0].Y, Waypoints[0].Z);
	}
	else if(result.Code == EPathFollowingResult::Type::Aborted)
	{
		UE_LOG(LogTemp, Warning, TEXT("Waypoint aborted to : %f %f %f"), Waypoints[0].X, Waypoints[0].Y, Waypoints[0].Z);
	}
	else if(result.Code == EPathFollowingResult::Type::Invalid)
	{
		UE_LOG(LogTemp, Warning, TEXT("Waypoint invalid to : %f %f %f"), Waypoints[0].X, Waypoints[0].Y, Waypoints[0].Z);
	}
	else if(result.Code == EPathFollowingResult::Type::OffPath)
	{
		UE_LOG(LogTemp, Warning, TEXT("Waypoint offpath to : %f %f %f"), Waypoints[0].X, Waypoints[0].Y, Waypoints[0].Z);
	}
	
	return EBTNodeResult::Succeeded;
}

It keeps showing me the result of Invalid and character is standing still. Someone please help!

Do you have a NavMeshBoundsVolume in your level? Is the actor and the destination inside it?

Yes NavMesh Volume

I don’t think you should just use the MoveTo function like that. Either create a FAIMoveRequest struct first and set some of its parameters like Use Pathfinding or ProjectGoalLocation, or maybe use the MoveToLocation function of the AI Controller which has those as arguments (and basically creates the request behind the scenes)

Other than that, enable Visual Logging, and try running the task, it should show you some more information that might help you identify the problem.

You might see logs like this:
image
Perhaps it can give some more info on what is causing the issue

Thank you very much I will try it now.

Ok I used only MoveTo and what I did was lower navigation mesh bounds volume by LITERALLY 1 MILIMETER and it works now… Thank you all.

1 Like