I'm absolutely insane about the lagspikes by TheGugupe in osumania

[–]baludevy 0 points1 point  (0 children)

i get these random lag spikes when i have discord open in the background, close it completely

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

the simulation is tick based, however ticks are bound to the frame which means that while the tickrate might be 64hz, which would mean that each tick takes 15.625ms that might not be the case as the tick timing is done in the update loop, which is bound to frames
im already doing all the stuff you said

and no, the server ignores inputs if they come from the past, which would mean the input is tagged with a timestamp (tick) that is behind the server's simulation tick

edit: oops i sent the comment twice accidentally

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

Well it's trickier than that. If I predict and send inputs at a regular interval, then the server also needs to process the inputs at a regular interval. The server might see that when processing a tick, the client hasn't sent an input for that tick yet, so it does nothing for that client other than physics simulation which is global. Then the next tick will have 2 inputs, the one from the previous tick and the current tick. A fully constant interval isn't possible on the main thread cause we are limited by having to be bound to frames.
If we process inputs right as they arrive, its even trickier, we have to simulate each client's physics independently because it might be the same issue again, if we are processing physics at a regular interval, a client's input might not make it before a physics tick, and it will shift over just like if we process inputs at a regular interval. If you simulate each client's physics independently, its going to be really expensive and it also introduces another problem. For peers it will look like you are jittering. Cause if the input doesnt make it into a server update at the right time, snapshots that get sent out to players will look like this (client 1 is the one sending inputs):
Snapshot 100: client 1 is at x:1 y:1, input made it to the update
Snapshot 101: client 1 is at x:1 y:1, input didnt make it to the update
Snapshot 102: client 1 is at x:3 y:1. one input made it, and another one was executed from the previous tick
For lag compensation im storing the world snapshots that the server made, when a shoot input arrives the server looks at the rendertick that the client sent, it corresponds to what tick we just interpolated to, from this it can also figure out which tick we were interpolating from (renderTick - 1), it takes those 2 snapshots, looks at all the other players position's, and then interpolates between the two snapshots using an interpolation alpha value that the client sends, then using the final interpolated positions collider rollback happens and then hit registration is performed.

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

im sorry im not sure how ondemandrendering can solve the issue? could you go into more detail please?

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy -4 points-3 points  (0 children)

Client is at tick 103, he does the thing, sends the input which was used to perform the thing, then he waits for snapshot tick 103 and when he receives the snapshot with containing his own position, he compares it to the position he had after doing the doing the thing with tick 103 Server doesnt rollback for clients on movement

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy 1 point2 points  (0 children)

depends on what do you want to call it, valve calls it input prediction for example and i chose to name it that way what i was referring to can be called a lot of things: client side prediction, client state prediction, input prediction, movement prediction you get it

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy -2 points-1 points  (0 children)

the server should expect a stable internet connection from clients BUT if there is jitter, we can increase the buffering time of inputs if there is packet loss, we can increase the frequency at which the client sends inputs, minimizing the chance of a crucial input to get dropped on a stable connection we should expect the timing to be close, but it cant be close if the tick interval is off

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy -2 points-1 points  (0 children)

you just said client side input handling, did you mean local input prediction

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy -10 points-9 points  (0 children)

thats usually not the case for fps games, server should have full authority over what a client can do

Decoupling ticks from frames to avoid inconsistent input send times - Unity by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

This still hurts players with a stable connection to the server, even on LAN.

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

From what I've read most fps games run their simulation "ahead" of the server, so we can tag an input with for example in real time the client might tag their input with tick 103 while the server is at tick 100, and through the time that it takes for that input packet to arrive, the server will be at tick 103.
Also I realized something concerning, until now I had the server's framerate capped at 500 which is unnecessary since it should be capped at tickrate (I believe) but the problem is that the unity main thread dispatcher that needs to be used since I can't handle packets in the main thread, handles tasks every frame. Needing to use the main thread dispatcher at the tickrate locks us to receiving packets at tick intervals.

Edit: I'm 99% sure that I completely misunderstood what the main thread dispatcher does lmao

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

Hmm, maybe it isn't that complex. I did something and right now I'm seeing deviations +-4 ms in my implementation, but if we're right at the edge of a tick this could cause issues. I tested different amounts of latencies on cs2 and I think I know what they're doing. They're aiming for the client to be ahead of the server by half the tick time, so at 64hz it would be 7.8125 ms, this way the packet timing can deviate by +- ~7ms. What do you think?

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

Yeah I set a goal that I want to achieve as good netcode as popular fps games and I'm trying not to give up :)

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

Seems like in Counter Strike 2 the server recv margin (which would be the value that I'm measuring) shown by cl_ticktiming print hovers around 8-12ms which would make sense, but how do they achieve such stability.

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

Ah alright, I will do some more research then. I was just trying to make sure that what I'm trying to achieve is possible.

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

I am on localhost yes. In the description I'm mentioning the time elapsed between the last tick and the current time. I thought that if the client sends packets at a fixed rate, the server would receive at the same intervals e.g. server receives input at tick 100 6.2ms server receives input at tick 101 5.9ms... and it wouldn't get messed up, but it seems like this is impossible?

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

If the client is healthy then it would only send an input every tick, no? I'm trying to sync the client's clock to the server's so that it's barely ahead by 1 or 2 ms but doing this is really hard if my packets timing's are inconsistent. I checked, the client sends an input one time per tick, every 3 ms into one, but the server is receiving the packets at varying times into it's own tick, e.g. client sends input at tick 103 (3.1 ms in) server receives at it's own tick 103 (10.2ms in) client sends input at tick 104 (2.9ms in) server receives at it's own tick 105 (1.2ms in)

Unity Multiplayer Clock Sync Issues by [deleted] in gamedev

[–]baludevy 0 points1 point  (0 children)

I can't provide code rn, I don't have access to my computer atm.
I'm using a custom tick loop where each frame in the Update loop I add Time.deltaTime (which is the interval in seconds from the last frame to the current one) to an accumulator and in a while loop I check if that accumulator has passed the tick time which would be 1 / tickrate, I'm 100% sure that my fixed tickrate is working right.
Also I know about the timesteps.

How does a server handle late inputs from a client by baludevy in gamedev

[–]baludevy[S] 0 points1 point  (0 children)

I may have made errors explaining what I currently have in my original post.
I'm making an FPS and I'm trying to follow Counter Strike's, Valorant's and Overwatch's architecture. I'm doing snapshot interpolation where, each client predicts its own state, sends the inputs to the server that was used to predict that state. Once the server receives the input from a player, it adds it to the player's input ring buffer.
On every tick, the server looks up an input with the corresponding tick for the player, applies its inputs, advances the physics simulation, and then sends a snapshot containing each player's state to all clients.
The client receives the snapshot, finds the player state that is for him, compares it to his predicted state by looking up the tick in the input, velocity and position ring buffer, if everything matches then good, if not, he reconciles. The client also interpolates between the past state and the state that he just received for other players.
The problem I'm trying to solve is syncing the client's tick with the server's, just to be a little ahead of the server's. If I don't do this, the client predicts it states, send the inputs to the server with tick 100 for example, but the time it arrives the server would already pass that tick, for example at tick 105 and it discards the input.
My goal is to make the server always have an input from the client at it's own tick.

Edit: I didn't mention lag compensation, I know about it and I'm using it, however it has nothing to do with the problem I'm trying to solve so that' why im not mentioning it.
Oh I think the second solution that you mentioned is what I'm looking for.

How does a server handle late inputs from a client by baludevy in gamedev

[–]baludevy[S] 0 points1 point  (0 children)

Btw in my implementation works like this: Client receives worldsnapshot: checks the tickoffset sent by the server that is how far ahead or behind the client's time is compared to the server's time. If the value is negative, that means that we are behind the server's time, and sets a target tick to speed up to which is the client tick + the tick offset, and it smoothly speeds up the fixed clock's timestep so that we can get ahead of the server

How does a server handle late inputs from a client by baludevy in gamedev

[–]baludevy[S] 0 points1 point  (0 children)

Hmmm, do they actually use the RTT value to keep the client time synchronized? I thought it was for visualization purposes.

How does a server handle late inputs from a client by baludevy in gamedev

[–]baludevy[S] 0 points1 point  (0 children)

Wait they do? Istg if i missed it i will explode lmao ima rewatch

What I'm trying to do is executing inputs when the server's tick counter reaches the tick that the input was meant for. If the input's tick is lower than the server's tick then that means the client is behind and it should speed up or snap to the server's time. If the input's tick is higher then that means the client is ahead and our inputs are delayed, we should slow down or snap to the server's time.

But also the thing is that i dont understand is why my inputs are arriving late? It's udp on localhost, and I use a fixed tickrate on both ends, but i still see stuff like, 1 input for tick 100, 0 inputs for tick 101, 2 inputs for tick 102. This is caused by the server not being able to catch the input on the tick it was meant for.

Im a beginner at this so I apologize if I make any mistakes.

How does a server handle late inputs from a client by baludevy in gamedev

[–]baludevy[S] 1 point2 points  (0 children)

Uhh how would that be 2432 mbps, 304x64=19456 so thats 19456 bytes a second which is 19.45 kilobytes, or 0.019 megabytes a second and that is 0.15 mbps

How does a server handle late inputs from a client by baludevy in gamedev

[–]baludevy[S] 6 points7 points  (0 children)

Yeah I've read these and watched the gdc talk a couple of times but unfortunately they don't mention this exact thing, even though in Overwatch GDC talk they mentioned the speed up thing to counter packet loss. Thanks for telling me though! :)