Projectile replication and networking discuss

Hey guys, first post here.

So im wrapping my head around projectile replication. I googled much for the last days, and tried out some things but i want to discuss this topic and i want to ensure that my informations are valid.

Im making an autoattack where a stone spawns in front of me and is shooting towards where im aiming. I use the projectile movement for this. The game should be competitive so -> server authoritive and everybody should be as near as possible to servers version of game. I will use a dedicated server

So there are 3 ways to do this in network ( correct me if im wrong or there are more ways)

  1. Ask server to spawn the actor and set it to replicate so it gets replicated to the clients.
    -There is an input delay depending on the ping
    -The replicated movement looks buggy to clients (is there a way to optimize this? tried to use interpolation with setting a interpolated component and updating with move interpolated component in tick event with repnotify servers actor location and rotation but doesnt make much better)

  2. Use Multicast without replication
    -Seems to be pretty responsive for all clients but if i understand it right everybody has its own version of the actor which is not synchronized with the servers one?
    -I read that multicasting is network exspensive and that you should avoid it if possible
    -With multicast i could exclude the server from spawning the actor but instead just predict the projectile with the function predict projectile path. Would i save server ressources with this? are there other problems with this idea?

  3. Replicate is but spawn it on the owning client directly
    -so its very responsive but the owning client will see two actors when the server begin to spawn its actor. So i make an RPC to the owning client to destroy his actor if the servers actor is spawned. That looks not satisfying. I tried to “smooth” the local actor towards the server actor and if the positions are equal enough then i will destroy the local actor and he sees only the server one. But then the server projectile still doesnt looks smooth.
    -Another idea is that the servers actor will only replicate to other clients except the owning client who has his local version. Of course just the servers projectile will fire hit events and so on. But there are two things in my mind with this:
    1.I think, escpecially with high ping, it would be very frustrating to see that you hit an enemy but server didnt. So you deal no damage. I KNOW that this is common in games, this happens
    and i cant avoid this. But i think with this method it would be too much if you know what i mean.
    2.I dont know if its possible to replicate an actor excluding one client. U could achieve this effect by using multicast but i try to avoid it for the autoattack. Is there another way to to this?

So my main problem is that i dont know how to make a replicated actor with projectile movement look smooth for everyone with a normal ping but will also feel responsive to the owner. High ping client will always see a snap back or something. What is the “standard” procedure in the game industry for this? And for information: I use 12000-15000 velocity for this actor
I tried to play with projectile interpolation i think im not using it the right way, neither im sure if projectile movement use this automatically if im enabling it. I dont find much about that in the internet is this a new feature or is it just not the way to go?

I tweak netupdatefrequenzy for the actor. increasing it seems to smooth it a bit but first i think for an autoattack which will be spammed a lot u dont want have this set up to 200 or sth like this and second if the server is updating the position 200 to the client but the server only has a tick rate of 30 ticks it wont make such a difference or do i mess up something?

What are your thoughts, opinions and best practices?

Sorry for some double-spaces in the text my space is broken :smiley:

Best approach is client fakey. You gain client responsiveness and still maintain server authority.

Client spawns local fired projectile with collision -> RPC’s server to fire. Servers projectile is authority on hits, dmg calc, dmg apply etc. Server replicates to all other clients.

Server hits (auth confirmed) execute blood splatter. This alleviates some of the high ping variance frustration. Players can only really assume a hit if they see blood splatter. Just to be clear you’ll have LP vs HP misses and vice versa with any server auth setup. You can mitigate some of the low ping shot misses using a frame history time buffer, but it’s a very complex process (refer to Rewind Time hit detection).

For projectile lag comp you’ll want to use delta and predict projectile path to sync proxy projectile positions. On all other clients (non firing) you’ll spawn the projectile at the original transform, but maintain Fx/sound on the muzzle…where ever it may be at the given time.

Battlefield 4/1/V (EA/DICE) use this approach.

3 Likes

Hey ,

For the projectile lag compensation: Which tools or methods gives UE4 already that i can use? Can i use projectile Interpolation for this or is it already used ?And you mean: write this in the projectile movement class so that every client predict next movement?

You said “Server replicates to all other clients”, but how can I exclude the client which has already shot? (If we dont use Multicast)

Thx for your anwser!

It would be nice if someone answered his last reply

For the projectile lag compensation: Which tools or methods gives UE4 already that i can use? Can i use projectile Interpolation for this or is it already used ?And you mean: write this in the projectile movement class so that every client predict next movement?

UE doesn’t provide Lag compensation tools/methods/code etc. Lag comp is specific to its purpose. It needs to be designed and implemented for the unique task.

Projectiles (PMC) already interpolates per client frame rate. Also need to consider sub-stepping.

You could implement network prediction into PMC, but that’s a lot of work and honestly a waste in my opinion considering the client fakey approach I already mentioned.

You said “Server replicates to all other clients”, but how can I exclude the client which has already shot? (If we dont use Multicast)

Flow Control!

instead of constantly rolling out branch conditionals all over the place I wrote a function to set the role of each proxy on spawn. I call the function directly on Begin Play in the character class.

In the weapon class I use it to determine which proxy can execute which code.

e.g. Exclude OWNER (Autonomous Proxy) and Server…Only sims execute

Here’s a Big Picture look at Client Fakey → Server Auth.

  1. Client fires a local only (obj pooled) projectile. Client projectile handles all the clients hit fx.
  2. Server fires a server-side projectile (obj pooled) which handles dmg calc and application.
  3. Server calls a multicast on sims and passes the values it used to shoot.
  4. Multicast is only executed on Simulated proxies.
  5. Sims fire a local only (obj pooled) projectile. Shot V/A FX are handled by the sim. Optionally the sim can do hit fx based on its projectile, or the server can multicast hit data so sims can apply server auth hit fx (location, normal etc).

(post deleted by author)

what keeps you from having a bullet on client and then a 2nd copied bullet from multicast sim?
also, thank you for responding. I’m trying to make sure I understand all of this multiplayer networking before I finalize my logic design and this has helped a lot. If I had to expand on more questions i would ask if you have any experience with the Mover2.0 system and using it on projectiles.

There are literally 3+ projectiles fired in the above posted code. Yours, The servers and then a copy on each Sim of your character. Projectiles aren’t being replicated which is expensive.

Projectile Movement Component (PMC) is actually too heavy (bloated) for this. Mover 2.0 would be even more so. Bare bones C++ Interpolation w/sub stepping and collision sweeping would be the best route. Yet still each simulation would handle the movement on its own.

BUT there are never 3+ flying in a single simulation because none of the projectiles are replicated. All 3 (Client, Server, Sim) projectile classes are set to NOT Replicate.

Client determines its own trajectory for the shot and fires. Then send an rpc for the server to shoot.

Server determines its own trajectory for the shot and fires. Then calls a multicast that passes its velocity or speed and rotation, muzzle location to simulated proxies on other clients.

Sim firing is essentially the following.
The server Sends the Bullet Config data in the multicast.

Without object pooling it would use a spawn actor node.

Spawning and destroying actors is expensive. Especially so if done often and at a high rate. Hence pooling and reusing the projectiles.

I assumed multicast would sim it on the client too resulting in a double instance on the client. but i looked at the code again and the proxy role seems to prevent that. it does seem like some desync could occur with the client having this much authority. I mean. even if the server has authority over character movement there is still some leeway in client interp of character location, or perhaps when client fire while desynced, which could result in a client not matching a sim in this instance. or am i missing something?

Character movement component does the same thing roughly. That’s what client-side prediction is. You input movement and “your” client executes it immediately. The inputs and results are buffered in a SaveMove. On next ClientDeltaSendMove all new moves are packed and sent to the server. Server attempts the same moves then compares its result against the clients result. If they differ, the server sends that client a correction, otherwise an ACK for the move.


There’s always desynchronization in multiplayer. The latency of the players, hardware/software differences, floating point precision errors etc. You’ll never sync anything 100%. Best you can hope for is a solid approximation.

You should be doing your own checks and balances in this regard.

For single and first burst/auto shot I’m sending the clients data (what it used for the shot) to the server.

Server calculates its own values and compares against the clients. If it’s close enough to the servers results then the server will use client data, otherwise server uses its values. There’s favor the shooter here but I’m talking small data offsets as limits. 125.012 vs 125.053 (1/8 cm against 1/2 cm)

In the clients firing functions (Single, Burst, Auto) I’m calling a Projectile Trajectory function.

The server has its own version of this function that handles the scrutinization and some anti-cheat.

Client might see a clean hit, but the server says no. This is common across all shooters. On sims we aren’t spawning the projectile at the sims muzzle. We are spawning it where ever the servers muzzle was at the time it fired.

To visualize CMC’s client-side prediction and “desync” aka lag turn on Network Emulation. Use the settings posted below.

Stable 100ms ping vs 100ms ping with 1% packet loss.

You’ll see an undeniable delay. This is what most modern gamers call desync. It’s just lag.

You’ve been very helpful.

1 Like