Quick answer: Dodge and roll bugs almost always trace back to a state or timing problem: invincibility frames that start late, a roll that cannot be canceled into a follow-up, or a dodge buffered through a transition. Words cannot capture this. Capture the dodge state machine, the active i-frame window, and the input timestamps at the moment of the report so you can replay the exact frame the player saw.
A roll feels right or it feels broken, and there is rarely much in between. When a player says they got hit during a dodge, they are describing a single frame they could not possibly have measured, and your bug tracker fills up with reports that all read the same and reproduce differently. The hard part of dodge and roll bugs is that they live inside a state machine and a few frames of timing that no screenshot conveys. This post walks through what actually goes wrong with evasion mechanics and how to capture enough state that a vague complaint becomes a deterministic repro you can sit down and fix.
Why dodge and roll bugs resist reproduction
The core problem is that a dodge is not a single action, it is a short sequence of states: startup, active i-frames, recovery, and an optional cancel window. A bug like got hit mid-roll could mean the invincibility window started a frame late, ended a frame early, or never armed because the player buffered the input during a hitstun transition. Each of those is a different bug with a different fix, but to the player they all feel identical, so the text of the report tells you almost nothing useful.
Add to that the fact that evasion is frame-sensitive and input-sensitive, and you get reports that depend on conditions the player will never think to mention: their framerate at that moment, whether they were mid-attack, what enemy attack overlapped the roll. Without the underlying state, you are guessing. You replay the obvious case, it works fine, you mark it cannot reproduce, and the same report comes back next week from someone else with a slightly different controller and a slightly different frame budget.
The dodge state machine is the real bug surface
Treat the dodge as an explicit state machine and most of the mystery evaporates. Name the states and log transitions: idle to dodge_startup, startup to iframe_active, iframe_active to recovery, recovery to cancelable. When a hit lands, the single most valuable piece of data is which state the player was in on that frame. Hit during iframe_active is a window bug. Hit during recovery is working as designed and probably a tuning complaint. Hit during startup means the i-frames had not armed yet, which is often a buffering issue.
Once you have the states named, the timing follows. Record the frame on which the dodge started, the first and last frame of invincibility, and the frame the damage was applied. Those three numbers tell you instantly whether the window was the right length and whether the hit fell inside or outside it. A report that arrives with iframe span 4 to 11 and hit on frame 12 is no longer a mystery, it is a one-frame recovery overlap you can tune or guard against.
Cancels, buffers, and the inputs that cause them
A large share of dodge bugs are really cancel and buffer bugs. Players report that a roll ate their attack, or that they could not cancel a roll into a block, or that a dodge came out when they meant to jump. All of these are about input timing relative to the cancel window, and none of them are reproducible without the input log. Capture the last several inputs with timestamps and the active cancel window at the moment of each one. The pattern usually jumps out: an input arriving two frames before the window opens that should have been buffered but was dropped.
Buffering interacts badly with state transitions, which is where the nastiest cases hide. A dodge buffered during hitstun, then released as the stun ends, can skip the startup state entirely and arm i-frames on the wrong frame. You will never reproduce that by hand because you cannot reliably press the button during a six-frame stun. But with the input timestamps and the state at each input, you can reconstruct it in a test harness and confirm the fix deterministically rather than by feel.
What to put in the report payload
Decide on a compact state snapshot that ships with every dodge-related report so you are not chasing data after the fact. At minimum: current dodge state, the i-frame start and end frames for the active dodge, the frame the report or hit occurred on, the current framerate, the last five inputs with timestamps, and the source of any damage taken. If your dodge has stamina or directional variants, include those too, since a backstep and a forward roll often have different windows and players conflate them.
Keep the snapshot cheap to assemble so you can attach it automatically rather than relying on the player to trigger it. The goal is that every roll bug arrives pre-loaded with the frame data an engineer would otherwise have to instrument and recreate. When the snapshot is consistent across reports, you can also start grouping them by state: all the hit during iframe_active reports cluster together and reveal a systemic window-length problem rather than ten unrelated tickets.
Setting it up with Bugnet
Bugnet is built for exactly this kind of state-heavy report. The in-game report button captures your custom game state automatically at the moment the player triggers it, so you attach the dodge state, i-frame window, frame counter, and recent input buffer as custom fields without writing any upload code. When a roll feels wrong, the player taps report and you receive the frame-level context they could never have typed out, alongside the device and platform details that explain the framerate they were running at.
Because evasion bugs repeat across many players, occurrence grouping does real work here. Bugnet folds duplicate reports into a single issue with a count, so fifty hit during roll reports become one prioritized issue you can sort by state. Filter by your dodge_state custom field to separate true i-frame window bugs from recovery-frame tuning complaints, and let the occurrence count tell you which one is actually hurting players the most this week instead of which one shouts loudest in your inbox.
Testing dodge fixes before they ship
Once you can reproduce a dodge bug from captured state, build a frame-stepping test that replays the input log against the dodge state machine and asserts on the i-frame window. This converts a feel-based complaint into a regression test: given these inputs at these frames, invincibility must be active from frame X to frame Y. Add a case for every distinct dodge bug you fix, and your evasion system stops regressing silently every time someone tweaks an animation length or a transition.
Pair that with a small amount of live telemetry. Even after a fix ships, keep capturing the dodge state on hit-during-evasion reports so you can confirm the field data matches your test assumptions across the framerates and controllers you cannot easily test locally. Dodge feel is the heart of an action game, and treating its bugs as measurable state rather than vibes is what lets a small team keep that feel tight as the game grows.
A dodge bug is a frame and a state, not a feeling. Capture both at the moment of the report and the impossible repro becomes a one-line assertion.