Client joining game on Server

I’ve been messing with some local multiplayer stuff and thought I’d try with 1 client connecting to a Server Listener.

My PlayerController has a binding to the Start button on a gamepad. This is binded to the function JoinGame.
JoinGame gets the GameMode, then calls my custom function on there PlayerJoin() and passes it’s self through (as “this”).

My CustomGameMode has a function called PlayerJoin(PlayerController* controller), and I have this to store how many players, pawns, controllers there are.
In this function I also spanw a Character based on a custom blueprint and let the controller possess() it.

I was using the GameMode as a class to hold references to my custom Character Blueprint - so I could use that to spawn per player that joined.

This all worked locally, but on multiplayer doesnt make sense as GameMode exists only on Server, and the Client never knowns about it. (lots of errors)

What is the correct approach here?
Where should I be storing the different Character Blueprints?

My basic idea at this stage was just to do a simple 2 players in the world, 1 has picked CharacterA (which is a BP based on my custom Character.cpp) and the other player can pick CharacterB (also based off Character.cpp) - both Blueprints have slightly different properties (speed, jump height etc…)

Am I going about this all wrong? Should I be storing a reference to these Blueprint types somewhere else?

Or should I be using UFUNC(server/client) in someway?

I’ve seen there’s GameState - but it doesn’t sound like this is the correct place to hold this information.

Any pointers would be greatly appreciated !

Instead of making your own custom logic you could simply override GameModeBase::GetDefaultPawnClassForController.

If you want to allow the Client to pick a Character Class while joining you could pass the Client choice as an Option string to OpenLevel

On the server GameModeBase::InitNewPlayer you parse the Option string and use it to set a custom Character Class variable on the connecting PlayerController pointer.

Then finally in GameModeBase::GetDefaultPawnClassForController you can use that custom variable to return the correct Character class.

That is it. Now the correct character should be spawned without the need for any custom spawn logic.

If you want the Client to be able to change the selected Character Class during gameplay you could make a Server RPC with the Character Class choice as a parameter and Set the variable on the server and call GameModeBase::RestartPlayer.

After I posted my question, I went to bed and read: http://cedric-neukirchen.net/Downloa…kirchen_BW.pdf
Which gave me a much better understanding - and actually reminded me of how I’d done something similar back in UDK days.

Your post here is perfect, and I will probably do your examples.

Where should the different character bp classes be stored for reference? like say on the client I want to tell the server player2 has chosen CharacterB, player2 on the client machine would need to see CharacterA/B/C etc…

Should I move those references to GameState ?

Cheers for you help!

@GarnerP57
Your point:
“If you want the Client to be able to change the selected Character Class during gameplay you could make a Server RPC with the Character Class choice as a parameter and Set the variable on the server and call GameModeBase::RestartPlayer.”

I was thinking, this is more what I was looking for in general. People could join the Server, and be in “spectate mode”, until they Press Start - and then Spawn in to a lobby level, and maybe change their character there.

With the Server RPC functions, I’m a bit confused. You say “set the variable on the server” - what would the variable be?
Say i bind this all to my StartButton func in my PlayerController class:



private:
UFUNCTION(Server, Reliable)
virtual void JoinGame();


void AWP_PlayerController::SetupInputComponent()
{
Super::SetupInputComponent();

InputComponent->BindAction("Start", IE_Pressed, this, &AWP_PlayerController::JoinGame_Implementation);

}

void AWP_PlayerController::JoinGame_Implementation()
{
// are we on server?
if (HasAuthority())
{
// set to some new character class or whatever
// this will tell the server ?
return;
}
}