Advertisement

Lag Compensation

Started by January 19, 2023 12:04 PM
3 comments, last by Kylotan 1 year, 10 months ago

So I'm attempting to perform lag compensation. Here's what I have so far.

When state updates come in from the server, I don't process them immediately. I buffer them and speed up/slow down the interpolation playback depending on network conditions. On the server end, we save past states of objects for 1 second.

I understand how lag compensation works for the most part. Each tick, our clients send the server the current remote interpolation time of what we're looking at, so that our server's player can actually hit objects that the client is actually seeing on his crosshairs. Suppose our client is interpolating between server tick 11 & 12 at an interpolation alpha of 0.5. On the server, we can temporarily generate new colliders for every object 50% between 11 & 12 right before our player fires. That way if our player hits an object clientside, he is most certainly going to hit it on the server.

Here's where I'm confused. The sources I've read say “just send the interpolation time and nothing more”. Well, here's our problem with that. When the server is performing lag compensation, it can determine which ticks our interpolation time is between, and generate an alpha for it. But what if our client misses a few snapshots? What if he's actually seeing ticks 11 & 14 at 50%? If the client only sends the interpolation time, the client and server are going to be viewing two different states.

I'm going to go ahead and assume that the articles I read aren't doing any sort of blending, and just comparing to the “nearest tick” state. That being said, instead of sending the actual interpolation time, should we rather just send fromStateTick, toStateTick, and the interpolation alpha? So in that case the client would be telling the server “When I shot this bullet on tick 18, I was seeing ticks 11 & 14 at a 0.5 alpha blend”? I can't think of doing it any other way.

Since you have locally predicted movement, the client and server are always going to be viewing two different states, even when they agree on which snapshots to use. You can't eliminate that, only reduce it. Lag compensation is a compromise - it does not generate a ‘correct’ world state, just one that appears closer to what the player would have seen, than to what the server knows to have actually been ‘true’.

Shooting information should, ideally, be sent along with all other inputs, which are usually linked to a specific tick/timestep. Allowing a client to provide extra timing information, such as the interpolation time, is inviting cheats that exploit this ability to put something false in. One example might be ‘back-dating’ shots to a time they know they will have hit. Another might be to pretend that it didn't receive a snapshot where the target had jumped or moved out of the crosshairs, so that it can still be shot.

Any examples you've seen that only include an interpolation time and nothing else are presumably using some other mechanism to ensure that they know exactly which tick the action was taken on, and it will most likely be a value intended to be used to calculate a time between 2 adjacent ticks, not 2 arbitrary ticks. It's common for clients to have to account for their input on every tick and to send several redundant copies of this to the server so that it's very hard to one to be missed out entirely.

Advertisement

@Kylotan Thanks for the response. After thinking about this a bunch last night, I'm going to have to disagree with you on a few things.

I think it's absolutely possible and manageable to recreate the state exactly how each client is seeing it. Let's just assume we're hitscanning and not doing any sort of projectiles at the moment. On the server, when player A's simulation is ready to be run, it will recreate the server state based on those two states from the client and interpolation alpha. Did we hit anything? Next is player B's turn for the simulation. The colliders are now moved to represent player B's view of the world state at the moment he fired. Etc.

Keep in mind, we're not moving the actual “real” colliders of the players and objects, just new “ghost” colliders that the projectiles are allowed to hit. We only need one ghost collider per object on the server to move around.

In terms of cheating, I don't think this really impacts anything at all. I could setup a lag switch that introduces 100+ms of added latency, so that I can see players before they see me. Also known as “peekers advantage”. This could be equally as problematic as the problem you described.

Having a hacked client modify the values would be difficult in the first place, as it would need to make decisions in under 1 second to actually rewind time to hit those colliders, and then the player would actually have to act on those <1sec decisions. At that point, the hacker would be better off just using aimbot or wallhacks. This also still wouldn't prevent hacked clients from artificially sending a later interpolation time and doing the same thing with that.

Assuming your prediction is working correctly, your player should pretty much be ending up at the same spot on server tick 15, as he did on his client at predicted tick 15 (Unless he's colliding with other players, or other server-interpolated moving objects etc). Recreating the world state exactly would only compliment this, and provide extremely detailed hit resolution for every client.

I play the game “Rust” a lot. Fun game. Can't tell you how often people get “projectile invalids" where they get blood and hitmarkers but no server damage. It really pisses off a lot of people and makes them rage. A system like I described would probably mitigate this almost entirely. Apparently the same thing happens often in CSGO.

allencook said:

I think it's absolutely possible and manageable to recreate the state exactly how each client is seeing it.

I didn't say you couldn't. If the client is unhacked and tells the truth about what it sends and when, and no messages from the server to the client got lost or delayed, then it's totally possible. It's usually what is done, within limits. I'm just saying that it doesn't give you a ‘correct’ world state even if all the above is true.

Having a hacked client modify the values would be difficult in the first place, as it would need to make decisions in under 1 second to actually rewind time to hit those colliders, and then the player would actually have to act on those <1sec decisions.

I assure you that hackers have been doing exactly this for 2 decades already. Be aware it's not the player that has to be able to act on the changed state, just the client itself.

Assuming your prediction is working correctly, your player should pretty much be ending up at the same spot on server tick 15, as he did on his client at predicted tick 15 (Unless he's colliding with other players, or other server-interpolated moving objects etc). Recreating the world state exactly would only compliment this, and provide extremely detailed hit resolution for every client.

Everyone experiences a different world state, if you have client-side prediction. You can attempt to recreate what individuals saw, and you can recreate what the server was seeing at that time, and you can mix and match things or even blend things as a compromise. But these are different states. The simulations will be ‘eventually consistent’ if they don't interact, because in such a case the prediction should be trivially correct. But it's exactly the case of interactions that causes the problem.

I play the game “Rust” a lot. Fun game. Can't tell you how often people get “projectile invalids" where they get blood and hitmarkers but no server damage. It really pisses off a lot of people and makes them rage. A system like I described would probably mitigate this almost entirely. Apparently the same thing happens often in CSGO.

Most likely the reason they get no server damage is because the server has made the necessary adjustments and decided that the shooting player's view was so lagged or otherwise incorrect that its predicted result can't be allowed to stand. Most games do go quite some way towards ‘favoring the shooter’ but there is always a limit to how far this can be taken because technically it is overriding the server's authoritative state, possibly disadvantaging other players.

This topic is closed to new replies.

Advertisement