Quick answer: Projectile bugs are state, trajectory, collision, and sync bugs. Capture the projectile's spawn state, its trajectory over time, the collision result, and the network sync state with every report. With that timeline you reproduce a projectile that tunneled through a target, curved wrong, or desynced between client and server, instead of guessing from a clip.
Projectile weapons feel better than hitscan because the shot travels, arcs, and can be dodged, but that travel is exactly what makes their bugs hard to reproduce. A rocket passes clean through an enemy at point-blank range. An arrow curves differently than the player expected. In multiplayer a grenade explodes in a different spot on each player's screen. Each of these is about the projectile's state and trajectory over time, its collision detection, and how that state is synchronized across the network. A single clip cannot show you the projectile's velocity, its collision settings, or what the server thought happened. The fix is to capture the projectile's life as a timeline. This post covers what to record and why tunneling and sync make projectiles tricky.
A projectile has a life, not a single frame
Unlike a hitscan shot that resolves instantly, a projectile exists over many frames, moving each tick under velocity, gravity, drag, and sometimes homing or wind. Its behavior is the integral of those forces over its flight, so a bug can originate at spawn, accumulate during travel, or strike at collision. To understand a projectile bug you need its state over time, not a snapshot: the spawn position and velocity, the forces acting on it, and its position each tick until it hit something or expired. A trajectory is a story, and you cannot diagnose where it went wrong from only the final frame.
Capturing the spawn state precisely matters because many projectile bugs are born there. The projectile may spawn at the muzzle while the player aimed from the camera, so it launches at a slightly wrong angle that compounds over distance. It may inherit the shooter's velocity incorrectly, drifting sideways. It may spawn inside the player's own collider and immediately collide with the shooter. Recording the exact spawn position, orientation, and initial velocity, alongside where the player aimed, catches this whole class of bugs that look like aiming problems but are really launch problems.
Tunneling and collision
The signature projectile bug is tunneling: a fast projectile moves so far in one physics tick that it passes entirely through a thin target or wall without ever overlapping it, so no collision registers. A rocket through an enemy at close range is usually this. The fix is continuous collision detection, casting a ray or sweep along the projectile's movement each tick rather than testing only its discrete positions, but you need to confirm tunneling is the cause. Capturing the projectile's per-tick positions and its speed lets you see whether it skipped past the target between two ticks, which is the smoking gun for tunneling.
Beyond tunneling, capture the collision result itself: what the projectile hit, at what point, and what collision layers and filters were in effect. Projectiles often have nuanced collision rules, ignoring the shooter for a few frames, passing through teammates, or detonating only on certain surfaces, and bugs hide in those rules. A grenade that bounces off a target it should detonate on, or one that ignores an enemy because a layer filter is wrong, is a collision-configuration bug. Recording the collision settings and the actual collision event distinguishes a physics tunneling problem from a filtering mistake, which are fixed in entirely different ways.
Network sync and desync
In multiplayer, projectiles must agree across machines, and that is hard because each client predicts the projectile's flight to feel responsive while the server holds authority. Bugs appear as desync: the projectile is in a different place on the shooter's screen than on the target's, or it explodes at different spots for different players. To debug it you must capture how the projectile was synchronized, whether it was client-predicted, server-authoritative, or both, the spawn timestamp, and the positions the projectile occupied on the client versus what the server computed. Lining up these timelines reveals where prediction and authority diverged.
Capture the latency and the reconciliation behavior too. A client predicts a projectile forward, the server simulates it authoritatively, and at some point the client must reconcile its predicted position with the server truth, which can cause a visible snap if they disagree. A projectile that hits on the shooter's screen but the server says missed is the projectile equivalent of a hitscan registration dispute, and it needs the same data: latency, the authoritative trajectory, and the predicted one. With both timelines captured you can see whether the server simulated different forces, used a different spawn position, or reconciled at the wrong moment.
Make projectiles deterministic and replayable
Projectile physics should be deterministic given the spawn state and the forces, which lets you replay a captured trajectory exactly. Run projectile simulation on a fixed time step so the same spawn produces the same flight regardless of frame rate, and avoid frame-rate-dependent integration that makes fast projectiles behave differently on different machines. Build a debug mode that records each projectile's full timeline, spawn state, per-tick positions, forces, and the collision result, and lets you replay it with the trajectory drawn in the world. A tunneling miss or a wrong curve becomes immediately visible when you can see the path.
On the network side, log both the client-predicted and server-authoritative trajectories for a short window, keyed to the same projectile, so desync disputes can be audited after the fact. Drawing both paths in a debug build, in different colors, makes a divergence obvious at a glance. Where the trajectory is deterministic, a captured spawn state replays into the identical flight, so you can reproduce a reported bug precisely and then fix the integration, the collision sweep, or the reconciliation. Save the captured trajectory as a regression test that simulates the spawn and asserts the expected collision, so the fix stays fixed.
Setting it up with Bugnet
Bugnet's in-game report button captures device and platform context automatically, including the network context projectile sync depends on. You add custom fields, or attach a small payload, for the projectile's spawn state, its per-tick trajectory or a summary of it, the collision result and layers, and in multiplayer the client and server positions and the latency. Because the button snapshots state when a player reports a rocket passing through an enemy, you receive the projectile's actual flight and collision data, not a clip that only shows the final frame. That timeline lets you replay the flight and find where it went wrong.
Occurrence grouping highlights which projectile bugs are systemic. If a fast projectile consistently tunnels through thin cover, Bugnet folds those reports into one issue with a count, pointing at missing continuous collision rather than a few odd misses. Filter by weapon using a custom field to find a projectile whose speed outruns its collision, filter by latency band to isolate sync issues among high-ping players, and keep every trajectory in one dashboard. Projectile feel and fairness generate a steady stream of subjective complaints, and captured trajectories plus grouping turn them into specific physics, collision, and netcode bugs you can prioritize.
Ship projectiles that feel honest
Projectiles are satisfying when they go where players expect and land when they should, and they feel broken the moment they tunnel or desync. Use the captured trajectories to confirm continuous collision is catching fast projectiles, to verify collision filters match design intent, and to tune your network reconciliation so predicted and authoritative paths agree closely enough that players never see a jarring snap. Every projectile bug you fix should leave a regression test built from the captured spawn state, so a physics or netcode change cannot silently reintroduce the tunneling or the desync you already resolved.
Treat each projectile as a deterministic simulation whose outcome is a function of its spawn state, the forces, the collision rules, and the network reconciliation, all of which you can capture and replay. Once reports carry the trajectory and sync data, you build projectile logging and dual-path auditing, and you grow a test suite of corrected flights, the it went right through them and it blew up somewhere else on my screen complaints become specific, fixable bugs. Players feel projectiles that behave consistently for everyone, and you can extend your arsenal with confidence that the data and tests will catch any flight gone wrong.
A projectile is a deterministic flight, not one frame. Capture the spawn, trajectory, collision, and sync and tunneling and desync become reproducible.