Networking roles are different in PIE and packaged project

So I got this weird behaviour. I post pics to make it easier.

On the picture above we got 3 instances of the packaged game. Don’t bother with different numbers of the character. What’s important is that the first 3 lines (ListenServer) we got remote roles == AutonomousProxy but on clients (4-9 lines) we clearly see that they got one Autonomous and 2 simulated. Is it some kind of bug? I thought that RemoteRole and LocalRole should be exactly the opposite on different machines.

On the one above (Play in Editor) It’s as I expected to see it. Server got one simulated (character controller by the guy on listen server) and 2 autonomous (controller by the connected players). Why the roles are different in PIE and build .exe? Which one is correct?

I checked it up on another version of the engine (4.19) and now roles are consistent. But is it correct way? I expected different result. Shouldn’t remote roles on the sever be as follows 2x simulatedProxy(for the server controlled actors) and 2x autonomousProxy(for the connected client)

Here is a tick function on the Character. GetLocalRoleText and GetNetModeText are my cpp function that calls AActor::GetNetMode() and Actor->Role and returns the Fstring instead of enum.

Yes the inconsistency is getting cleaned up in later versions. You can see from your later 4.21 tests that the server which has authority over the first set of controllers correctly reports that the remote role is SimulatedProxy which matches the local role reported by the client which does not have authority over them.

It’s important to note that the assignment of SimulatedProxy or AutonomousProxy as a pawn’s remote role doesn’t actually give or take away any permissions or capabilities. It is supposed to be helpful in coding the correct relationships between objects but a SimulatedProxy can still make RPCs if it has a PlayerController on it. Usually, the most important thing is our local role. In some cases, due to the inconsistency you may have to check remote roles as SimulatedProxy || AutonomousProxy if you are relying on that logic.

Hopefully these later versions will be more consistent.