Repository navigation
fix: character controller drops its move on a flat floor's rounding error - #1058
Open
VirtualMaestro wants to merge 1 commit into
Open
VirtualMaestro wants to merge 1 commit into
VirtualMaestro wants to merge 1 commit into
Conversation
…rror A floor normal one ulp short of unit length, e.g. (0, 0.99999994, 0), left a ~1e-9 downward part in `vertical_tangent`. `handle_slopes` read it as a slip and the non-slip-slope branch dropped `vertical_tangent`, which on a flat floor holds all or part of the horizontal move. A slip now needs a downward part above 1e-5 of the tangent's length. Fixes dimforge#809.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A character moving over a flat floor sometimes loses all or part of its horizontal motion for one step, and drifts
along the other horizontal axis (#809: "occasionally sticks", x drift while walking along z). The same thing happens
to a character carried on a moving collider: on some steps the carry is dropped.
Cause
The shape cast returns the floor normal one ulp short of unit length:
(0, 0.99999994, 0), or with a ~5e-9 tilt(±4.8e-9, 0.99999994, ±4.8e-9).decompose_hittakes the horizontal tangent direction asnormal1 × up. For a normal parallel toupthat iszero, so the whole tangent lands in
vertical_tangent. With the 5e-9 tilt it points along an arbitrary diagonal,so about half of the move lands there. (In 2D the horizontal tangent is always zero.)
vertical_tangentkeeps a downward part of about -1.9e-9.handle_slopesreadsup · vertical_tangent < 0asslipping.slipping_intentis false, so the non-slip-slopebranch keeps
horizontal_tangent + normal_partand dropsvertical_tangent, i.e. the horizontal move.Trace of the reproduction from #809 (second comment), step 24 at v0.36.0:
Fix
slippingnow needs a downward part above1e-5of the tangent's length:The bound it introduces: a slope within 1e-5 rad (0.0006°) of horizontal no longer counts as slipping, so a character
standing on it slides by under 1e-5 of its vertical move per step. Nothing else changes.
Tests
character_controller_flat_ground_keeps_horizontal_motion: a port of the 3D kinematic character jumping/jittering on flat surface #809 reproduction (capsule walkingalong z at 9 m/s on a body-less box floor, dt 1/30, 200 steps). It asserts the z move of every step within 1e-3 of
the desired one and |x| < 1e-2. On master without the fix it fails at step 69 (0.24 instead of 0.3); with the fix
the worst z error is 1.6e-4 and the largest |x| 1.25e-3.
character_controller_ground_detectionpasses, and its reach improves from 933.8 / 974.3 to 998.2 / 999.1 (no snap/ snap; ideal 1000). The comment there blames "accumulated numerical error" for the shortfall; most of it was this.
cargo test -p rapier3d: 444 passed, 0 failed (lib 82, integration and doc tests).cargo test -p rapier2d: 216 passed, 0 failed (lib 64).cargo fmt -- --checkclean;cargo clippy -p rapier3d --testswith-D warningsclean.(Windows, stable-x86_64-pc-windows-gnu.)
Note for review
In
character_controller_ground_detection, the fix ends the balls lower than before (final y 0.30 / 0.04 insteadof 0.95 / 0.99; they start half inside the floor). Started at rest on the floor (y 1.01) instead, the no-snap ball
sinks to y -0.5 and the test's
groundedassert fails at step 6043. The sink is not in the controller. It comesfrom the shape cast against the test's 2002 m wide cuboid: in f32, parry's GJK ray cast stalls on a simplex face
inside the CSO, about 1400 m from the origin, and then reports
Noneor a time of impact up to 9 cm past thesurface. A ball resting at the target distance then moves the full -0.1 into the floor on step 0. With a half-space
floor at the same height, the test shows no sink with or without this fix (final y 1.0101, reach 999.3 / 1000.5
of the ideal 999.4 / 1000.6). Without the fix, the false slip dropped the move on many steps and applied only the
upward nudge, which lifted the balls back out. I can open a separate parry issue with the traces.
Not checked: the y bouncing under 100x gravity in the first report of #809, and the 2D reproduction in its third
comment.
Fixes #809
🤖 Generated with Claude Code