Understanding GameTime

Understanding GameTime

  • Comments 21

Time can be a surprisingly slippery concept to get to grips with. Back when I was working on Allegro it caused the most common question from new programmers, and even though XNA does more than Allegro to handle time for you, it appears some people are still confused. Hopefully this post will clarify how time works in the XNA Framework.

 

Game.IsFixedTimeStep = true

By default XNA runs in fixed timestep mode, with a TargetElapsedTime of 60 frames per second. This provides a simple guarantee:

  • We will call your Update method exactly 60 times per second
  • We will call your Draw method whenever we feel like it

Digging into exactly what that means, you will realize there are several possible scenarios depending on how long your Update and Draw methods take to execute.

The simplest situation is that the total time you spend in Update + Draw is exactly 1/60 of a second. In this case we will call Update, then call Draw, then look at the clock and notice it is time for another Update, then Draw, and so on. Simple!

What if your Update + Draw takes less than 1/60 of a second? Also simple. Here we call Update, then call Draw, then look at the clock, notice we have some time left over, so wait around twiddling our thumbs until it is time to call Update again.

What if Update + Draw takes longer than 1/60 of a second? This is where things get complicated. There are many reasons why this could happen:

  1. The computer might be slightly too slow to run the game at the desired speed.
  2. Or the computer might be way too slow to run the game at the desired speed!
  3. The computer might be basically fast enough, but this particular frame might have taken an unusually long time for some reason. Perhaps there were too many explosions on screen, or the game had to load a new texture, or there was a garbage collection.
  4. You could have paused the program in the debugger.

We do the same thing in response to all four causes of slowness:

  • Set GameTime.IsRunningSlowly to true.
  • Call Update extra times (without calling Draw) until we catch up.
  • If things are getting ridiculous and we are too far behind, we just give up.

If you think about how this algorithm deals with the four possible causes of slowdown I listed above, you'll see it handles them all rather well:

  1. Even if the computer is too slow to run Update + Draw inside a single frame, chances are that Update + Update + Draw will fit into two frames. The game may look a little jerky, but it will still play correctly. If the programmer is particularly smart they might even notice that we set IsRunningSlowly, and automatically reduce detail or turn off special effects to speed things up.
  2. If the computer is way too slow (ie. if the Update method alone is too slow to fit into a single frame) there isn't really much we can do, other than set IsRunningSlowly, cross our fingers, and hope the game might do something clever in response to that. Most of the time, though, if you find yourself in this situation you just need a faster computer!
  3. If a particular frame happens to take unusually long, we automatically call Update some extra times to catch up, after which everything carries on as normal. The player may notice a slight glitch, but we automatically correct for this to minimize the impact.
  4. Pausing in the debugger will leave the game a long way behind where the clock says it should be, so our algorithm will give up, accept that it has lost some time, and continue running smoothly from the time execution was resumed.

In summary, you don't need to do anything special to take advantage of our our fixed timestep logic. Just make sure you put all your game logic inside the Update method (not in Draw!) and everything will run at a nice constant speed.

For bonus points you can automatically adjust your game detail in response to the IsRunningSlowly flag, but most games are fine not bothering with this.

If you put breakpoints on your Update and Draw methods you may notice us calling Update more often than Draw, but this is just because the breakpoint has made us late and we are trying to catch up. Timing is a great example of the Heisenberg Uncertainty Principle: by examining the way the timing system is behaving, you change the timings, and get different results than when you let the game run normally.

You can change the TargetElapsedTime property if you want to run a fixed timestep game at something other than 60 frames per second. We chose that default because it matches the standard television refresh rate, but some games might want to slow this down to 30 frames per second.

 

Game.IsFixedTimeStep = false

If you disable fixed timesteps, XNA does nothing clever for you. Our algorithm in this mode is extremely simple:

  • Update
  • Draw
  • Rinse, lather, repeat

(that is actually a slight simplification, but the details are unimportant)

There are some significant advantages to running in this mode:

  • Because the game is not tied to any fixed update frequency, it can do a better job of exactly matching your monitor refresh rate. This is important for twitch FPS games that want to render at exactly 70, 90, 120, or however else the user has configured their monitor.
  • This mode can be more efficient when running on slow computers. Instead of having to call Update several times to catch up, we can just call it once with a large ElapsedTime value. If the game is programmed well, it may be able to handle that more efficiently than if Update was called several times with a smaller ElapsedTime.

The downside is that variable timestep games are much harder to program. Even simple computations such as "add velocity to position" must be adapted to take the elapsed time into account. For anything more than the most trivial calculations this requires you to integrate the equation, so you can evaluate how it changes over a period of time. Some people are good at calculus, but I'm not, and I don't much enjoy having to deal with such things every time I want to move a game object!

 

Holy Wars

So, which mode is better? Game programmers have argued about this since the dawn of time, and will probably still be arguing when the universe implodes around us.

As a rule of thumb, console programmers prefer fixed timesteps, while PC programmers usually go for variable timing mode. There are two main reasons for this disparity:

  • Consoles are usually connected to a 60 hz television, while PC monitors can be set to many different refresh rates.
  • The speed of a console is known ahead of time, so while games must handle single frames that take longer than expected, it is unlikely they will be consistently too slow for the machine they are running on. PC games must support a wider range of hardware, so it is more important for them to cope well with way-too-slow machines.

But there are no absolute rules. I've seen console games that worked well using variable timesteps, and I personally shipped a PC title that ran just fine with a 60 fps fixed timestep.

XNA defaults to fixed timestep mode because that is easier to program, but you are welcome to change this if you disagree with our choice.

 

Multiple Update Frequencies

There is no law saying all parts of a game must update at the same frequency. For instance MotoGP combined three different update rates:

  • The main game logic ran at a fixed timestep 60 fps. This included input, sound, user interface logic, camera movement, rider animations, AI, and graphical effects.
  • The physics update ran at a fixed timestep 120 fps (we just called it twice in a row from our main Update method). This provided a more accurate simulation, which was important for simulating vehicles moving at extremely high speeds and right on the edge of loosing traction.
  • The network update ran at a fixed timestep anywhere between 4 and 30 fps, depending on how many players were in the game. The more players there were, the more data we had to send, so we adjusted by sending it less often to conserve bandwidth.

Running some parts of your update logic less often than others is a great way to make games more efficient. For instance pathfinding and AI often only need to be updated a couple of times a second. Once you have found a good path or made the decision to attack, you can follow that decision without having to repeat the entire original calculation on each update.

  • Exactly the information I was looking for, thanks very much for the post.

  • excuse my noobness ...but i am trying to compile just one little sprite moving to my screen ...i dont think my computer is so slow(hyperthread 3.4ghz) that it can't move just one sprite smoothly....i have tried all the examples you can find in the net... every single one of them "jerks","stutter"."jump a frame"....and it is only just one little sprite...a Commodore Amiga(7.14MhZ,68000Motorola) would scroll smoothly much more sprites than just one...isn't this right??...so obviously i must be doing something wrong can you point me at the right direction??

    please somebody post an understandable example for smooth scrolling...

    i have installed VC# 2010 and XNA 4...

  • Here's something I don't exactly know which way to handle: Whenever I change to a new screen in our game, the screen loads itself (models, textures, sounds, etc), so switching from one screen to the next take some *Update* time (all this loading, say 3 seconds, happens during the last update call, when the player decided to go to the next screen). When the new screen finally loads, XNA's timing system tries to catch up, so it calls Update several times (I made a test and it updated very quickly 14 times without a draw) and the new screen shows up about half a second ahead of what it should have. Since I have a timed sequence of sounds being played in the first second of the screen, they all fire at the same time making the whole transition a mess.

    How should I handle this situation? I tried setting IsFixedTimeStep before everything is loadad (in the same Update call) and the back to true after the first Update of the new screen but this doesn't seem to help at all.

    Thanks Shawn

  • Juan: this is exactly what the Game.ResetElapsedTime method is for.  Just call that at the end of your load function.

  • Oh, I didn't know about the existance of that method, thanks!

  • Hi, thanks for the clear explanation but I still have a doubt.

    Every 16 millis. will be called all the game loop (Update and Draw)? or every 16 millis. will be

    called first Update and then Draw and after other 16 millisec. will be called again Update and so on...

    Confused!!!!

Page 2 of 2 (21 items) 12
Leave a Comment
  • Please add 2 and 1 and type the answer here:
  • Post