Pawn Possession Fails in 4.6.1

Since moving to 4.6.1 possession of a players pawn fails frequently in our multiplayer game.

I’ve confirmed this by migrating our code back to 4.5.1 and used the same situations/scenarios that were causing the player to not gain possession of their pawn in 4.6.1 only to have it work every time.

Is there anyone at Epic who can possibly point me in the direction of changes that could have affected pawn possession over a network? Perhaps there’s a change that I’m unaware I need to make?

Reading the release notes possession is only mentioned once, and in a comment, but something clearly has changed.

From IRC:

iniside: overlawled: i had similiar problem on 4.7

iniside: it was connected to overrideing BeginPlay() and OnRep_Pawn() in player controller, and assinging pawn to other object twice

Testing this now

The above was not the cause.

When the player respawns and ClientRestart is called on the server the pawn has a value but on the client the pawn passed into ClientRestart is NULL when it is initially called.

When called the second time (automatic retry) the pawn is NOT NULL and the controller is able to successfully possess it.

Just to further confirm that this is what’s happening I added a ClientMessage call right after the call to ClientRestart. The name of the Pawn comes through just fine.

It should also be noted that in fact the very first ClientRestart call when a player joins also fails, but the retry is called instantly. Looks like attempting to pass it that first time is where the issue lies…

Forgot to add as well that the pawn exists on the client and in fact has the same name as it does on the server, just cannot control it.

This also does not occur in the editor with dedicated server selected. This only occurs when running the server and client outside of the editor.

Willing to put the project up somewhere so someone at Epic can take a look if needed.

When the player respawns and ClientRestart is called on the server the pawn has a value but on the client the pawn passed into ClientRestart is NULL when it is initially called.

This does not happen in 4.5.1. The client receives a value on the first call of ClientRestart.

Hi overlawled, as you probably saw John Pollard suggested on the forum you try something with async loading. I also want to see if something we’ve changed since 4.6 fixes this for you. In APlayerController::ClientRestart_Implementation() there is a line that checks if the pawn is null and just returns, replace it with this:

	if ( GetPawn() == NULL )
	{
		// We failed to possess, ask server to verify and potentially resend the pawn
		ServerCheckClientPossession();
		return;
	}

Hi Zak,

Unfortunately neither this nor the other suggestion fixed this. I’ve done more digging and below is the relevant log messages from that digging.

Most important to note is that it appears that at some point immediately after the first APlayerController::ClientRestart after death the client DOES get a reference to the correct pawn but doesn’t acknowledge it with the server.

This reference to the pawn is provided by AController::OnRep_Pawn() but is not acknowledged, and as a result of it not coming through APlayerController::ClientRestart APawn::SetupPlayerInputComponent is never called which is why the player does not gain control of the pawn.

Anyways, the logs attached.

So to test my previous findings I overrode the AController::OnRep_Pawn() function and added all the acknowledge code from APlayerController::ClientRestart.

AcknowledgePossession(GetPawn());

GetPawn()->Controller = this;
GetPawn()->PawnClientRestart();

if (Role < ROLE_Authority)
{
	ChangeState(NAME_Playing);
	if (bAutoManageActiveCameraTarget)
	{
		AutoManageActiveCameraTarget(GetPawn());
		ResetCameraMode();
	}
}

This fixed my issue and the player successfully gains control of their Pawn when they should.

I’d do it at the engine level and commit but I’m not sure this is an issue anyone beyond myself has had.

Realistically the real cause of the issue is that ServerCheckClientPossession() fails to get to the server over the course of 5-10 seconds, when when connecting to the loopback address.

Zak,

Not sure whether to make this change at the engine level and commit.

The issue is affecting me as well. OnRep_Pawn is somewhat Unreliable on the Server and corresponding clients, and although I can possess a pawn, i don’t get any control over it.

I’m getting the same issue in Blueprints. Simply asking a player controller to possess a new pawn over the network simply doesn’t work correctly.

That change makes some sense, but I’d like to dig in to why things are broken. There has always been some cause for concern since variable replication can lag behind function replication. The call to ServerCheckClientPossession() should handle the case where the Pawn came over as null, and ask for the server to re-call the method. It’s concerning that this appears to be broken.

Zak,
Would it help if I provide you with our project?

That might help, yes. Someone provided a project with entering/exiting a car I believe, I haven’t had a chance to look at it yet.

Just wanted to update you that some people here are still looking in to this issue.

Zak,

Where can I send our project to? I’ll send the source/assets to the last build we had moved to 4.6.1.

A link to dropbox is probably easiest, or another external link. If you don’t want it to be public you can send me or Adam a private message on the forums with the link.

Please check the AnswerHub post here for an explanation of the networking issues going on in the GTA vehicle project, with a solution provided as well.

I haven’t seen your project yet but based on what you describe this sounds like the same issue.
The most important takeaways are:

  1. Only use “Possess” on the server. We will fix future releases to make this more clear and enforce it correctly.
  2. Only spawn/destroy Pawns on the server if they can be possessed. Ideally you won’t need to destroy and spawn the Pawn in these scenarios, but it can be made to work.

Hey Zak,

I’ll get you the project later tonight or early tomorrow morning. I’m fairly certain that destruction and possession is all happening on the server but I’ll double check.

Quick look of it though is damage is only applied on the authority, and upon pawn death we start a timer on the server that respawns the pawn on the server.

GetWorldTimerManager().SetTimer(PC, &APlayerController::ServerRestartPlayer, 5.f);