Jump to content

  • Log In with Google      Sign In   
  • Create Account

sheep19

Member Since 20 Jul 2007
Offline Last Active Feb 09 2016 02:34 PM

Posts I've Made

In Topic: Using a physics engine on the server

04 November 2015 - 09:50 AM

If you are behind (sending commands too late) you need to immediately catch up, which means stepping the simulation several times without rendering. This will glitch a little bit, but hopefully only happens at most once. If you are ahead (sending commands too early, causing unnecessary latency) you can smoothly drop the step delta. Say, if you're ahead by X steps, you subtract (X / 10) steps from the local offset (which means you step simulation slower / less frequently for a little bit.) (Also, you have to keep the time -> server ticks offset variable as a double or fraction)

Finally, you want some "desired" set of jitter buffering. It may be OK to be between 0-4 steps ahead of the server, for example, because transmission times will jump around a little bit. You may even want to count how many times you have to adjust the clock (either direction) and slowly increasae the acceptable jitter size if you have to adjust it often, to compensate.

 

Hello. I'd like to thank for your help. I have implemented what has been discussed in this thread, and the results are much better than before!

The player now is almost exactly where he should by the time the update packet is received! (It's not exactly 100% correct, but it's barely noticeable).

 

One thing remains to do. Currently the client completely ignores the tick diff reported by the server and just adds +2 to each input's tick (+2 is because that's what I noticed was the best with the server running on localhost).

By setting an artificial delay to my network, the results change, because the tick diff changes. With 50 milliseconds delay, the client gets this: http://pastebin.com/kNu9RL1U

 

As you can see, it changes just a bit when it does.

Here is my idea: Use an average of the last X tick differences (updated each frame) and round to the nearest integer. But what would be a good value for X? Probably it should be a small number - I was thinking of maybe 5.


In Topic: Using a physics engine on the server

24 October 2015 - 01:59 PM

"current tick" in each packet is common. "current tick rate" is not very useful, because the idea is that the tick rate is exactly the same on client and server -- 60 times per second (or whatever you choose.)

Often it's useful to have the server send to the client "this is how off you are in your ticks" -- i e, the client sends "this command is for tick X" and the server sends back "your command arrived Y ticks early/late." The client can then adjust its compensation any way it sees fit. Maybe adjust by a third downwards if it's early (to reduce latency) and adjust by the full amount, limited to a value of 10 ticks per adjustment, if it's late.
If you use this to also tell the client what the current tick is when the client late-joins, that one-time adjustment of course needs to potentially be big.

 

 

Alright, so I'm in the process of doing what has been discussed here.

  • Clients include the target tick in their (input) packets.
  • Server includes tick difference for each state update sent to clients.

 

The clients will use that difference to appropriately set the target tick:

targetTick = currentTick + tickDifference (I haven't implemented this part yet).

Where targetTick will be sent to the server (like you said, send for the future).

 

For now, clients send their currentTick.

 

On the client, when a new state from the server is received, I print the tick difference. Here are the results: http://pastebin.com/dh7GFFcq

In the first few frames, the tick difference is 1 and increases up to 20~ until the first input from the client is received by the server.

 

So my question is, how does the client use tick difference information? Should it just calculate the targetTick using the last value of tickDifference? The value won't be correct until the server processes the 1st input from the client, but this will be corrected really soon.

 

====

Also, another question regarding this. With this approach, the client sends input "for the future" to the server. The inputs should arrive exactly at that tick and be processed by the server.

Let's say that the client sends a input with targetTick = 5. But due to a lag spike, the server receives it at server tick = 7. But now, at server tick = 7, the server has 3 inputs from that clients (because inputs are received in order by my own protocol).

So, in that update loop at tick = 7, the server should process all 3 inputs at once, correct?


In Topic: Using a physics engine on the server

23 October 2015 - 02:41 PM

"current tick" in each packet is common. "current tick rate" is not very useful, because the idea is that the tick rate is exactly the same on client and server -- 60 times per second (or whatever you choose.)

Often it's useful to have the server send to the client "this is how off you are in your ticks" -- i e, the client sends "this command is for tick X" and the server sends back "your command arrived Y ticks early/late." The client can then adjust its compensation any way it sees fit. Maybe adjust by a third downwards if it's early (to reduce latency) and adjust by the full amount, limited to a value of 10 ticks per adjustment, if it's late.
If you use this to also tell the client what the current tick is when the client late-joins, that one-time adjustment of course needs to potentially be big.

 

Yes, that's what I meant. I don't know how I wrote "tick rate" instead :P

 

So yes, it also seems easier to implement if the server tells the client the difference to each client instead of the client having to do it manually!

 

Thanks for your advice!


In Topic: Using a physics engine on the server

23 October 2015 - 12:42 PM

 

But, due to latency, the server will always be ahead of the clients, right? So when the server receives an input with tick count 15 (from client A), it might actually be at _simulationTickCount 30. What does it do in that case? Furthermore, another client, B, which has more lag than client A sends his tick count 15 at 30 server tick rate... What should the server do?[/size]

 
That's why I say clients send commands for the future. If the client knows it's 6 steps away from the server, and it's currently client tick 22, the client will send a command for tick 28.

 

So the client needs to learn how many steps he is away from the server.

Would adding a current tick rate variable to client inputs and server world states suffice? The client can make the subtraction and find the answer.


In Topic: Using a physics engine on the server

22 October 2015 - 02:26 PM

@sheep19: You probably want to number each game simulation tick. Make sure you use the same, fixed, tick rate on all nodes! The player would then enqueue commands "for the future" for the server. This would include both "spawn bullet" as well as "move" or whatnot. The server applies the appropriate input at the appropriate simulation tick (so at each physics update on the server, only one input from each client can be applied).
 

 

I don't quite understand this.

 

If understand correctly, the server will keep a counter _simulationTickCount which will increment on every physics update?

Clients will do this as well, and send the current tick count with every input packet. Then, the server applies that input at that tick rate, based on its count (_simulationTickCount).

 

But, due to latency, the server will always be ahead of the clients, right? So when the server receives an input with tick count 15 (from client A), it might actually be at _simulationTickCount 30. What does it do in that case? Furthermore, another client, B, which has more lag than client A sends his tick count 15 at 30 server tick rate... What should the server do?

 

============

 

I also have another issue.

Currently, when an input is received, the server sets the rigid body's velocity of the client to a certain value, updates the physics world and then resets it back to zero.

This causes the local client to always be ahead of the server... (and because of corrections, the player's model "jumps" to the corrected position).

 

But from what I read, what should happen is that the server should be ahead of the client. This make me think that what I'm doing above is wrong.

Should the server assume that when an input is received (e.g RIGHT arrow pressed) that it remains active until a packet containing RIGHT as not pressed is received?


PARTNERS