I have a predicament - if a player is moving, and then makes an attack, then the player and the server should both start raycasting for hit detection.
However, since the server sees the player as further behind than the client, then it results in desynchronization.
Here is an example video:
The Red rays are the server’s hitboxes, and the green are the client’s.
Clearly, they are way out of sync. I’m wondering how you all deal with this issue, since it’s been a really annoying thing to deal with for me.
The simplest way to solve this desync looks like a delay on server-side hitboxes.
The simplest way of doing this could perhaps be the right mix of remote events and remote functions.
For example, you could fire a remote event from client to server saying they just inputted an action, but you probably already have that covered, since inputs are handled client-side and you would have to tell the server anyway.
You could also try firing a remote event to the server, then the server firing a remote function to the client, casting hitboxes immediately when the client returns on the invoke.
If all else fails, you could add a generic wait on the server and hope that handles it, though probably not well. It all depends on how long the delay has to be.
The server is behind the client, not the other way around.
The red rays are the server’s, and the green are the client’s. Since the red rays spawn behind the player, it means the server’s hit detection is delayed compared to the client’s.
Based on the video, I noticed that the server was casting “at the same time” as the client’s, but what differed was the location of the raycasting. If you were to delay the server’s raycasting enough to catch up to the client’s raycasts, you could theoretically cast them to the same position, albeit delayed, and this is why I suggested using remote functions to add a delay on the server based on the client’s connection.
You can do the reverse with client inputs, which is actually the intended way to do this, and it would actually create the same effect as before, only using a remote event that is.
It looks like what you are doing, based on the synchronization, is firing a remote function from client to server, and once the server returns, the client casts hitboxes, essentially at the same time as the server replicates the hitboxes back to the client.
If you actually are using the above method, you can set hitboxes to the same position by casting hitboxes at the same time the signal was fired instead when the signal is returned. This would allow for the most accurate hitboxes visually for every other client but the one who cast them. Your method does not seem to allow for either, as these hitboxes would be cast at different times and positions, especially to other clients.
In theory, if you wanted to change the position of a hitbox, you would have to change the time it took place, and vice-versa, due to the delay between the client and the server.
Sorry if this sounded rude and self-righteous, I would also like to hear other people’s approaches to this!
Client starts its raycasting, and server starts interpreting received signal
Server starts raycasting
The desynchronization, from what I can tell, is due to the server not knowing where the client’s updated position is, since the player is moving on the client.
The server doesn’t really predict anything.
I’ve tried implementing a few network prediction algorithms on the server to see if that would work, but they have mixed results.
I’m starting to think the only way to truly handle this is to make the server more generous, and keep track of previous locations, and let the client dictate when it hits something.
There are a few ways I’ve seen this done in the past to account for ping but I don’t think I can provide you with enough accurate information.
However, have you thought about doing hit-detection on the client?
By doing it on the client you make a much more responsive feel for the player but obviously it comes with the downside of the need for some serious exploit prevention.
If you do it on the client, I suggest you do these few things to prevent exploiting:
Send your rays from that position checking only for obstacles that are permanently in place such as map objects, this way we know they’re not hitting through walls or whatnot.
Keep track of every players position on the server as frequently as you can to do magnitude checks.
Obviously check to make sure the player isn’t hitting faster than they supposed to be able to, you can do this with a lastHit value in their data or many other methods.
When a player hits someone, fire a remote event to the server simply stating which player they hit. On the server, check the time that the remote event was received, subtract the clients ping, and then use your data to make sure the player was close enough to functionally hit the other player.
If everything checks out, damage the player.
That’s the best method I know but I would love to hear other people’s feedback.
Yeah, I have considered it.
My current plan is to only do hit effects (e.g. hit sound) on client hit detection, and offload the actual damage detection to server.
I think I will end up having to do some client-based reconciliation though.
Most people have suggested a delay for when the server begins the raycasting, the delay being based on the users ping. This system, is a good work around. Maybe a little annoying for high latency players, but they’re always an issue in fighting games.
Another style you can use is some predictive crap, it makes the entire process more instantaneous. Now i know you’ve tried some algorithms before. Most of them haven’t been the absolute schnitzel for you. You’re welcome to dispose of this pile of rubbish as you see fit. Anyways here goes…
Since you’ll probably need to take into account player ping at some point in development, this is gonna be the first step.
My idea involves multiplying the velocity vector of the humanoid root part on the server by the ping. Since we usually measure ping in milliseconds, and velocity vectors show how far one is moving in 3 dimensions per second, you’ll want to convert the ping into seconds and then multiply it to the velocity. This will get you about a good sense of where the player is.
So to recap my late night idea:
Get tha ping
Convert the ms ping into sec
Multiply the velocity vector of the humanoid root part by this ping in seconds
Add this to the current position of where the hitbox is without the prediction
(Optional) get a lil crazy and do this with rotational velocity! Though itll be a little different since you have to also do some changes to my system above.
Basically, I’m tired, but liked this thread too much to not reply.
I’ve tried a similar velocity-based prediction method, but I completely forgot rotational velocity existed.
I’ll give it another go and see if it estimates movement better.
Detect hits on the client and check the validity of the hits on the server. This is the best way to make a smooth experience for the player while still being secure.
The reason I’m hesitant to do this is that it increases the latency for other players; They won’t know they are hit until the client that fired the attack first sends the signal to the server, and then the server sends it to the client being hit. While it probably wouldn’t matter much for smaller latencies, it could definitely be a major pain point for larger latencies.
I haven’t tried it though, so I’m wondering if anyone else has had success with this.
Sorry to bump this post, but have you fixed your issue?
I am currently having some hit detection issues and knowing what to do with client/server desync could help a lot.
I think this issue can be explained through the concept of ‘Client Prediction / Server Reconciliation’ in the server-client architecture, which there’s many youtube resources explaining it and how to implement systems dealing with it on other platforms