Quick answer: Input lag in action games comes from multiple sources: input polling frequency, game logic processing order, render pipeline depth, and display latency. Debug it by measuring each stage independently, polling input as late as possible in the frame, and ensuring consistent frame pacing.
Players of action games can feel the difference between 50ms and 100ms of input latency. In fighting games, a single frame of extra lag can make combos impossible. In platformers, it makes jumps feel floaty and imprecise. Input lag is one of those bugs that players struggle to articulate — they just say the game “feels off” — but it has a measurable, technical cause that you can diagnose and fix.
The Input-to-Display Pipeline
To debug input lag, you first need to understand every step between a button press and a pixel changing on screen. The full pipeline looks like this: the controller hardware registers the press and sends it over USB or Bluetooth, the OS driver receives the input event, your game’s input polling reads it, game logic processes it (updating player state), the renderer draws the new frame, the GPU finishes rendering, the frame is sent to the display, and the display’s panel physically updates. Each of these stages adds latency.
For most game developers, the stages you can directly control are input polling, game logic processing, and render submission. Controller hardware latency and display response time are outside your control, but you should be aware of them when interpreting your measurements. A wireless controller can add 4–8ms compared to wired, and some displays add 10–30ms of processing latency on top of their pixel response time.
The key insight is that input lag is not a single number you can optimize in one place. It’s the sum of latencies across the entire pipeline, and reducing it requires attention to each stage.
Measuring Input Latency
Before you can optimize, you need to measure. There are two approaches: external measurement with a high-speed camera, and internal instrumentation.
For external measurement, set up a camera recording at 240fps or higher. Point it at your display and the controller simultaneously. Press a button that triggers an immediate visual change (like a flash or a character jumping). Count the frames between the button press and the visual response. At 240fps, each frame is ~4.2ms, so you can measure latency with reasonable precision. This method captures the entire pipeline, including display latency, which makes it the ground truth.
For internal instrumentation, add timestamps at each stage of your pipeline:
// Instrument input pipeline stages
struct InputTimestamp {
double poll_time; // When input was read from the device
double logic_time; // When game logic processed the input
double submit_time; // When the render command was submitted
double present_time; // When the frame was presented to the display
};
void PollInput() {
input_timestamp.poll_time = GetHighResTime();
// Read input state...
}
void UpdateGameLogic() {
input_timestamp.logic_time = GetHighResTime();
// Process input, update game state...
}
void SubmitFrame() {
input_timestamp.submit_time = GetHighResTime();
// Submit draw calls...
double poll_to_submit = input_timestamp.submit_time - input_timestamp.poll_time;
LogLatency("input_pipeline_ms", poll_to_submit * 1000.0);
}
Log these measurements over time and look at percentiles rather than averages. The 99th percentile latency is what players feel during the worst moments, and it’s often much higher than the average due to frame pacing issues.
Common Causes of Input Lag
Polling too early in the frame: If you poll input at the start of your frame and don’t render the result until the end of the next frame, you’ve added a full frame of latency. Poll input as late as possible — ideally just before you need it for game logic. Some engines let you configure input polling timing; in Unity, you can use the InputSystem.pollingFrequency setting and process input in LateUpdate for camera-related responses.
Render pipeline depth: A deep render pipeline (triple buffering, deferred rendering with multiple passes) adds latency because the frame the player sees was rendered one or more frames ago. Each buffered frame adds ~16.7ms at 60fps. Consider reducing buffer count or using platform-specific low-latency modes. On PlayStation, the sceVideoOutSetFlipRate API gives you fine-grained control. On PC, both Nvidia Reflex and AMD Anti-Lag can help.
Inconsistent frame pacing: Variable frame times cause variable input latency, which feels worse than consistently high latency. A game that alternates between 16ms and 33ms frames feels sluggish even though its average frame time is only 24.5ms. Lock your frame rate to a value you can consistently hit, and investigate any frame time spikes.
Input buffering misconfiguration: Input buffering is a technique where you accept inputs slightly before or after the exact valid window. Fighting games use this extensively to make combos feel responsive. But if your buffer window is too large, it can make inputs feel delayed because the game is executing an input from several frames ago. Start with a 3–5 frame buffer and tune from there.
Platform-Specific Considerations
Different platforms introduce different latency characteristics. On consoles, the display output path is well-defined, but you need to be aware of HDMI processing and the specific low-latency modes available on each platform. On PC, the combination of display driver behavior, window compositor (especially on Windows with DWM), and variable hardware makes latency less predictable.
On Switch, be aware that handheld mode and docked mode have different display latency profiles. The built-in screen has different response characteristics than an external TV connected via HDMI. Test input responsiveness in both modes.
For mobile games, touch input latency is highly device-dependent. Android devices in particular vary widely — some flagship phones have touch-to-display latency under 40ms, while budget devices can exceed 100ms. There’s limited ability to optimize beyond your rendering pipeline, but you can use predictive touch techniques where you extrapolate the touch position by a few milliseconds to compensate.
Web games running in a browser face an additional layer of latency from the browser’s event loop and compositor. Use requestAnimationFrame for your game loop, avoid processing input in setTimeout callbacks, and be aware that the Gamepad API polling frequency is limited to the refresh rate of requestAnimationFrame.