Joining session playercontrollers all are -1

I am Hosting a listen server with 4 players splitscreen.
I run another instance (build for win64) and join the first one as a client, also with 4 player splitscreen.

So now there is a server with 8 players, half of them belonging to the client, and half of them showing on the server’s screen.

Everything is cool until i start the game in earnest (everyone is in the same map by this point), when I spawn and possess a pawn for each player.

The server’s 4 players spawn and possess just fine. But the 4 client players seem teleported to a black void.
I print out the player controller IDs of each player on the server side (which includes the connected client’s players) and the printouts show 0, 1, 2, and 3 for the server players, but -1, -1, -1, and -1 for the client’s players.

Is it normal for the remote player controllers to always be ID -1?
I thought maybe the lack of valid player index was why they can’t possess the pawn, but I dont know.
I thought non-negative IDs would get automatically assigned but maybe that’s not the case for remote players?

Maybe the problem is completely unrelated to the controller ID?

I should mention that coming out of a server-to-client RPC from the OnPostLogin event, asking the Client for the settings it has for player color and name, etc.,then the Client makes a client-to-server RPC passing the info along so the Server can apply them to the replicated versions of the PlayerStates. It all seems to be working great - the names get applied to the joined players (though it seems to have trouble with the colors).

BUT when it spawns the joined player’s pawn and tries to possess them, that’s where the trouble is, and where it’s saying all the joined players have an ID of -1, where the players that started on the Server have 0,1,2, and 3.

Whether that’s what’s banishing the joined players to the void or not, I don’t know.

When I did an experiment with a fresh project, without starting any network sessions, just local multiplayer splitscreen, and simply Create Player 4 times, I get IDs of 0, 1, 2, and 3, but if I add any more, then anything past the 4th player (Id 3) says it has an ID of -1, AND it doesn’t create a new player; the GameMode → Num Players remains at 4.

Then I can remove players and add them again, and it still caps out at 4. This may help me find the answer but it doesn’t fully explain what’s happening.

Thank you @anonymous_user_f5a50610. That will keep me from trying to do something impossible to fix my problem. Now, the problem remains that the client machine’s local players lose possession of a pawn when the Server possesses a pawn at a certain player index. It takes the possession away from the same player index on the client machine. I’m investigating the function where I spawn a pawn and possess it, and the Possessed event, to see where I might be going wrong.

I my fresh project where I did the experiments, though, I kept it as simple as possible. If a client has splitscreen 4 players, and the server has splitscreen 4 players, then the client keeps all 4 viewports, and viewport 0 keeps its player, but viewports 1, 2, and 3 lose their players. I wish I could think of a way to find out what is causing the client viewports to lose their players.

PlayerControllers same as GameMode are not replicated aside of local players for security reasons, but player IDs specifically seems not replicate at all. PlayerStates same as GameState exist exactly for information replication about players for other players. Try making IDs on client side if you really need them, but generly you should not rely on PlayerControllers on client side or else you make single player (which really works liek server in such case)

Player IDs became more relevant just recently, before it was just order of found and didn’t really been relevant, you can use different method of identifying players if what engine has to offer fails, you can always try fixing player IDs to with Set Player Controller ID

I found that the player controllers were being lost due to multiple RPC calls somehow. When I remove the Multicast to spawn some actors that are meant to follow the pawns around, then the loss of playercontrollers ceases, and everything is fine (except I don’t get my little actors to generate on each machine locally).

I did some more work on my project and found some of the following to be facts, at least when using splitscreen and networking together:

  1. Unless you modify the code, Create Player will only create up to 4 players on the machine that is executing the Create Player node. Creating any further players with this node will fail.
  2. When a client joins the server, its players are added to the server, but may not have an ID other than -1 on the server side.
  3. Player Controllers can never reliably be used to identify which player is connected to which pawn across a network, only on the machine the local player is created on. (Like was saying).
  4. Player States have a unique ID you can use in remote procedure calls to identify the correct playercontroller > playerstate > unique ID == the unique ID I sent in the RPC. This method works pretty well for making sure the correct player controller is acted upon in RPCs.
  5. changing a variable on a Player State will not synchronize it across the network unless the variable is replicated AND the server machine is the one that sets it.
  6. I tried to set the PlayerController ID to identify or synchronize player data, but this only works for the locally controlled players. If I set the controller ID on remotely connected players it will set it, then immediately revert to -1 (it seems they must always be -1). Again, Player Controllers and their IDs cannot be used reliably to identify players across network. And it turns out, cannot even be set for remote player controllers (they always revert to -1 in the tests I ran).

These test results may differ if you’re not using splitscreen with networking, but this is how it appears to work in that configuration.

You can create more than 4 players controlled by each machine if you modify the C++ code to allow it, but then it’s up to you to figure out how to get splitscreen to handle it if you’re using splitscreen, which means more C++ code modification.

I have solved the problem.

  1. The RPCs I was using to set up Player preferences on each pawn and replicate those things (tank color, nametag, etc) were causing loss of playercontroller-pawn connection (still don’t know why) so I rewrote them.
  2. I had to match Playercontrollers to their PlayerStates over RPCs by using the Player ID variable in the PlayerState, passing only that, looping over it on the server side, then passing it back down to each client. Any other way of matching up PLayers to their PlayerInfos and Controllers did not work reliably.