• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
fjholmstrom

Best way of sending updates at fixed intervals.

8 posts in this topic

Assume my game is running at a rate of 60Hz (~16.66 ms) on both the server and client and updates from the server to the client is sent at 20Hz (50ms). Now since the game is running at 60Hz, there are two ways of calculating the interval for the client updates. I can either just do this: 

if((currentTime - lastSendTime) >= 0.05) {
     SendUpdate();
     lastSendTime = currentTime;
}

 

And just check this every frame for each client. But to me it seems like a cleaner solution would be to specify the client send rate in "every n:th" frame instead, so if I want to send at 20Hz when running at a 60Hz simulation rate I would just do this:

if(frameNumber % 3 == 0) {
    SendUpdate();
}

 

It just feels a lot cleaner, you don't need to keep a separate timer or have to deal with small inaccuracies in the local time of the server, etc. It also becomes nicely synchronized with updates to the game state on the server, etc. The reason I'm asking is because in the few examples of "professional" networking code you can find on the web, I see *everyone* using a the first method of a separate timer for the send time for each client, so I'm thinking I must be missing something here?

0

Share this post


Link to post
Share on other sites

For sure, if you can guarantee 60Hz, then frame hopping will be better, due to 'aliasing' associated with the first method (sometimes you will get perfect 1/3 updates, sometimes you will get 1 /4 updates doe to floating point drift).

 

Then you can also have options for 30Hz, 15Hz, 12Hz, 10Hz, 12Hz, ... (1/3, 1/4, 1/5, 1/6, ). A reason why '60' is a nice number to have. 

 

Professionally, the first method is often used, with maybe some rounding error to compensate for round off errors and frame aliasing. Even sometimes the network tick runs in a separate thread.

 

Se second advantage, is that you can guarantee the frame timestep (so, each network tick will be exactly 20Hz, or considering to be exact), thus removing the need to implicitly indicate timing (you can measure time using the packet sqn, for example). 

 

Sometimes, the problem of aliasing is not always such a big deal tbh. It depends how things work for you.

Edited by papalazaru
0

Share this post


Link to post
Share on other sites

papalazaru:

 

If the simulation runs on a fixed timestep (60Hz) - I would take that as a guarantee of 60Hz, it might jitter a *tiny* bit back and forth but at least the whole simulation will "jitter" instead of individual connections send intervals. And yes, the slight aliasing which will happen with the first method is what hit me when I implemented it - but like you say the aliasing could be countered by simply doing some slight rounding or something equivalent. 

 

One thing which trips me up about using the second method of "frame hopping" (never heard that expression before) is this: What happens when I do get jitter on the server, what if I get HUGE jitter and I need to run 4 frames to "catch up" to real time. Then I will send two packets in quick succession... hm, but then again if that happens the client will just perceive it as network jitter anyway. The difference here I suppose is that timing it manually using (lastSend - currentTime) you would only send *one* packet for those four updates.

0

Share this post


Link to post
Share on other sites

Here's an other method:

// all times are long given in ms 
const long INTERVAL = 1000/frequency_in_Hz;
if( (current_time / INTERVAL)>(last_time/INTERVAL))
{
 sendUpdate();
 last_time = current_time;
}

This ensures that you sends at most X, equally spaced, updates per second, but less if your performances drops for some reasons.

Edited by Ashaman73
0

Share this post


Link to post
Share on other sites

It is my advice that you should always run physics with fixed time steps. And, thus, if you use fixed time steps. you can also run networking at a fixed number of physics steps.

At the larger scale, if you get a big frame hitch, then yes, you may send to packets in quick succession. And, as you say, this will look to the other end as jitter, which is what it is.

0

Share this post


Link to post
Share on other sites
Here's an other method:
// all times are long given in ms 
const long INTERVAL = 1000/frequency_in_Hz;
if( (current_time / INTERVAL)>(last_time/INTERVAL))
{
 sendUpdate();
 last_time = current_time;
}

This ensures that you sends at most X, equally spaced, updates per second, but less if your performances drops for some reasons.

Thats got 2 bugs. Should be more like this:

if(current_time>=last_time+INTERVAL)
{
  sendUpdate();
  last_time += INTERVAL; // to prevent the step being slightly larger
}
0

Share this post


Link to post
Share on other sites

[quote]Thats got 2 bugs.[/quote]

 

No, it doesn't, assuming current_time and last_time are integral types. Given that INTERVAL is a long, and he counts in milliseconds, that's a reasonable assumption.

I don't like using milliseconds as integers for timing much, as they are kind-of imprecise, but it actually works alright. The only bug in the code posted above is when the system clock wraps 2 billion milliseconds, which happens a little over three weeks after boot. (And then again nine weeks after boot.)

0

Share this post


Link to post
Share on other sites

I was assuming current_time and last_time were real numbers like in the thread starting post; that would mean its nearly always updating.

If they are longs its still not right, for example wanting 60 updates per second 1000/60=16.666666... not 16 and 1000/16=62.5 updates per second.

Depending on 2 divisions to round down appropriately seems not the right way to do this as when the starting time is not exactly divisible by the INTERVAL everything is delayed about the size of remainder forever.

 

Also there are forgotten updates when the time ticks further than an exact multiple of the INTERVAL sometimes and you just set last_time=current_time instead of adding:

for example wanting 100 updates -> INTERVAL==10

current_time==0 -> no update

current_time==9 -> no update

current_time==21 -> 1 update -> oops should have been 2

 

I guess you are just assuming larger error margins are ok when I was already counting them as wrong.

0

Share this post


Link to post
Share on other sites
I was assuming current_time and last_time were real numbers like in the thread starting post

But if you read the code, that's clearly not what it's assuming.
If they are longs its still not right

Yes, it does, because it does the division and compares every step.
Also there are forgotten updates when the time ticks further than an exact multiple of the INTERVAL sometimes and you just set last_time=current_time instead of adding

But that's not what the code is doing. It adds for each step, and if time elapsed more than one step, it will step faster until it catches up.

I'm all for pointing out flaws in code snippets, so that other readers can be aware. However, so far, I'm afraid you're batting pretty poorly :-)
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0