Nooby multiplayer question :3

Hi,

I’m trying to increase max walk speed of a character in a small multiplayer test game. But right now when i increase the speed it increases it only on the server’s character movement. How can i make it so that it changes on the client’s character movement ?

Do you have “ReplicateMovement” in the root component of your character enabled?

Yes, I do. I’m just trying to get sprinting with the use of a stamina value to work. But God I can’t figure it out. Been trying to get it to work for over 5 hours now. Still doesn’t work at all. xD

Can someone please like post an example of how you would approach something like this. I just started with multiplayer and I have to say i find it EXTREMELY confusing and difficult to understand. There are tutorials. But I’ve watched them all countless times and it doesn’t help me much tbh. I really need some concrete examples of how the approach this because right now my mind is about to explode. Haha.

EDIT: OKAY wow I just had a major breakthrough! The big chunk of information I was missing was that after a call to server event whatever values you ask from the actor you are working in will be of the actual instance of the one you control on the client. But when you ask the values of variables without the use of a call to server event you get the values of the server version of that actor. Okay, I’m one step closer to understanding this now.

My Multiplayer TopDown Survival Kit handles this with a RepNotify boolean variable “IsRunning”:

StartStopRunning.png

InputActionRun.png

Thank you for sharing that! Why exactly use a rep notify? Doesn’t that mean that the “isRunning” boolean will be the same for all clients? Doesn’t that mean that when one client is running, all other client’s will also have a “IsRunning” on true?

Also, I’ve noticed that beginplay is always fired twice by both the client and the server. Why exactly is this?

Yes that actor will replicate that value to all clients. That’s what you want. Just the instance of that actor not all the instances of that actor.

Yes events like Beginplay, EndPlay, EventTick, ActorBeginOverlap, ActorEndOverlap are executed on the server and all clients. Because the actor these events are called on exist on each of those clients individually. The actor isn’t exactly the same one on each client. Every client has his own “copy” and so that events are called on each client. Theoretically that actor could behave on all clients completely differently though this is very rarely what you want. So you use some replicated variables / events (ideally as few as possible but as many as needed) to make the actor behave the same on all clients. Though often times you don’t want to execute all nodes in the BeginPlay, EventTick, … on the server and all clients. This is where you need to use nodes like SwitchHasAuthority / HasAuthority (to read and set variables from the gamemode like max health on BeginPlay for example) or IsLocallyControlled (to spawn a widget only on the owning client for example).

This really confuses me.

I’m going to dig at this step by step because appearantly I’m not smart enough to understand this as like most people. :stuck_out_tongue:

Here is a gyazo of a small test I did. I have 2 players I’m testing with. I put a simple print string on beginplay to see which actor is triggering the beginplay and only let the server print the actual string.
Now what I was expecting was for the serer to print one string. Namely, the name of the character who is the server. But what I get is the names of both characters. Now this is where I’m completely lost. Why is the name of the client printed when only the server should be printing it’s own name?

Okay, that makes sense. That’s kind of what I initially thought was happening. But the reason I’m so confused is because When i change things in the character blueprint, it only changes these things in the server version of the character. I tought that when i changed something with for example a function I made and if i triggered that function on the client it would simply just fire on the client, and as long as I don’t replicate the function’s behavior it would only appear ont the client’s screen. But appearantly that is totally not how it works. Because whatever function or variable i change within the character blueprint only gets changed in the server version, not the client. Why is this happening?

Let’s say you have a class “MyCharacter”. And you have the server and 2 other clients playing. So you have 3 instances of the class MyCharacter. Let’s call them A, B and C. Now each of those 3 players have a copy of each one. Let’s call them A1, A2, A3, B1, B2, B3, C1, C2 and C3. This means MyCharacter does actually exist 9 times. 3 times for each player. So BeginPlay will be fired 9 times. 3 times for the server, 3 times for the first client and 3 times for the last client.

Without the SwitchHasAuthority node PrintString should print something 9 times. With the SwitchHasAuthority should print something 3 times. Once for the server’s instance of A, once for the server’s instance of B and once for the server’s instance of C.

Okay, you sir are awesome! I’m really starting to wrap my head around this. I’ve just also cleared something up. Namely, I was looking for a way to fire code only on the client. And appearantly you simply get the player with index 0 (which is always your own player). Am I right in using this method? Or are there better ways to fire code only on the owning pawn?

Some further experimenting lead to another confusion. lol
I made a thirdpersoncharacter variable which i populate on beginplay with a reference to player index 0. Now this doesn’t seem to work. Not sure why… Although getting index 0 and then immediatly calling a function on that player does work. I’m guessing the beginplay reference get’s overwritten or something?

This doesn’t work

But this DOES work

o_O

Wrote this while you wrote your latest reply. Possibly you already got this but maybe it will help you even more:

This is how it works. When you trigger a function on a client, it will only execute on the client. But BeginPlay isn’t only triggered on the client. BeginPlay is triggered when an actor is spawned. And an actor is spawned on each client. So the server and each client will execute BeginPlay (in case the server spawns the actor and the actor is replicated of course). In my example BeginPlay of MyCharacter will be executed even 9 times. 3 times on the server for A1, B1 and C1, 3 times on the first client for A2, B2 and C2 and 3 times on the last client for A3, B3 and C3.

Outside of your character class like in a widget, yes GetPlayerCharacter is the node to go (Like when a button is pressed let your character do something). But in the character class you would use the node IsLocallyControlled together with a branch node.

Man, really you have helped me SOOOOOOOOOOOOOOOOOOOO much. I can’t thank you enough!

You should make a tutorial on networking, I’m sure it would be the best out there. Haha!!

Awesome example :smiley:

On the server GetPlayerCharacter returns A, on client1 it returns B and on client2 it returns C. No matter in what instance it’s called. So you end up with the following:

This is the server’s character (name A):
ReferenceToSelf of A1: A1
ReferenceToSelf of A2: B2
ReferenceToSelf of A3: C3

This is the first client’s character (name B):
ReferenceToSelf of B1: A1
ReferenceToSelf of B2: B2
ReferenceToSelf of B3: C3

This is the last client’s character (name C):
ReferenceToSelf of C1: A1
ReferenceToSelf of C2: B2
ReferenceToSelf of C3: C3

Or more easily said: On the server all 3 characters (A1, B1 and C1) all have ReferenceToSelf A1. On the first client all 3 characters (A2, B2 and C2) all have ReferenceToSelf B2. And on the last client all 3 characters (A3, B3 and C3) all have ReferenceToSelf C3.

I doubt this works. Or better said, I am sure InteractDetect is called 3 times as often as you want it to do.

It’s called 3 times on A1, 3 times on B2 and 3 times on C3.

Okay, although it’s rather complicated I do understand it! So if I get this right, I should initialize everything locally on beginplay. And when i want to adjust something locally on the go i use “isLocallyControlled”. When I want to change something for others to see, i use “call on server”, the server than checks if whatever change i request is legit. If yes, the change is made.

Now where does “multicast” come in? As far as I understand that node it replicates everything that comes after the function to all other clients? Right? When would one use this exactly?

Oh nevermind!!! I get it. It’s an event that is always called from the server. So for example if the server should spawn something, like a meteor or whatever, that is when you would use multicast right?

Multicasting and OnRep (RepNotify variables) events are pretty similar. The important thing that tells you when to use which of it is network relevancy. Multicast events are only called on clients when the actor is network relevant for that client when it’s called. OnRep events will also be called when the actor wasn’t network relevant to a client when the variable was changed but when he gets network relevant at any point in the future.

So in case of the sprinting example: If you’d replace the RepNotify variable with a Multicast function and a character would start sprinting when he’s far away from a player and would still be sprinting when those come close together, the client wouldn’t know that player is sprinting.

So multicast events should always be used when something should happen on all clients but isn’t important in the future. For example an explosion needs only to be played on clients that are near to it when it happens. Other clients only need to know that an actor (the one that exploded) is removed from play now.

Yeap, I get it. Sweet!

One more thingy. I’ve noticed that all variables i have in my blueprint are usable and i can change from the client through “islocallycontrolled” but when i try to change any variables that i initiated with beginplay I always get a reference to the server’s version of said variables (or some other version). How would i go about initilizing variables for later local use?
Do i have to make a seperate local beginplay or something? Because as you said beginplay is always called on each actor from each other actor.

For example, i save a reference of my animInstance on beginplay. But this is never the one it should be because of the beginplay being fired countless of times as you mentioned.

None of these variables are usuable with “islocallycontrolled” (interface ref and animinstance ref)

I have problems understanding what you mean here. But the last sentence should be:
Because as you said beginplay is always called on each actor on each client (and on the server of course):

The first part with the AnimInstance should work correctly. Each character should set the right reference on each client here.

The second part shouldn’t work correctly. Each client (and the server) spawns 3 times (in my example) the same widget here. That’s not what you want. These nodes should be placed after a branch with an IsLocallyControlled plugged in.

The third part is fine. You want to attach these component on each character on each client (and the server). Alternatively you could enable ComponentReplicates for TestWeapon and TestShoulder and execute these 2 nodes only on the server. That’s up to you and your needs.

Thanks again for clearing that up. I’ve managed to get most of the stuff i’m trying to work, which is awesome. Mainly thanks to your help. Right now I’m trying to set a text render’s text. (basically a nametag above the player’s head). And everything works just fine aside from one small issue. Namely, that the name change appears on all clients, except the server client. I used a repnotify. Does repnotify not work on the server’s listen client?

Here is what I do. I have a textbox i can enter a name in on each client. When i press enter i change a repnotify text variable in the owning player of the widget in which i entered the text. Now this all works perfect. When i use print strings to check the text variable it nicely shows the name of each client which i gave them with the text box.

BUT! How do i update the text of the text render of the player and how do i make sure all the other players see the one guy’s changed name. What i tried was change the text of the text render inside the repnotify. But I do understand why this doesn’t work. Because this only changes the text render of the local client. But then i tried using a custom multicast event to distribute the changed name to all the other clients. But this also doesn’t work for a reason unknown to me at this point. Well, it sorta works a little bit. Meaning, when i change the name on the server the change is passed down to the client. But when i change the name on the client the change is only visible on the client and not the server. I would really like to know what’s going on here. I’m still struggling quite a bit understanding what is controlling what tbh. Man, it’s so incredibly complicated. I’ve watched tons and tons of videos and read almost every article i can find about it like 5 times each. I’m starting to lose hope a bit… :frowning:

I really want to learn this so bad but I’m too stupid i guess. xD :mad:

This is how replication in UE4. The server can send information to every client (either by replicated variables or by Multicast events) but a client can only send information to the server (by RunOnServer events). So when you want the client to change something for everyone but himself you have to send that information to the server by a RunOnServer event, change whatever you want to change on the server and then replicate that variable all clients.

Generally to test any multiplayer related content you have to use at least the server and 2 additional clients. If you use only 1 client to test there is a good chance you’re frequently implementing bugs.

You might also be interested to read through eXi’s network compendium.