Frame Pacing: Why 60 FPS Doesn't Always Feel Smooth
Here’s a puzzle that trips up new developers and confuses players: a game can report a steady 60 frames per second and still feel like it’s stuttering. The counter says everything is fine. Your eyes say otherwise. The culprit is almost always frame pacing — and once you understand it, you can’t unsee it.
Average frame rate hides the truth
Frames per second is an average. If your game renders 60 frames in one second, the counter proudly says 60. But it doesn’t tell you when those frames arrived. Imagine 60 frames where 59 land evenly and one arrives twice as late as it should. Your average is still 60. Your experience is a visible hitch.
The thing your visual system actually tracks is the time between frames — the frame time, usually measured in milliseconds. At a true 60 FPS, every frame should appear about 16.7 ms apart. What ruins smoothness isn’t a lower average; it’s variance. A game locked at a rock-steady 40 FPS often feels better than one bouncing between 55 and 70, because the steady one is predictable and the bouncy one isn’t.
Where stutters come from
Most pacing problems trace back to a few usual suspects. The garbage collector can pause everything for a few milliseconds at unpredictable times in managed languages. Asset streaming — loading a texture or a chunk of world just in time — can blow a frame’s budget. Shader compilation on first use is a notorious cause of the “traversal stutter” that plagues many modern releases: you walk into a new area, the engine compiles a shader it’s never seen, and the frame hangs. And plain old CPU/GPU sync issues can leave one waiting on the other in irregular bursts.
How to actually diagnose it
Stop watching the FPS number and start watching a frame time graph. A flat line means smooth. Spikes mean stutter, and the height and frequency of the spikes tell you how bad it is. Most engines and profilers can show this; if yours can’t, it’s worth wiring up, because it turns a vague “feels janky” complaint into a measurable, fixable signal.
From there the fixes are concrete. Pre-compile shaders during loading instead of mid-gameplay. Budget your streaming so big loads are spread across frames instead of dumped into one. Pool and reuse objects to keep the garbage collector quiet. Cap your frame rate to something you can consistently hit rather than chasing a high number you can only sometimes reach.
The lesson
A high frame rate is nice. A consistent frame rate is what actually feels good. If you only optimize for the average, you’ll ship a game that benchmarks well and feels bad — the worst of both worlds. Watch the frame time graph, smooth out the spikes, and trust your hands over the counter.