NSTimer vs CACurrentMediaTime()

Z.O. picture Z.O. · Jul 26, 2012 · Viewed 10k times · Source

So I'm amidst my first iOS game and am struggling with how to go about the best way to integrate object movement.

The game relies heavily on fast moving objects and constant, fast user input changes. As such, I'm trying to have object integration and the constraint solver run as quickly and accurately as possible (to minimize user input change in between successive game loop calls).

More specifically, I'm unsure of the capabilities of the NSTimer class and CACurrentMediaTime() function. It's hard to test empirically because I'm not sure which have the larger error. For example, using an NSTimer with a repeating interval of 0.008 (~2updates/screen refresh) and calling CACurrentMediaTime() on successive calls, I find the time interval between calls varies from 0.0075 - 0.009. Hard to say which is responsible for the (small) inconsistency. So for determining the time step should I be:

  1. Assume NSTimer is accurate enough to use the NSTimer time interval as the game loop time step

  2. Use CACurrentMediaTime() to determine the time interval between successive game loop calls.

Student and new to all of this - please be nice :) Any advice is greatly appreciated. Thanks for your time.

Answer

Rob Napier picture Rob Napier · Jul 26, 2012

NSTimer is not a real-time timer. It's not even close, nor does it mean to be. If you're looking at anything faster than about half a second, NSTimer is the wrong tool. I wouldn't even recommend it for things under a second. For multi-second things, and particularly multi-minute things, when you don't really care exactly when it fires, it's great. I use it all the time.

CACurrentMediaTime() is not a timer. It's a wrapper around the most accurate time function in the system: mach_absolute_time(). So if you really care what time it is right now, and you'd like that in a human-understandable number, CACurrentMediaTime() is your function. mach_absolute_time() will give you a really accurate number, but it's based on the Mach absolute time unit which doesn't actually map to anything pesky humans think in (and every CPU has a different scale). That's why we have CACurrentMediaTime() to make our lives easier.

OK, so NSTimer isn't for real-time, and CACurrentMediaTime() isn't a timer. What's a game programmer to do?

Grand Central Dispatch includes some one of the best "make this run at about this time" systems we have. It's a Dispatch Source. I say "about this time" because GCD still isn't really "real time" in the way that RTOS guys mean it. But it's realtime enough for game developers. Look for Creating a Timer in the Concurrency Programming Guide. Also take a look at dispatch_after(), which is good for one-shot "run this after a delay."

Remember, anything that runs on your main thread (the UI thread, where all the drawing is done), is going to share time with everything else on that thread. So often you're going to need to do calculations on a background thread while you handle drawing and user interaction on the main thread. This is the kind of thing that GCD dispatch_queues are designed to help you with. On the other hand, remember that many iOS devices are single-core. So "background thread" is a bit of a misnomer. Only one thing can really run at a time on the CPU. That's why moving things to the GPU is so important (see below).

You may also want to seriously look at systems like cocos2d, which is a very good game engine. It takes care of a lot of these kinds of details for you and lets you focus on the game part.

Staying in Apple frameworks, you should also take a look at Core Animation. If you're moving things around on the screen with timers, you shouldn't be doing that. Core Animation is how you move things around on the screen. It takes care of a lot of details for you, faster and using much less battery than you'd do on your own, and it moves a lot of the work to the GPU (as I mentioned above). It's a bit more designed for UI elements than games, but it can definitely be used to build simple games.

And of course there's GLKit, but that's a whole different thing....