Projectiles not registering-- encountering trouble with latency

Problem

Hi. I’m encountering an issue where projectiles look like they hit on a client, but the server’s model [or hitbox] does not align, so the hit does not process. Below is some footage that shows both a client’s render of a projectile and the server’s.

The green hitbox is the server hitbox.
The red is the client hitbox.

i.gyazo.com/d3088817332dae53652bb184f6f65869

Within the video, one of my arrows doesn’t register due to latency at 00:04. At 00:06, you can see ‘Scripted_Noah’ also encounters a no reg.

My Code

In an effort to make more sense of my code, I am excluding all sanity checks (which are used to defend against exploiters and are very light on performance [simple conditional statements, etc.]).

On the client, I record the input time of an attack using workspace:GetServerTimeNow(), ‘which returns the epoch time on the server with microsecond precision’.

Then, I send the client’s request over to the server and calculate the time it took to receive the input with this:

local receive_time = workspace:GetServerTimeNow()
local latency = receive_time - send_time

After that, in a nutshell, I plug the latency time into a function to match the client’s projectile position on the server.

Example:
f(x) = 2x
f(latency) = 2(latency) – this position should be pretty close [if not the same] to a client’s projectile position

Final Thoughts

Regardless of anything I’ve tried, I can’t seem to get past this ‘no reg’ problem. I want combat to be as fluid as possible, considering my game is mainly fighting-based. In my opinion, no regs are completely unacceptable and not something I want to overlook.

7 Likes

unfortunately, there is not a clean way to go about this. Anytime the client needs the server time, the trip to the client will have some delay leading to desynced times (though if you have amazing internet it wont be noticable). I would instead get the average ping and then use that for the math instead as that will be more accurate with the only issue during network spikes which could mess it up.

Outside of roblox games such as Halo have some neat tricks to get around the lag but roblox doesnt give us a lot of the tools for that. Large games such as Phantom Forces and Arsenal do client side detection with a ton of sanity checks. Arsenal leans more towards the client side trust which is why it feels smoother to play then PF. However, thats also why exploiters are more prevelant in Arsenal which they deal with by having a ton of moderators.

Of course, this is all very abstract and for implementation fixes I recommend using GetNetworkPing() and using that for math over GetServerTimeNow().

2 Likes

Serious Response,

  1. The projectiles are not moving “close enough” to the arrow. That seems to be the biggest of your issues. Possibly improving your formula to predict better position to make the red closer to the green, currently they exist barely touching each other. (formula not provided so idk how to improve that)

  2. I would also suggest maybe making a larger hitbox around the humanoid. These cases seem to be arrows colliding with limbs, not the torso. Generally the torso is going to be the target for most players. I would suggest making a hitbox .5 to 1 studs larger than the torso of the player. This larger hitbox would provide a more accurate representation of what the player is aiming for if you understand me.
    image

Let me know if any of this helped.

2 Likes

For anybody curious, I figured I’d leave what I ended up doing.

I completely dropped the concept of server-sided hitboxes. What a client sees is too inconsistent with what’s happening on the server (this makes sense-- latency). Instead, I opted to do client-side rendering, in which a client will send hits to the server and the server will process each hit, determining whether it was valid or not.

Some key things to note:

  • I keep track of every projectile fired, recording it on the server.
  • After an arbitrary amount of time, the projectile recording expires and is deleted from the server. (arbitrary time is the projectile’s lifespan [in this scenario, the arrow’s lifespan]).

While there might be some visual inconsistencies on other clients, I decided that the shooter’s experience is more important than anybody else’s. These inconsistencies are few and far between but they do occur.