Download

Server Pawn Possession Bug/Problem? (Please Help)

I don’t know if this is a bug or i’m just a bad programmer but i have set up a GTA style pawn possession where the player gets into and out of car’s. It all works well on “offline” mode but it doesn’t work when i enable ‘run with dedicated server’ mode.

Before you say “the code haves to execute on the server in order for it to work” every bit of my code IS running on the server, and for the most part my code works. It does possess the vehicle pawn and it does destroy my character, But i can’t control the vehicle almost as if its frozen/crashed but it isn’t because the ‘fps’ indicator is still running.

here is my code :



PlayerController->UnPossess();

if (PlayerController->GetPawn() == NULL)
{
	PlayerController->Possess(Cast<APawn>(VehicleToEnter));
}

if (PlayerController->GetPawn() == Cast<APawn>(VehicleToEnter))
{
	this->Destroy();
}

If it’s possessing the vehicle pawn, then the problem probably isn’t in your possession code. And instead, in your input/movement code for the Car. That or your networking simply isn’t setup right, because if I remember simply “Possessing” a pawn doesn’t give control to the client to have simulated authority over it.

Whenever you’re designing a multiplayer game, and you run the game with “Run with Dedicated Server” mode, then you’re considered playing as a “client”. Being a client means you’re running network code as it appears you know. So more than likely you’re swapping out possession, but the “client” isn’t being given authority/simulated control over the car. So it can’t process commands because the server setup won’t let it.

Well how do i give the client authority to control the pawn?

It’s sort of a chain of events that need to happen which is a lot of Networking that can’t be summed up in a simple manner.

I would suggest reading up RestartPlayer() inside GameInfo in the UE4 Source and follow the chain of code. I did look at PossessedBy() inside Pawn, and it seems like it should do all the networking for you. So it could be one of many other problems. I’d say use DisplayAll to check out some variables such as Role and RemoteRole to see what’s happening network wise, whether it’s setting properly. That’ll tell you if it could be an autority problem.

Then check your input logic and see if it’s calling on the client.

There is a function that all Actor based classes should have, which is HasAuthority(). True means it’s the server, false means it’s the client (with few exceptions). Doing this can limit a lot of code being ran on a client or a server, as well as redirect code where you need it to. Start off by using logs inside a if(HasAuthority()) check to get a feel for it.

I believe IrishKilter is right in that your problems are being caused by the client not having network authority over the vehicle. If a remote client is not the net owner of an actor, it cannot call any client-to-server RPCs via that actor. This affects both throttle and steering inputs you give client-side to the vehicle movement component (they are sent to the server via client-to-server RPCs) and any custom client-to-server RPCs you defined to send input.

Luckily I have a tried solution for you: you can set your vehicle’s net owner in C++ by calling AActor::SetOwner() server-side. So at the moment your PlayerController possesses the vehicle, also call SetOwner on it like this:



APlayerController * SomePlayerController = ...;
APawn * SomePawn = ...;
SomePlayerController->Possess(SomePawn);
SomePawn->SetOwner(SomePlayerController);


Now your client-to-server RPCs will get through. Let us know if it works!

I just added ‘SetOwner’ in the server rpc like you said and it didn’t work :frowning: ?

here is my code:



PlayerController->UnPossess();

if (PlayerController->GetPawn() == NULL)
{
        PlayerController->Possess(Cast<APawn>(InVehicle));
        Cast<APawn>(InVehicle)->SetOwner(PlayerController);
}
if (PlayerController->GetPawn() == Cast<APawn>(InVehicle))
{
        this->Destroy();
}

EDIT: Nevermind. I just understood your code.

The code you presented, is that the server RPC? So if I understand correctly, that function is executed server-side after being called on the client, is that correct?

Can you confirm that the code that you show is being executed when requested by a remote client? So if you play as a remote client and try to enter a vehicle, does that code run at all? If so, after calling Vehicle->SetOwner(PlayerController), do server RPCs on the vehicle actor work?

I’d also highly recommend the use of the console command DisplayAll by pressing the Tilda (`) key and typing in displayall ClassName variablename. A very quick way to check various variables, which reflect properly on both the client and server (depending which window you use to display it).

For example


"Displayall YourControllerClass Pawn"

could tell you if you’re even possessing the pawn (which should be your vehicle at this point). You can also do


displayall yourvehicleclass Owner

and


displayall yourvehicleclass Role

to see if you have any authority over the vehicle. On your client “Role” should = ROLE_AutonomousProxy for you to have control over sending info to the server (like throttle, steering, etc)

Yes! that’s correct.

Yes it is being executed when requested by the server. When i try to enter the vehicle the code does run/work but i cant control the vehicle for example forward throttle , mouse move camera… etc, and no even after setting the owner i still cant move the vehicle.

Hey i was dealing with this exact issue last night.
I twisted my head for houers, but i cheated and checked out Tom Looman Survival Project.
And i notice he is calling APlayerController::ServerRestartPlayer.

Now i decided to place this in the over-riden AController::OnRep_Pawn (This suit my requirements)

So when Pawn is spawned and and possessed server side and client gets stuck in “limbo” so it can`t move.
This solves the issue for me, you stile need to handle the UnPossesssion and Possession of the Pawn so 4th server side, and ServerRestartPlayer() is called from Client.

Hope it helps with your problem.
WCode

I’ve just done that and these are the results, Two lines came up for each command, im not sure which one is the server/client i’m assuming that the top one is the server so it said the following…

(I added the server/client at the beginning)

Server : Owner = PlayerController
Client : Owner = None

Server : Role = ROLE_AutonomousProxy
Client : Role = ROLE_SimulatedProxy

Oh wow, I just added ServerRestartPlayer(); to my code and it worked!!! thank you so much.

Hey everybody i got it to work, Thanks to every body who tried to help i really appreciate the fact that you stopped and bothered to help me :smiley:

This is my final code that works -



PlayerController->UnPossess();

if (PlayerController->GetPawn() == NULL)
{
	PlayerController->Possess(Cast<APawn>(InPawn));
	Cast<APawn>(InPawn)->SetOwner(PlayerController);

	if (PlayerController->GetPawn() == Cast<APawn>(InPawn))
	{
		this->Destroy();
	}
	else if (PlayerController->GetPawn() != this)
	{
		PlayerController->Possess(this);
	}
}

PlayerController->ServerRestartPlayer();

It said that ServerRestartPlayer had to be called by the client, but i made it where its called by the server. I don’t know if i’m doing it right be it worked! Thanks again to everybody.

My pleasure happy to help. :slight_smile:

So I know this has been resolved, but out of interest: AndrewM47 when you had the issue of the possession failing, did try to possess a vehicle that was just spawned at that instant or was it already in the level?