Game Dev · July 6, 2026
Versus Mode Netcode for Indie Shmups: Rollback, Lag Compensation, and Fairness
A versus shmup mode, where two players trade offense and defense in real time over a network connection, has almost zero tolerance for the input delay that other genres absorb without players noticing.
Published July 6, 2026
Cooperative online play, covered separately in co-op shmup design, tolerates modest network latency reasonably well, since both players are fighting the same enemies rather than each other and small timing discrepancies rarely change the outcome of a shared encounter. Competitive versus play is a different problem entirely. When one player's dodge needs to beat the exact frame their opponent's attack lands, even 50 to 80 milliseconds of added input delay is enough to make the game feel unresponsive and, worse, to produce outcomes that feel unfair to the player on the disadvantaged end of an asymmetric connection.
Lockstep versus rollback, briefly
Traditional lockstep networking waits for both players' inputs to arrive before advancing the simulation by a frame, which guarantees both clients stay perfectly synchronized but means every player's local input delay is bounded below by network latency — the game feels exactly as laggy as the connection is, with no way around it. Rollback netcode instead predicts the remote player's input as "same as last frame" and advances immediately, then silently rewinds and resimulates if the actual input that arrives turns out to be different. This lets the local player's own inputs feel instant regardless of connection quality, at the cost of occasional visible correction when a prediction was wrong.
Determinism is a prerequisite, not a nice-to-have
Rollback only works if resimulating from a given state with a given input sequence always produces exactly the same outcome, every time, on every machine. That requirement reaches deep into the engine: floating-point operations that produce slightly different results on different hardware, any use of an unseeded random number generator, and any simulation logic that reads real wall-clock time instead of the fixed simulation frame counter will all break determinism and cause rollback resimulation to diverge from what actually happened. This is the same discipline covered in fixed timestep and delta time in shmups, and a versus mode with rollback effectively requires the strictest possible version of that discipline applied everywhere, not just to player movement.
Bullet-heavy games stress rollback harder than fighting games
Most public discussion of rollback netcode comes from the fighting game community, where the simulation typically tracks two characters and a modest number of active hitboxes. A versus shmup can have hundreds of active bullets on screen simultaneously, and every one of them needs to be included in the resimulation when a rollback occurs. Naive resimulation that recomputes every bullet's full physics and collision state on every rollback can become a real performance problem at high bullet counts, which pushes toward optimizations like resimulating only the frames since the last confirmed state (typically just a handful of frames at reasonable network quality) and using the same object pooling infrastructure discussed in object pooling for bullets in shmups to keep resimulation cheap.
When lockstep is still the right call
For a small team without deep networking experience, implementing correct rollback from scratch is a significant undertaking, and it is worth being honest about whether a versus mode needs it. If the versus mode is a secondary feature rather than the game's core competitive identity, a well-tuned lockstep implementation with an input delay of two or three frames, combined with clear connection quality indicators so players know what they are getting into, is a reasonable and much simpler alternative. The open-source GGPO library is a widely used reference implementation worth studying even if you end up building a custom system, since its handling of the prediction and resimulation cycle is well documented and battle-tested across many shipped games.
Matchmaking by connection quality, not just region
Region-based matchmaking is a reasonable first approximation, but two players in the same country can still have a poor connection between them depending on ISP routing, while two players on different continents occasionally get a surprisingly clean path. A short connection quality check before a match starts, measuring actual round-trip time and packet loss rather than assuming it from geography, gives players an honest read on what to expect and lets the game warn about or refuse matches that fall outside a workable latency range instead of letting two players discover mid-match that the connection cannot support fair play.
Communicating desync clearly when it happens
Even a correct rollback implementation will occasionally desync in the field, whether from a rare determinism bug, a dropped connection, or hardware differences that were not anticipated during testing. When it happens, the failure needs to be visible and clearly labeled rather than silently producing a confusing, broken game state that players assume is a design flaw rather than a network fault. A clear "connection lost, match ended" message, paired with logging detailed enough to actually diagnose the desync afterward, turns a rare failure into a minor inconvenience instead of a confusing, trust-eroding experience that makes players assume the netcode is fundamentally unreliable.