Engineering · July 6, 2026
Controller Hot-Swap and Mid-Run Reconnect Handling in Shmups
A wireless pad losing signal for half a second three stages into a bomb-perfect run and taking the whole game down with it is the kind of bug that turns a five-star review into a one-star review, and it's almost entirely preventable.
Published July 6, 2026
Most engines expose a device-connected and device-disconnected event that fires when a controller drops, but a surprising number of shipped indie games never actually listen for it — they just read stale input state from the last known frame and let the ship silently stop responding, which players correctly interpret as a crash even when the process is still running fine. Handling disconnection explicitly, rather than letting it fail silently, is a small amount of code for a large improvement in perceived reliability.
Auto-pause on disconnect, don't punish the player for hardware flakiness
The baseline behavior that costs nothing and prevents the worst outcomes: the moment the active input device disconnects mid-run, pause the game and show a clear "controller disconnected — reconnect to continue" message rather than letting the run continue with no input and the player's ship getting destroyed by bullets they can no longer dodge. This single behavior eliminates the most common and most infuriating version of this bug — a run lost not to player skill but to a battery dying or a USB cable getting bumped.
Some teams go further and give the player a short grace window — a second or two of continued simulation with the last-held input state — before triggering the pause, on the theory that a genuine brief signal dropout on wireless hardware shouldn't interrupt play at all if it self-resolves fast enough. This is a reasonable refinement once the baseline auto-pause behavior is solid, but it should never be the only safety net, because plenty of disconnects last much longer than a couple of seconds.
Reconnecting to the correct device, not just any device
In a single-player game this is simple — resume with whatever input device reconnects. In local co-op it's not: if player two's controller disconnects and reconnects, or if a different controller entirely gets plugged into that same USB port, the game needs to either restore control to the same logical player slot automatically or present an unambiguous "assign this device to a player" prompt rather than silently reassigning inputs and confusing two people about who's controlling which ship. Device identity (not just port number, since ports get reused) is the safer thing to key off of, because port-based assignment breaks the moment a player unplugs from one USB port and plugs into another while reconnecting.
Don't forget keyboard fallback
A controller disconnect shouldn't be a dead end if the player has a keyboard available. Offering an in-context prompt to switch to keyboard input rather than forcing the player to quit out to a menu and manually change input settings keeps a session salvageable even when a wireless pad's battery genuinely dies mid-session with no spare batteries around. This only works cleanly if keyboard and gamepad input are already unified behind one input abstraction layer internally — the same architectural work discussed in cross-platform gamepad input, which pays off again here for an unrelated reason.
Log disconnect events, even without telemetry infrastructure
A lightweight local log of disconnect and reconnect events — timestamp, device identifier, how long the gap lasted — costs almost nothing to add and is genuinely useful when a player reports "my controller kept dropping" and the developer needs to distinguish a real driver-level bug from an ordinary battery-dying event. Without any record of what actually happened, every report of this kind turns into unproductive back-and-forth trying to reconstruct circumstances the player often can't describe precisely themselves. This doesn't need to be sent anywhere or tied into a larger analytics pipeline to be useful; a local log file a player can attach to a bug report is often enough to resolve an otherwise unreproducible issue.
Test disconnect handling deliberately, not by accident
This category of bug is chronically undertested because it requires physically unplugging hardware mid-session, which QA processes rarely script for on a regular basis. Building a debug key that simulates a disconnect event on demand — firing the same code path the OS would fire on a real unplug — turns this into something that can be tested in seconds during any playtest session rather than something that only gets caught when a real player hits it after launch. Pair that debug trigger with a deliberate test pass through every major game state (menu, active run, pause, results screen, replay playback) to make sure the disconnect prompt behaves sensibly no matter where in the flow it happens, since a disconnect during a results-screen leaderboard submission needs different handling than one mid-run. The rebinding and remapping system covered in building an input remapping system is a natural place to also surface reconnect status, since both features already need to know which physical device maps to which logical player slot.