Quick answer: Swimming bugs hinge on water volume detection, buoyancy forces, and the camera and control mode switch that happens at the surface. The waterline is the danger zone, where the player bobs between modes. Capture the water volume the player is inside, the submersion depth, the buoyancy state, and the active control and camera mode so a stuck or flickering swim transition can be replayed exactly.
Swimming looks simple and is quietly one of the most bug-prone systems in a game. It introduces a whole alternate movement mode with its own controls and camera, gated by whether the player is inside a water volume and how deep. The transitions in and out are the hard part: enter the water and controls flip to swimming, surface and they flip back, and right at the waterline the player can bob between the two faster than the system can settle. Reports come in as stuck at the surface, controls froze, camera went crazy, or fell through the pool floor. This post covers capturing water volume, buoyancy, and mode state so those waterline bugs become reproducible.
The waterline is a mode-switching trap
A swimming system is really two movement systems and a switch between them. On land the player walks and the camera behaves one way; in water they swim with different physics, different input mapping, and often a different camera. The switch is driven by water volume detection: is the player inside a trigger volume, and how submerged are they. That sounds clean until the player sits exactly at the surface, where a small bob of the camera or a wave can push the detection point in and out of the volume every few frames, and the system thrashes between modes.
This thrashing is the source of the classic swimming bugs. Controls freeze because the mode switched mid-input and dropped the state. The camera snaps between underwater and above-water framing. The player appears stuck, neither swimming nor walking, because each mode keeps handing control back to the other. To debug any of this you need to know, frame by frame, which water volume the system thought the player was in, how deep it measured them, and which control and camera mode was active. The visible symptom is a consequence of that mode state, not the bug itself.
Capture the water volume and submersion
The foundational state is the water volume relationship: which volume or volumes the player is currently inside, the water surface height at the player's position, and the submersion depth measured from whatever reference point your detection uses, usually a point on the character. Log whether that point is above or below the surface and by how much. A huge share of swimming bugs come from the detection point being placed badly, at the eyes, the chest, or the feet, so the player triggers swim mode while their head is clearly above water, or stays walking while obviously submerged.
Overlapping and adjacent volumes deserve special care. Pools, rivers, and oceans are often built from multiple triggers, and the seams between them are where players fall through floors or get stuck between volumes that disagree about the surface height. Logging the full set of volumes the player overlaps, and each one's surface height, exposes these seam bugs immediately. When a report says the player sank through the pool bottom, the volume log usually shows two adjacent volumes handing the player off badly, or a gap between them where neither claimed the player and gravity took over.
Buoyancy and the control mode
Capture the buoyancy state alongside the volume data: the buoyant force being applied, the player's vertical velocity, and whether they are floating, sinking, or held at the surface. Buoyancy bugs show up as players who cannot surface, bob uncontrollably, or get pinned underwater. The force depends on submersion depth, so it is tightly coupled to the detection accuracy from the previous section. Logging the computed buoyant force next to the measured depth lets you see when the force was wrong because the depth was wrong, versus when the buoyancy curve itself is mistuned.
Then log the active control and camera mode and every switch between them, with the trigger for each switch. This is the single most valuable thing for waterline bugs, because it shows the thrashing directly: swim, walk, swim, walk across consecutive frames as the detection toggles. Once you can see the mode oscillating you know the fix is hysteresis or a settling delay on the transition, not a change to the swim physics. Without the mode-transition log you would be staring at frozen controls with no idea that the real problem is two modes fighting over a player sitting at the surface.
Common swimming failure modes
The recurring bugs are mode flicker at the surface, falling through the floor at volume seams, detection that triggers at the wrong body point so swim mode starts too early or too late, buoyancy that traps the player above or below the surface, and camera transitions that snap or invert when crossing the waterline. There is also the entry-velocity problem, where a player diving in at speed punches too deep before buoyancy catches them, or skips off the surface entirely because the volume detection missed them on a fast frame. Each has a distinct signature in the volume and mode logs.
Edge cases multiply with shallow water, moving water, and water that can be drained or filled. Shallow water where the player can both stand and the swim trigger fires is a perennial source of mode confusion. Moving water surfaces, like waves or a rising flood, make the surface height a moving target that the detection must track each frame. Draining a volume mid-swim should drop the player gracefully but often strands them in swim mode in empty air. Logging the volume's current surface height and fill state across frames is what makes these dynamic cases debuggable rather than mysterious.
Setting it up with Bugnet
Bugnet's in-game report button lets a player flag a swimming problem the moment it happens, while they are still bobbing at the surface or stuck on the floor. The SDK attaches the water context you capture: the volumes the player overlaps, the surface heights, the submersion depth, the buoyancy force, and the control and camera mode history. The report arrives in your dashboard with the mode-transition record already attached, so you can see the thrashing or the seam handoff directly, instead of trying to interpret a player saying the water felt broken.
Water bugs are usually tied to specific bodies of water in specific levels, a particular pool seam, a shallow pond, a flooded room, so the same spot snags many players identically. Bugnet groups these into one issue with an occurrence count, and with the water volume id or level location as a custom field you filter straight to the problem volume. Seeing that one pool accounts for hundreds of stuck-at-surface reports makes prioritization trivial and tells your level designer exactly which volume or seam to rebuild, instead of guessing from scattered anecdotes about funny water.
Testing swimming and the surface transition
Build a deterministic test bench that drives a bot through every water scenario: entering slowly and at speed, sitting exactly at the surface, crossing volume seams, swimming in shallow water, and surviving a volume that drains or fills mid-swim. Assert that the control mode never oscillates across consecutive frames, that the player never ends up below a volume's floor, and that buoyancy settles the player to the surface within a bounded time. Run it headless in CI so a change to the detection point or buoyancy curve that reintroduces mode flicker fails the build.
Turn real reports into fixtures by replaying their captured volume and mode state and asserting the transition now resolves cleanly. Add runtime robustness too: hysteresis on the swim and walk switch so a single frame of detection noise cannot thrash the mode, a settling delay at the surface, and a graceful drop when a volume drains. The combination of deterministic scenario tests, real-report fixtures, and a hysteresis-protected transition keeps swimming feeling natural while ensuring the inevitable waterline edge case is captured, reproducible, and fixable rather than a recurring source of frustration.
Swimming bugs live at the waterline where two modes fight. Capture the volume, depth, and mode transitions and the stuck-at-surface report becomes replayable.