RPCs versus Replication and OnRep-events

I’d like to hear some opinions about RPCs and OnRep. In my project I am shifting more and more towards using OnReps instead of RPCs. It just seems much more reliable. And often RPCs can potentially desync the game between machines, especially when you’re thinking about re-connecting to a game or generally joining a game in progress, where all previous RPCs are “missing”. Another problem with RPCs is that necessary replicated data usually isn’t available on the client in time, when you change it right before the call.

My concern about replication is that I don’t know how fast it is. Right now I’m wondering whether I should replicate a character firing a weapon (continuously) through a state-variable with an OnRep-function or with an RPC. I mean, it’s a very time-critical thing, so it should be received on clients as soon as possible. On the other hand, if a player joins the game after a character has started firing using an RPC, he will never see it until that character stops and starts again. In that case, if I didn’t write certain “pre-cautions”, I guess a stop-fire RPC without a prior start-fire RPC might even crash my whole simulation…

Any thoughts about this? And is it possible to tell the engine to replicate a single variable immediately? I know there are actor-settings somewhere that determine the general replication frequency (at least I think so…), but increasing it to the maximum would probably be a waste of performance, especially when there are just one or two of these time-critical variables.

edit: so, there is this function AActor::ForceNetUpdate(). When I use it right after changing an actor’s replicated variables, will it reach the client as quickly as an RPC would?

2 Likes

You are approaching it with wrong ideas.
Replicated variables, ale usefull, when you are concerned with replicating values and/or current state of object (which as you have already noticed help with synchornization when new players join late). OnRep_ events are here if you want to do something specific with value on client.
Replicated variables while are alwyas reliable, aren’t replicated as fast as possible. They are queued, and replicated in batches at the end of tick.

RPC on the other hand are replicated to clients them moment they are called (doesn’t mean they will arrive faster than variable, though they usually are). You can send data with RPC (as value parameters), but as per usually it won’t work with UObjects only simple data with defined serialization/deserialization. Most native UE types will work out of box. If you have something special, you have to take care of it, yourself.

You should use RPC any time you want to get data to clients, as fast as possible and use replicated variables if you just want to synchronize values or state of object.

1 Like

I’m not sure what exactly my wrong ideas are. I know I can send data as RPC parameters and how OnRep-events work. That isn’t really the point. The question is why would I use RPCs for anything “state-changing” at all, unless they are <<significantly>> faster than replication.

If replication can be done at the end of the current tick, without the engine waiting for the update timer, I guess this would be almost as fast then.

In the example with the character firing a gun, it’s important to know that fire-rates can be extremely high, so that a replicated state (on/off) still seems to make much more sense to me than triggering an RPC every single frame for individual fire-events. And if I used an RPC to switch the state, there would be potential problems like I described above.

Something like movement you might want to replicate as fast as possible. For example vehicles, characters, projectiles, without waiting. You have processed data, you send it (usually from client), server get it, check and eventually send corrections the same way (server is still authoritative, client just sends predicted info).

Firing weapon can be done both ways. You might want to just sync start/send but you might also want to use RPC (it will be more responsive, though more bandwidth heavy).

Old subject but I stumbled upon it while googling this question myself. I’ve typically try to adhere to the following analogy when using an RPC or Replicated variables:

RPCs are FUNCTIONS
Replicated Variables are just VARIABLES.

Ask yourself these questions:

Do I need to know about every intermediate value of something? Use an RPC.
Do I only care about the current value, no matter it’s previous values it could have been? Use a Replicated Variable.

RPCs are just logic. They can tell clients or servers to do a specific routine. I typically only use Reliable RPCs, so that these routines are executed in order they were sent.
A replicated variable is simply state. Sure you want that state to be in sync on all the clients, but any intermediate state should not be of any importance.

Replicated variables are sent as bunches periodically. So you can set X to be X+1 multiple times in one frame, but the client will only get the final result. There is a reason that by default, OnRep_ doesn’t give you the old value. You really should not be reliant on the old value, cause it could have changed multiple times, and then the question is, did you need to know about all those intermediate values. If the answer is yes (maybe rethink your architecture), then you want an RPC where you send every value individually. It’s now become a function, a function that tells you to do specific things according to the input parameter.

5 Likes

How reliable are reliable RPCs. Meaning if deemed reliable and the server sends one out, what happens if there is packet loss and the rpc gets lost…is there some check?

Reliables are sent again if lost.