Download

Need Help Getting Started With Networking

Hey,

I recently started learning networking and multiplayer stuff in Unreal Engine 4. So, I went through all the documentation here https://docs.unrealengine.com/latest/INT/Gameplay/Networking/ and you don’t learn stuff until you get your hands dirty.

So, I downloaded the multiplayer shootout sample from the learn tab. It is a pretty good sample, but not that well documented or commented like you would expect from any other sample from Epic.

I started learning a bit following the blueprint execution flow and now I wanted to add some stuff for learning. I’ve added a ‘TEXT RENDERER’ component to the ‘Gunslinger_BP’ in order to have a visual identification of the server and the client. So here is my code

https://drive.google.com/file/d/0BwS_CEp1uqThNlNiT2xfRmx4bDA/view?usp=sharing

This works perfectly and indicates the server and the client respectively on both instances. But it is not a feasible solution for more than two characters. If I had 5 characters how would I indicate server on all instances including the listen server and the other 4 clients that a certain player is server.

Any suggestions are most welcome.

Thanks.
Amaresh Beuria

You might want to try using IsLocalPlayerController. It will only be true for the client that owns that controller.

I spend 3 Weeks trying to learn how that Dedicated Server thing works… Still have no idea. Usualy when i was “modding” stuff a bit…
There where Server Files and a Client. In UE4… i have no idea what is what.

I’m calling CheckRole on BeginPlay inside the ‘Gunslinger_BP’. It doesn’t give me the expected result as on server it is correct, but on client the server is not detected. And once I respawn the server pawn it also says ‘CLIENT’.

Tried it myself. You can set the “Test Text” as replicated with OnRep, so the client can receive a notification when it changes on the server. I then run the role verification in the BeginPlay only at the server, checking the controller role using GetController()->HasAuthority() to set the character variable to Server or Client whether it has authority or not.

72b72c866597dbf0e517c48c0f1b0a165a124910.png

2f0d6691a57d44d764ffa4350088814a3862f0f2.png

So the flow is something like this:

  • BeginPlay run at the Server for each character and we verify whether its controller has authority or not, setting the OnRep variable appropriately.
  • Each client receives the variable modification, and changes the TextRender text locally.

I hope this helps :wink:

EDIT: This actually works for the wrong reason! It worked here was because “GetController->HasAuthority” was null for client characters (as stated by Amaresh below), so the branch would be false. I explained another solution in a new post. Sorry!

Hey! I’m curious: what’s the difference between “SwitchHasAuthority” and “GetActor->HasAuthority”?

Thanks. I’ll definitely try it and by the looks of it(Flow) I guess it’ll work. I’ll let you know.

From what I know. The “SwitchHasAuthority” checks if the script is being executed on a machine that has Network Authority (in most use cases, this would mean Server) or if its being executed on a remote machine (in most use cases, this would be the Client).

On the other hand, “GetActor->HasAuthority” (In the above mentioned case) checks whether the controller has authority over this current pawn or not.

This is just my guess(Hope its correct), so don’t take my word for it as I’m also getting started with networking here.

Hope it helps.

Cheers

If you meant “GetController-HasAuthority” (as it is in my screenshot) instead of “GetActor->HasAuthority”:

  • Let’s say we remove SwitchHasAuthority, so that “GetController->HasAuthority” would run both at the server and the client. BeginPlay first runs at the server, then runs at the client (at least I hope). We are first checking “GetController->HasAuthority” server-side, so the server would set the text correctly for each character. But now we are also letting each client to run the GetController->HasAuthority, which would evaluate to false since locally a client doesn’t have access to other player controllers but its own, setting now the text to “Client” for every character. So every client would see “Client” above the server character.
    EDIT: This doesn’t actually happen. The “GetController->HasAuthority” just returns true if ROLE is ROLE_Authority. So it would return true for server spawned actors.

The reason it worked here was because “GetController->HasAuthority” was null for client characters (as stated by Amaresh below), so the branch would be false. I explained another solution in a new post. Sorry!

So yes, SwitchHasAuthority is internally the same as HasAuthority:

C++ HasAuthority:


FORCEINLINE_DEBUGGABLE bool AActor::HasAuthority() const
{
	return (Role == ROLE_Authority);
}

I tried your method. Its working, but there is an issue. If the client shoots the server then the text renderer reads ‘CLIENT’ on the server as well. It is giving me accessed none on the ‘GetControllerNode’ when the character is respawned.

And If I do a ‘isValid’ check the setText is not running on the client.

You can always check this out for some networking stuff…

I released this video for free as a example of some of the information contained in these tutorials.

Unreal Engine 4 - (Tutorial) Quick And Dirty Blueprint Shooter Replicationhttps://youtube.com/watch?v=Vz6CwxI67ko
If you like what you learn in this video please feel free to check out my patreon page!
https://www.patreon.com/iamjohngalt75

Sorry, looks like the “GetController-HasAuthority” gives a null for the spawned characters for each client. To get access to it, we could make a valid check and if it happens to be not valid we delay it for 0 and re-call it. But it wouldn’t work, since the server does actually have authority over every spawned character in the server. I tried it, and it set “Server” over the head of every character.

So there’s two ways we could reach the result we want:

  • Run SwitchHasAuthority and If it’s Authority, check the RemoteRole for each character (GetRemoteRole). I tried it, and it returns ROLE_SimulatedProxy for the server character and ROLE_AutonomousProxy for client characters.
    So we just branch on the RemoteRole and set “Server” if it is ROLE_SimulatedProxy and “Client” if is not.

  • Run SwitchHasAuthority and If it’s Authority, use IsLocallyControlled to filter the server character. So IsLocallyControlled would return true for the server character, so we just set the text to “Server”, and if it is false we set to “Client”.

I tested and both of them works. Should work after respawning.

The second approach is indirectly the same as the first one, since internally it uses the RemoteRole and the Role to figure if it is locally controlled:

C++ IsLocallyControlled->IsLocalController:


if (GetRemoteRole() != ROLE_AutonomousProxy && Role == ROLE_Authority)
{
	// Local authority in control.
	return true;
}

Sorry for the mess, I’m learning network myself as I try to help! :smiley:

d77916f70c5f4590d86e084f12fc4f8fd617fbcd.jpeg

This is my current node setup as per your suggestion and it works perfectly for me. Although the delay is a necessary evil in this case, otherwise the ‘SERVER’ reads ‘CLIENT’ when respawned. I guess it is because BP is a bit slower than c++. But anyways it is working and that’s the good news here.

Thanks a lot man! you’re a champ. As I go through the networking in depth I’ll keep asking questions, so I hope I can learn more from all the fellow developers.

Cheers!

The need of delay in this kind of situations a mistery to me. I have my thoughts but I’m not sure. Maybe someone could eventually explain it here.

Besides that I’m glad you got it working :smiley: I’ll be happy to help whenever you need!

Have fun

Here the delay is necessary because the PlayerCharacter is spawned and then instantly possessed. But this “instantly” thing can be laggy and lead to the PlayerCharacter not being possessed RIGHT AWAY. That means on “EventBeginPlay” the Character may not be possessed by a PlayerController, which gives you the “Client” output since it’s not locally controlled.

Can someone explain the “Has Authority”?
Using “Authority” (true) it means that this Blueprint will run on server?

Each game Actor contains a Role and a RemoteRole. The HasAuthority will basically return true if the actor Role equals ROLE_Authority.

Replicated actors are owned by the server, so if you run HasAuthority for an actor as the server, it would return true.

If you run it as the Client it would return false, since the replicated actor Role in the Client is not ROLE_Authority (it will be the RemoteRole set at the server, since their Role and RemoteRole gets swapped).

Take a look at Actor Role and RemoteRole for a better explanation.

For actors spawned at the server yes, it would have Role = ROLE_Authority and a defined RemoteRole (probably ROLE_SimultaneousProxy or ROLE_AutonomousProxy).
ps: it doesn’t mean that the “Blueprint” would run on server, but if you branch it, the True would only run for server owned actors. But this is probably obvious?

But you could have actors spawned at the client. They would have Role = ROLE_Authority and RemoteRole = ROLE_None. This means the client owns that actor and that RemoteRole is none, since it was spawned locally at the client.

So the correct answer for your question is “not always”, but if you’re working with replicated actors, then “yes”.

So when i have a actor (FirstPersonCharacter) and this actor needs to be replicated? Because more people will use the same actor to play not only one person.
Replicated means it runs on both server and client?

Hum, we don’t set as replicated so that more than one person can use the same character, if that’s what you meant.

Replicated basically means that some properties from the character are “sent” from the server to clients, so that each client sees what the server sees. It also means that each client would have the same information from the server, the base of multiplayer.

I strongly suggest you to take a look at the Multiplayer Network Compendium by eXi, but feel free to ask more questions here :wink:

Players health variable is on the server but does it need to be replicated? Replication means that everyone would have the same HP because it would change the HP for everyone connected to the server? Or it will tell only everyone that THIS guy has XY HP?

Let’s say that we have a dedicated server with three clients playing. The server will spawn a character for each client, so the server will have spawned three characters when every client connected succesfully. Each character contains its HP.

But keep in mind that each client is playing in its own machine. Each client will have three characters spawned, but they’re like a “copied version” from the server version, for each character! This is (basically) replication.

Well, now each character at the server have its own HP. We can decide to replicate the HP variable or not.

If we don’t set it to replicate, the clients won’t be able to have a copied version of it locally. Each client will have no idea of what the HP for any of the three characters is.

You might want to work like that, but what if you wanted to add a health bar on top of every character head? Then you should set the HP variable to replicate, so that each client will have its copy to put above the head of every character.

(if you’re still confused, this might help you (or make it even worse): if we look at our game from a “global” perspective, how many health bars do we see? 6, since we are excluding our own health bar. (if you tought 9: each client owns one character and sees other two).

If this is only making you even more crazy, take these ideas slow, it’s hard at the beginning. I’m trying my best here because a while ago I was on the same spot as you are now.

Good luck! :smiley: