Having trouble with spawning players in game mode

Hi. I’m spawning player characters when there are 2 players in a session. When a player enters the session, I’m storing that player controller in an array. Then, when I’m spawning characters and possesing them to controllers, I’m using save game reference from player controllers to decide which character class to be spawned. Here is a screenshot.

When I test game in mobile devices, finding, creating joining session or gameplay (damage etc.) is fine. But client always has server character. For example, if server has character A then client always has character class A even I change it to something else. What I’m doing wrong ? Do I need to make prefshipindex (variable I use to save ships) replicated ?

you are always returning playerController(1) - is this the way you want it? Also remember that the Gamemode is serverOnly. Depending how you’ve implemented your saveGame logic, the server does not know what the client saved and can only access his own saveGame. The saveGame doesn’t also look like it is replicating. Why don’t you save it in eg. PlayerState?

Thanks for reply. So should I load savegame in a playerstate ? I don’t know much about networking. Never thought about player states. Here is my save game loading setup.

gamestate is more of a temporary solution. i dont know your setup but if a player is able to choose a pawn and this should be picked up the next time the game is startet a savegame is fine. I would suggest make your saveGame variable replicated then your setup should work. but still I’m curious with your playerControllers->get(1) - i would think also it returns the client because playerControllers(0) should be the server in this case, but again, depending on your setup things might be different :wink: I would not rely on it in a production game.

Clients have to send their gamesave data to server. Server might have to ask them for it. Both can be done in RPCs. Structs might not work in RPCs. If they dont then break them out and send each component as a separate RPC parameter.

I tried making savegame variable replicated. Nothing changed :(. As for get (1) of player controllers, I’m pretty sure it is not the issue.I don’t know, should I spawn player characters in player controllers ( just use game mode for calling player spawn) ?

So, when second player joins session, I need to get save data from second player controller and pass it to server player controller, right ?

I’m not sure if it’s the best way, but that’s how I do it.

Most people set up their game so people manually choose their preferences and player customization AFTER joining the Session. This is much easier.

But if you did your project weird like I did, then it’s more complicated and it works more like this:

  1. Set options for player on client.
  2. Save options on client
  3. Join server.
  4. PostLogin is called on GameMode
  5. PlayerState is spawned for logged in player on server
  6. PlayerState gets spawned on Client
  7. PlayerState gets replicated from Server to Client
  8. You code on Server needs to recognize that the Client who just joined is not initialized yet. Send Client RPC to that client’s player controller.
  9. Client’s playercontroller receives RPC, fetches save game file, extracts values from it and sends them back to the server’s GameState object in a Run On Server RPC. Can initialize the client side player at this point too if it want, but will repeat the action later as you’ll see.
  10. Server receives RPC, initializes player options using the params fed in.
  11. Server sends a reliable multicast to all clients with the same info, so the player gets initialized with the recently-connected client’s options, on all THEIR machines.
  12. From that point on, Pawn is replicated continuously with those settings with no further RPCs. Step 11 might not be necessary, depending on whether these options are part of the replicated pawn or stored elsewise.

Kinda long complicated process right?

Now if you have them wait to set up their player until AFTER they join the server, it looks more like this:

  1. Join server.
  2. Player is not spawned yet, set up options. Every change is sent to the server when it happens, and stored server-side for that player. This means one Run On Server RPC for every option change action possible.
  3. Player done setting options, hits a button to start playing, their pawn is spawned on the server, using the options that were set on the server.
  4. Pawn is replicated continuously with the options that had already been communicated to the server before. Server maintains any changes that are caused by further Run On Server RPCs.

Not sure which way you’re doing it. Maybe you can combine the two approaches to make a stable, reliable, and simple, responsive way.

Hmm, thats something complicated.

So when server player creates the session, I don’t need to make anything since his save game, player ship etc is ready. In player controller class, I make a “Run on Server” event which gets game state and sends “prefshipindex” - variable i use to spawn player class - to game state.When second player (client) joins I call “load save game and send it to game state” event of client controller from gamemode blueprint (right? I’m curious about this because I know clients cannot access game mode, but not sure about game mode cannot calls events from clients). After game state receives that variable, I first get prefshipindex variables from game state, then spawn characters and posses them to controllers in game mode blueprint, not getting that variable from save games of player controllers.

Please correct me if I understand something wrong, do I need to make save game, or prefshipindex variable replicated ? I could try and see, but I don’t want to package my game over and over again.

Are you applying the prefs before the client joins or after?

Player chooses ship to fly in main menu, so before player joins session.

Okay that’s how my game works, but it’s the hard way.

In my game I don’t replicate the save game object because that is set by the Client and variable replication only goes from server to client, not the other way.

It might work to replicate the prefs variable but I’m not sure if structs replicate properly. If they do then that’s great :slight_smile:

You’ll still need to arrange for the Client to send the game save or prefs to the server, have it be set on the server side according to the params the client sent to it, before it can replicate the correct values to everyone else.

Thanks, I will give it try when I have the time.

OK. Just remember the savegame exists on the machine it belongs to,is related to a file on that machine’s hard drive, so really only that machine knows about it unless you pass the info to the server deliberately.

Yes I think that should work. I can’t remember if that worked for me or if I had to RunOnServer on the GameState in order to pass the info. If you can do it on the PlayerController then that’s better because then you don’t have to go looking for the correct player to apply it to on the server side.

@Adnoh PlayerState is the best way in my opinion, so I agree with you. However, PlayerState gets killed when you open a level non-seamlessly, or join a server, which his game is doing AFTER the preferences are set.

So what my game does is when the PlayerState is constructed or begins play on the Client side then that’s where it volunteers the information to the Server through an RPC, and then the server stores it on the server-side version of that PlayerState :slight_smile: