Sure. I’ll try to explain
Look lets imagine we have a multiplayer game where we have one server “S” and two clients, “C1” and “C2”. So that is 3 instances of the game running. Now let’s focus on C1. C1 has a character actor. Now this character does not only exist within C1, a replica of it also exist in S and C2 so that is 3 characters, one in every computer running the game. To make it so they all look the same or synchronize them is through replication and the way that works is something like this. S contains the “real version” of C1’s character actor, in fact S contains the real version of every actor in the game. C1 and C2 only have the “fake version” of the actors. S tells them every frame about any change on his “real version” so C1 and C2 can update their “fake version”.
You may ask, yeah but how do I make all of that happen?
We do it with replicated variables and Remote Procedure Calls (Events that use Run on Server, Multicast or Run on Owning Client). Ok, it should be clear that when you make a blueprint and put some code and variables in it, both server and clients are gonna use that same code and variables. If you mark a variable replicated, for example you do it with a health variable in your character, S will know that he should take the health of his real version of the character and send that to the fake characters in C1 and C2 so they can put that information in their health variables. If C1 tried to change his health variable by himself it would only last for that frame because it would be overridden by the one that S is sending him, and also no one else but C1 would know that he tried to change it (C1 trying to cheat and stuff D: setting his health to 999,999,999, not gonna happen >:D).
Like I said before when you put code in your character blueprint, every body, in this case S, C1 and C2 will have that same code, but how do account for that when you are coding? how do you know when a blueprint executing in S, or in C1, C2? You do it with the Switch has Authority node, you probably have seen it in tutorials. If it has authority then your code is being executed in S, if it is remote then you are executing code in any client, C1 or C2. So if you wanted to change a replicated variable like health, would you do it in the authority line or the remote line? Answer is authority line, because, like I mentioned, S contains the real version of your character and he will tell everybody else if something changes. If you change health in the remote line it would just be overridden.
Now let’s take a look at RPCs (Remote Procedure Calls). Let’s say that you have created a function in your character that makes him attack and you have your input setup in your blueprint so it executes this function when you press the spacebar. If you didn’t account for networking in your code and let’s say that C1 presses spacebar so he runs your attack function. You will probably end up with something like, C1 doing the attack but S won’t know about it and thus C2 won’t know about it either, for them it will look like C1 never did the attack. If you want C2 to know that C1 did an attack then S is the one that should tell them so S himself needs to do the attack. First thing you should know is that input is local. Input only works for C1 or C2. S does not know anything about input his only job is to send the information about his “real versions” of the actors to every client. So then how do I tell S, that C1 pressed space bar, so that C2 and any other client can see my attack? You do it through RPCs.
Inside your actors you can define events as RPCs. RPCs are basically for executing functions in the other version of your actor, for changing a variable or doing an action, anything you want.
Run on Server. This one is the one that you will use for most cases and it’s perfect for our example. When you mark an event with Run on Server you are saying that this event is supposed to be called by clients (C1 or C2) and executed in the server, how do you know if you are using it on a client? Switch has authority on the remote line! So the way we would use this in the exapmle for the attack function is that you would put that attack function inside a Run on Server Event and then call the event in your input instead of calling the attack function directly. The effect of this is that C1 will tell S to perform an attack and if S does the attack then C2 will see the attack too, because S will make sure that C2 knows about it. What if you had a C3 would he know about it too? Yes! S will tell everybody, the number of clients does not matter. So again Run On Server is an event that client actors are supposed to call so that server version will execute something, whatever you want.
Multicast. Multicast is an RPC that you are supposed to use only in the server. Multicast is not for clients. How do you know if you are executing it in the server? Switch has authority on the authority line! What multicast does is that it would make an actor in S (could be the character) execute that event and then tell all the fake versions of that actor, (the ones in C1 and C2) to execute that same function. You could be tempted to use Multicasts to change replicated variables or do the attack function and it could work but you shouldn’t use it for that. Don’t use Multicasts events for gameplay related stuff, use only for aesthetic stuff like playing sounds, non important animations or particle effects.
Run on Owning Client. This RPC is like Run On Server but backwards. It is supposed to be used only on the server and it will tell an specific client to run a function. For example you define a Run On Server Event that shows a Win Screen in your Character blueprint. Then after something happens in the game, S calls this event in his version of the Character from C2. Again, how do you know if you are executing in S and not in C1 or C2? Switch has authority! You should know on what line by now What would happen is that C2 would execute that event in his own version of the character but only C2 would know about it, C1 wouldn’t know that this event happened. So C2 would see a win screen but C1 wouldn’t.
I hope that this helps you understand a bit better. I had a lot of trouble when trying to learn this stuff, the best thing you can do is practice and research and test. Note that there are plenty of exceptions and edge cases on all of this but what I described were the most basic situations you will encounter.
I hope it helps you instead of making you even more confused xD
If you have more questions about this, fire away! I’ll be around
P.S. Sorry for the text wall D: