How do I handle replication lag with projectile weapons?

So here is my issue: I have a character that shoots projectiles. The client controls where the gun is pointing. The issue is that if there is ANY replication lag, the aim will be totally off.
If I go off of where the character is aiming on the server, the projectile will appear at where the player used to be aiming for the player and it’ll also look weird to other players
If I let the client choose what direction to shoot from when firing the server (which is fine), the projectile will not look like it’s coming from the gun to other players and might still be slightly off
If I give the client full control over the projectile, an exploiter could teleport the projectile wherever they want
If I use automatic network ownership, an exploiter could deflect shots (and possibly still teleport them) and there would still likely be some noticable lag

How should I go about handling this?

EDIT: Oh yeah also using a custom character so not sure if automatic network ownership would even work
Also the click event is detected before the rotation is replicated.

1 Like

Let the client handle the direction it wants to fire. The server can dictate the position it’s firing from (plus some adjustment with ping).
From there you can calculate a sort of “firing to” position. Send that to other clients excluding the one who is firing.
On the other clients just trace the bullet from the shooter’s barrel to the “firing to” position. You can simplify this to a unit vector if gravity is not involved in the trajectory.

This is a modest example of what you can do, although there is still room for inaccuracies.

I solved this by faking the projectiles in Lua using kinematic equations. The latency is handled by applying the ping as an offset to the time the bullet was created. From shooter to server this is just the shooters ping, but also includes the viewing client’s ping when fired to the other clients.

I open sourced the library if you’d like to see how that works in code, or if that’s something you’d want to use. GitHub - ZachCurtis/EasyBullet: A simple bullet handler that accounts for network desync

I’ve made a module for projectile before. I just handled the projectiles predicted motion both on client with deltatime and handled the bodymover on the server and set the network owner. All in all it ended up being a very smooth unexploitable projectile. The only problem was projecting the spot it will hit.

Looks tempting, although this is a practice project so I’d like to learn how to go about it
Can you go over how you go about doing this?
@Daniel1154 and @Locard Since you seem to have done it too I’d like your input too

I’m not home yet so im limited in my ability to help right now but. I assume you are using body movers for projectiles right now or something that isnt hit scan. but you should just be able to wait to replicate the arms rotation and then have it fire after its done replicating to accomadate for lag. You should be able to set the projectiles network owner on the server to (nil) and get rid of any exploiter issue or replication issue or if you want you could just move the arm towards where you clicked then shoot. I used my own custom projectile module with custom physics so it may be a little to complicated for what you are trying to do. Additionally for example if you were also moving and you fire an event to fire the gun the server may see you a couple miliseconds back so you can feed the guns barrel cframe or fire point (from the client) and shoot the projectile from there. You should calculate the servers and clients barrel positions (magnitude) and if they are too far above a threshold like 25 studs you should kick or return the request to shoot.

The bullets are simulated both on the server, and the clients. The client simulation is used to display the bullet visuals. Those bullet parts only exist on the clients, and are updated by their local simulation.

The kinematic equation I’m using takes in the initial velocity, acceleration, and simulation duration (time since the bullet was fired), and returns the current position. I just add the pings on to the simulation duration.

Here’s a link to the relevant networking code in that library. Of interest is how I add the shooters ping with the viewers ping when firing the client on line 279. I only use the shooter’s ping to start the server simulation on line 283.

One idea I’ve had for this is a “consensus” system where the clients detect when a projectile has hit and if a certain amount of clients agree on a hit it gets registered (heck you can start doing client side things for the hit while you wait on the server to confirm)
Another way would be to make an invisible projectile for the server that decides the hit although that might feel more unresponsive