I downloaded the project and found a few solutions, depending on which angle you want to take.
Solution 1: Use move_and_slide_with_snap
instead of move_and_slide
. If you replace move_and_slide(Vector2(motion_x, motion_y), UP_DIRECTION)
with move_and_slide_with_snap(Vector2(motion_x, motion_y), Vector2.UP, UP_DIRECTION)
then is_on_floor
will work as expecting. What is strange with this, in my opinion, is that jumping even works with this solution! I thought move_and_slide_with_snap
made jumping hard because the snapping code would force the character to stick to the ground, but I guess this is not the case.
Solution 2: Use another move_and_slide
call that pushes the character down slightly. If you add move_and_slide(Vector2.DOWN * 3, UP_DIRECTION)
after move_and_slide(Vector2(motion_x, motion_y), UP_DIRECTION)
, then is_on_floor
works as expected. The reason for this is that I am guessing it removes the slight upward position caused by colliding with the floor. Though, I have another hunch of why this fixes the issue, as seem after solution 3.
Also, I have no idea why multiplying by three makes it work. Anything less than 3 results in is_on_floor
being inconsistent.
Solution 3: In the gravity
function, when is_on_floor
is true, set the Y gravity to something small (like 10
) instead of 0
. This will continue to push the player against the floor at a small speed, similar to solution 2. With this alteration, is_on_floor
will react as expected.
I think the issue is that is_on_floor
only returns true if the player is actively colliding, actively pushing against, the floor. So, when the gravity is set to 0
when is_on_floor
is true, the player no longer is actively pushing against the floor and is_on_floor
returns false. Once is_on_floor
is false, gravity is applied again, pushing the player against the floor and setting is_on_floor
to true, repeating the cycle.
This is what I think is happening, based on the solutions found. This theory does not explain why solution 1 works though, but it would explain why solutions 2 and 3 work. This is also not how I expected is_on_floor
to work, though in hindsight I suppose it makes sense that is_on_floor
only returns true if the character is actively pushed against a floor.