Quick answer: MoveToLocation returns Failed when the AI controller cannot find a valid path to the target. The most common cause is a missing or improperly configured NavMesh. Ensure a NavMeshBoundsVolume exists in your level and that it covers the area the AI needs to navigate.
Here is how to fix Unreal ai moveto not working. You call MoveToLocation or MoveToActor on your AIController, and nothing happens. The AI pawn stands still. No error in the Output Log, no movement, no callback. This is one of the most frustrating silent failures in Unreal Engine, because the MoveTo system fails without telling you why. The fix usually comes down to one of four missing pieces.
The Symptom
You have an AI-controlled pawn or character in your level. You call AAIController::MoveToLocation() or AAIController::MoveToActor() from C++ or the equivalent Blueprint node, and the function either returns EPathFollowingRequestResult::Failed or appears to succeed but the pawn never physically moves. There is no crash and no error printed to the log. The pawn simply stays where it was spawned.
In the behavior tree variant of this problem, the MoveTo task node completes instantly with a failure result, and the tree moves to the next branch or aborts. You may not even notice the failure unless you are watching the behavior tree debugger closely.
What Causes This
1. No NavMesh in the level. This is the most common cause by a wide margin. The MoveTo system relies on the navigation system to compute a path from the pawn's current location to the target. If there is no NavMeshBoundsVolume in the level, or if the volume does not cover the area where the AI needs to walk, the pathfinding query returns no result and MoveTo fails immediately. Press P in the viewport to toggle NavMesh visualization — if you do not see a green overlay on the floor, that is your problem.
2. Pawn has no movement component. The path following component on the AI controller needs a movement component on the possessed pawn to actually execute movement. If you are using ACharacter, you get UCharacterMovementComponent automatically. But if you are using a raw APawn subclass, there is no movement component by default and you must add one yourself.
3. AI controller is not possessing the pawn. MoveTo operates through the controller-pawn relationship. If GetPawn() returns null when MoveTo is called, the request is silently discarded. This happens when you spawn a pawn but forget to call Possess(), or when the pawn's AutoPossessAI is set to Disabled.
4. Target location is off the NavMesh. If the destination point is not on or near the navigation mesh, the pathfinding query fails. This often happens when you pass a world location that is slightly above or below the navigable surface, or when the target is inside a wall or obstacle that carves the NavMesh.
The Fix
Step 1: Add and configure the NavMesh. Place a NavMeshBoundsVolume in your level and scale it to encompass all navigable floor surfaces. Then rebuild navigation paths.
// Verify NavMesh exists at runtime before calling MoveTo
void AMyAIController::MoveToTarget(FVector TargetLocation)
{
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
if (!NavSys)
{
UE_LOG(LogTemp, Error, TEXT("No navigation system found. Add a NavMeshBoundsVolume."));
return;
}
FNavLocation NavLocation;
bool bOnNavMesh = NavSys->ProjectPointToNavigation(TargetLocation, NavLocation);
if (!bOnNavMesh)
{
UE_LOG(LogTemp, Warning, TEXT("Target location is not on the NavMesh."));
return;
}
MoveToLocation(NavLocation.Location, 50.f);
}
Step 2: Ensure the pawn has a movement component. If you are using a custom pawn class rather than ACharacter, add a movement component in the constructor.
// In your custom pawn constructor
AMyAIPawn::AMyAIPawn()
{
// Add floating pawn movement for AI navigation
MovementComponent = CreateDefaultSubobject<UFloatingPawnMovement>(TEXT("MovementComponent"));
MovementComponent->MaxSpeed = 600.f;
MovementComponent->Acceleration = 2048.f;
// Ensure AI controller possesses this pawn when spawned
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
AIControllerClass = AMyAIController::StaticClass();
}
Step 3: Verify controller possession and log the MoveTo result. Always check the return value of MoveTo so failures do not go unnoticed.
void AMyAIController::BeginPlay()
{
Super::BeginPlay();
if (!GetPawn())
{
UE_LOG(LogTemp, Error, TEXT("AIController has no possessed pawn!"));
return;
}
FVector Destination = FVector(1000.f, 500.f, 0.f);
EPathFollowingRequestResult::Type Result = MoveToLocation(Destination, 50.f);
switch (Result)
{
case EPathFollowingRequestResult::Failed:
UE_LOG(LogTemp, Error, TEXT("MoveTo failed. Check NavMesh and movement component."));
break;
case EPathFollowingRequestResult::AlreadyAtGoal:
UE_LOG(LogTemp, Log, TEXT("Pawn is already at the goal location."));
break;
case EPathFollowingRequestResult::RequestSuccessful:
UE_LOG(LogTemp, Log, TEXT("MoveTo request accepted. Pawn is moving."));
break;
}
}
Related Issues
If your AI moves but your replicated state is not updating on other clients, see our guide on replicated variables not syncing. If the AI works in the editor but your packaged build crashes before you can test it, check out fixing packaged build crashes on startup.
Press P in the viewport. If there is no green, there is no NavMesh.