Can Someone Help Me Understand Controllers In Multiplayer?

In PIE I have set it so that there is 1 player playing in Client Mode. However, this creates two controllers, 1 for the client and 1 on the server (so technically there are 2). Does this transfer over when I publish the game i.e., will there be a second “server controller” running in the background if playing in online game?

NOTE: I am not running a dedicated server

NOTE: I can’t test it myself because I do not know how to setup multiplayer Sessions in EOS yet.

Listen Server gets a controller
Dedicated Server does not get a controller.

So, 1 per player, + 1 if on Listen Server.

a not dedicated server (listen server) means that there is a player on that server, so it has a controller.

Just to clarify, if there are 2 players, they will both get a controller as well as there will be a listen server with a controller. However, that is 2 PlayerControllers for the players, does the listen server get a different type of controller, or do they get a playercontroller as well? Sorry I didn’t clarify that last part in my original question.

When using a listen server Player 0 is the host, thus the server. So Player 0 gets a local controller and the server gets one as well. All other players get a local controller. Server doesn’t get one for them.

On dedicated server only players get a controller.

GameMode references PlayerControllers. GameMode only runs on the server.

PlayerControllers support “run on server” RPCs.

The only way this can work, is if there’s a player controller on the server, for each player.
Additionally, each local player gets a local player controller.
Additionally, remote players pawns get replicated to the local player, but don’t get a full PlayerController on the client.

In a game with 3 players, and a dedicated server, I would expect the following to be true:

Server:
PlayerController for Player 1 (server copy)
PlayerController for Player 2 (server copy)
PlayerController for Player 3 (server copy)

Client 1:
PlayerController for Player 1 (player copy)

Client 2:
PlayerController for Player 2 (player copy)

Client 3:
PlayerController for Player 3 (player copy)

On a listen server, I would expect this to be true:

Client 1 (listen server):
PlayerController for Player 1 (player and server copy)
PlayerController for Player 2 (server copy)
PlayerController for Player 3 (server copy)

Client 2 (player):
PlayerController for Player 2

Client 3 (player):
PlayerController for Player 3

The PlayerController will have the same class on client and server, else replication and Run On Server RPCs won’t work.
You can test whether a particular player controller is locally controlled (has an input device attached) using IsLocalPlayerController()
PlayerControllers on servers automatically get movement events replicated from the clients to the server, other more special events may need to be explicitly replicated. (I think movement replication is handled through the MovementComponent, not through the Controller, though!)

The APlayerController subclass objects can get re-created when loading new maps, no matter whether you use “seamless travel” or just plain new connections. See AGameModeBase::OnSwapPlayerControllers().

This is easy to verify. Make a new input event, call it Test Event, and make it in turn invoke a run-on-server RPC event:

Start a listen server with a second client.
When you invoke the input event on the second client, the server will print a message from “player controller 1.”
When you invoke the input event on the server, the server will print the invocation message from “player controller 0.”

You will note that the local listen server player will ONLY print the “sending message” message, it won’t actually print the “running on server” message. Because, if you’re already running on server, the “send to server” message gets silently ignored, so you have to special-case this in each and every case where this comes up, which is an annoying behavior IMO. Would be better to just make it transparent, and wouldn’t cost anything. If I really didn’t need to send that message to myself, then THAT what I can special-case.

Also, the full “construct, begin play” process does not happen for the second player controller on the server; it goes through a slimmer start-up process. This is annoying as well, because making sure everything gets set up the same on client and server side requires additional hooks (on possess only runs on server, so that’s a good hook to use.)

Anyway, I haven’t found a good description of the exact semantics of when each of those different hooks are called, in which order, on which kinds of servers. This is all what I’ve found out through experimentation, which really shouldn’t be the way to learn, because I don’t know if this is the intended “only true path” or if it’s just “what happens to occur for me in this case.” If you know of a good networking document that actually lays out the full expectations and guarantees here, I’d love to read it!

2 Likes

jwatte,thanks for your answer. how do i can get the server player controller copy on the client. I want to press a key on client and spawn a character on the dedicated server and possess it, but the warning ref that Warning:only the controller’s authority copy can use possess

If you read the above description, you will note that player controllers have the ability to “Run on Server” for events.
You need to make the input event that handles “press a key” check whether it’s running on the server, and if so, directly call the function to spawn the object, else, call an event that is marked “run on server” that calls the function to spawn the object.

tanks for your help!
but I’m still confused.
I spawn a player pawn in a GameMode (by override PostLogin & PreLogin),now i want to unpossess the default pawn and possess the new pawn. if I call possess function directly, the game crushed. if I call the ServerPossess, it can worked.