Problems in combining the krazy karts with the previous section

First of all I want to say that i loved this course, it was really well structured and helped me understand the topic immensely.
But now i have a little problem, i tried to combine the krazy karts section with the previous one in order to have a complete project but something isn’t correct and I don’t really know what i’m missing.

The steam oss seems to work fine, the client finds the server and they connect without a problem but after the seamless travel in the client the simulated proxy doesn’t move (in fact it seems like the pawn doesn’t receive the serverstate rep) but in the server everything works.
Another strange thing is that if I play whitout using steam (starting the game in the map with multiple players) everything works. I don’t really understand whats the problem here and I really need some help.

I’m using UE 4.24

The game is running on two different machines? Strange that it wouldn’t get the State rep. If you are still struggling why not send your project my way so I can test it. https://gdev.tv/projectupload

yes and with 2 steam account. Anyway i’ve just send to you the project (I’ve removed the binaries in order to make it smaller I hope i did it well)

Before I dive head long into debugging this for an hour, a few more questions…

Have you put logging in to see where the state is getting to?
Does the move get created? Does it get sent to the server? Does the server receive the move? Is the data populated in the move the server receives? Does it replicate back correctly? Is the position getting updated?

Once you’ve had a look at those yourself I can dive in and have a look.

In the tests that i’ve done the client pawn is working (both in the client and in the server the pawn moves and replicates correctly).
The only things that seems to fail in the server is that the if statement (GetOwner()->GetRemoteRole() == ROLE_SimulatedProxy) return false (but this isn’t the case if i start playing directly in the map in the editor)

So, that if statement should only be true for the server pawn. I thought the issue was with the client not moving?

Oh, wait, are you saying the server pawn isn’t replicating to the client? Then it’s worth looking into that. You’re saying that if statement fails on the server? Your sure it’s failing for the server pawn and not the replicated client’s pawn? If so, what are the remote roles listed as?

Yes the server pawn isn’t replicating to the client. I’m pretty sure that is failing on the server’s pawn in the client since the code in the if statement doesn’t ever been called (i tried to add a log). The role of the actor are AutonomousProxy for the client’s pawn and SimulatedProxy for the server one but if I try to print the remote role unreal crashes but only after joining the server.

But what is the remote role for the server’s pawn on the server? Is the if statement getting called there (that’s where it should be getting called).

On the server the server’s pawn have AutonomousProxy as remote role so that’s why the if statement isn’t getting called there.

Hello @iNOTme,

I believe I was having the same problem as you - input sometimes not working on client after server travel (actually, it did not work much more often than it did) . As a matter of fact, while searching for answers myself, I have seen this kind of behavior happening to a lot of other users. The common issue here seems to be the server travel. So let me share my findings, maybe they help.

After a lot of logging and debugging, I was able to pinpoint the problem, in my case, at least, to the SetupPlayerInputComponent() method in the pawn. Sometimes, the method simply did not get called because of some weird conditions depending on how pawns are spawned and posessed remotely. If you want, to can try for yourself, adding some logging in the method, overriding some other spawn/possess methods of Pawn and PlayerController, and adding some logging in there, etc.

The first and naive solution I came up with was to force the recompute of the player input. In my player controller, I overriden the OnRep_Pawn() method (you would need to have your own player controller extending from the default one) :

void AMyPlayerController::OnRep_Pawn()
{
	if (GetPawn<AMyPawn>() != nullptr) {
		UE_LOG(LogTemp, Warning, TEXT("onrep pawn %s"), *GetPawn< AMyPawn>()->GetFName().ToString());
		GetPawn< AMyPawn>()->RecomputePlayerInput();
	}
}

and then, obviously implementing the RecomputePlayerInput() method in my pawn. Please note that this implementation is actually just a striped-down copy-paste from APawn::PawnClientRestart()

void MyPawn::RecomputePlayerInput()
{
	if (InputComponent == nullptr)
	{
		InputComponent = CreatePlayerInputComponent();
		if (InputComponent)
		{
			SetupPlayerInputComponent(InputComponent);
			InputComponent->RegisterComponent();
			if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
			{
				InputComponent->bBlockInput = bBlockInput;
				UInputDelegateBinding::BindInputDelegates(GetClass(), InputComponent);
			}
		}
	}
}

However, I later realized that there’s a much easier way - handling input inside the player controller, and not in the pawn. The player controller is free from such replication/spawning/possessing issues, and will just forward the input to the pawn. So I removed the SetupPlayerInputComponent() from my pawn, and I added it in my player controller ( virtual void SetupInputComponent() override; )

void AMyPlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();
	InputComponent->BindAxis("MoveForward", this, &AMyPlayerController::MoveForward);
	InputComponent->BindAxis("MoveRight", this, &AMyPlayerController::MoveRight);
}

void AMyPlayerController::MoveForward(float Input)
{
	if (GetPawn<AMyPawn>() == nullptr) return;
	GetPawn<AMyPawn>()->MoveForward(Input);
}

Not sure if this is the best way, but it looks pretty clean and I really hope this gets your issues fixed :slight_smile: