in development

when time isn’t a constant

I noticed a problem last night with Gas (working title for my current development effort). NPCs were jittering as they moved. I hadn’t noticed it much before, but I couldn’t unsee it now. I debugged my way down the chain.

Behavioral state machine, check. Physics, check. Drawing, check. I couldn’t find the reason. I set up a simple test, enlisting an NPC to run away from the camera at top speed, and I followed it, moving at what I thought would be the same speed.

It wasn’t, though. Acting on a hunch, I monitored the velocities of the NPC model and the camera, and found that the difference between them was fluctuating from frame to frame, sometimes as much as 10%. I checked the directional vectors—same. Speed? Same. What’s left?

Well, distance equals velocity times time. I checked the time intervals I was using to update the camera and NPC positions. They were varying by 5-50 milliseconds. Couldn’t be, I thought. I use a single time base calculated by my SOAR library on every animation frame. It had to be consistent!

Unless of course, the camera and the NPC were updating in two different frames. I couldn’t see how it was possible, but was all I had to go on. I started tagging frames to see which phase each update was happening in.

The camera and the NPC were indeed updating in two different frames. Since the time interval between animation frames can vary wildly, especially under heavy loads, a model updating its position in a frame before or after the camera updates its position will be drawn out-of-phase, so to speak, with the camera. This becomes significant at higher speeds, manifesting as jittery movements.

So, why were they updating in different frames? Three factors.

In the main application loop, updating and drawing are performed in two different methods. This way, if the player pauses the game (freezing all updates) then resizes the window, I can still redraw the scene with the new aspect ratio. This is usually fine, but it helped create the issue in this case.

I schedule the draw method to follow the update method. However, due to some fiddling I was doing with the SOAR library, scheduled methods are run in reverse order—the draw method is actually being executed before the update. Therefore, updates to a model aren’t drawn until the next animation frame. Now, that’s not actually a problem, as long as all the physics calculations are performed within the context of the update. You’d be fine as long as you didn’t do something stupid—like handling physics inside the draw.

Ahem. Well, I was trying to save some time. My display list handler iterates over all active drawable objects. Early on, I figured I could stuff in a quick call—if the drawable object is updatable, then update it. However, this forced the updates to the NPCs to be handled in the context of the draw, which was executed in the animation frame previous to the frame that updated the camera. Inconsistent timebases → mismatched velocities → jittery models.

I moved the NPC updates out of the display list draw and into the update handler. Result: rock-steady models. Boo-ya, I guess. It did strike me as funny that Time, the one parameter we usually assume constant, was the wildcard. Well, that and Stupid.