Spawned pawn doesn't respond to AddMovementInput

I’ve modified the template TopDown controller to work nicely on multiplayer, and I set it up so if I touch a trigger, I call a SpawnActor function (as APawn), and then I call a function to possess it and to Destroy the original actor.

Everything works great, it gets destroyed, the new one gets spawned and possesed, but suddenly the click-to-move system doesn’t work anymore. I added debug lines, and it gets the clicks correctly (position, direction, distance), but the new object just won’t move.

The code for the SpawnActor:

APawn* playerPawn = world->SpawnActor(heroC, FVector(0, 0, 150), FRotator::ZeroRotator, SpawnParams);

The code for the movement:

APawn* const Pawn = GetPawn();
	if (Pawn)
	{
		Debug("Pawn found");
		Distance = FVector::Dist(clickLocation, Pawn->GetActorLocation());
		Direction = (clickLocation - Pawn->GetActorLocation()).Rotation().Vector();
		
		Debug(Direction.ToString());
		Debug(FString::FromInt(Distance));
		Pawn->AddMovementInput(Direction, Distance);}

Adding a movement component is supposed to work, but it hasn’t for me, so I suggest inheriting from DefaultPawn instead of Pawn.

Need to set the AddInput to true, try this.

  Pawn->AddMovementInput(Direction, Distance, True);}

Have you given a value to MovementComponent in your custom APawn object’s constructor and set the MovementComponent’s UpdatedComponent to the root component of your custom pawn?

// Create dummy root scene component.
DummyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("Dummy0"));
RootComponent = DummyRoot;

/* Attach stuff like static meshes to the dummy root here */

// Create the movement component and set the updated component for it.
MovementComponent = CreateDefaultSubobject<UPawnMovementComponent, UFloatingPawnMovement>(ADefaultPawn::MovementComponentName);
MovementComponent->UpdatedComponent = DummyRoot;

A good way of figuring out stuff like this is to look through code for similar classes in the engine. In this case, DefaultPawn’s source code.

I’ve encountered this, am I right in assuming it does work on the server, but not on a remote client?

If so, the issue is caused by the fact that the server notifies the client that it is possessing a new pawn, but that pawn isn’t replicated to the client yet. Although it may seem weird, try overriding OnRep_Pawn() in your controller class like this, this enforces the client to acknowledge the pawn possession right when the new pawn is initialized client-side.

MyPlayerController.h:

virtual void OnRep_Pawn() override;

MyPlayerController.cpp:

void AMyPlayerController::OnRep_Pawn()
{
	Super::OnRep_Pawn();
	if (!HasAuthority() && GetPawn() != AcknowledgedPawn)
		ChangeState(NAME_Inactive);
}

I’ve encountered this, am I right in assuming it does work on the server, but not on a remote client? If so, the issue is caused by the fact that the server notifies the client that it is possessing a new pawn, but that pawn isn’t replicated to the client yet. Although it may seem weird, try overriding OnRep_Pawn() in your controller class like this, this enforces the client to acknowledge the pawn possession right when the new pawn is initialized client-side.

Note: There is a retry mechanism in place that should trigger

MyPlayerController.h:

virtual void OnRep_Pawn() override;

MyPlayerController.cpp:

void AMyPlayerController::OnRep_Pawn()
{
	Super::OnRep_Pawn();
	if (!HasAuthority() && GetPawn() != AcknowledgedPawn)
		ChangeState(NAME_Inactive);
}