Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KinematicBody2D.is_on_floor() returns false when body is on the floor and moving parallel to the floor #54975

Open
kleonc opened this issue Nov 14, 2021 · 4 comments

Comments

@kleonc
Copy link
Member

kleonc commented Nov 14, 2021

Godot version

3.4.stable

System information

Windows 7

Issue description

When a KinematicBody2D is on the floor (the collision shapes just "touch" each other) and it's not moving (velocity is zero) then after calling move_and_slide() it correctly reports that it's on the floor. When moving in parallel to the floor it reports it's not on the floor anymore. After stopping it correctly reports being on the floor again.

In action:
AEr2lbvzKA

extends KinematicBody2D

export(float) var speed = 100
var velocity := Vector2.ZERO

func _physics_process(_delta: float) -> void:
	velocity.x = speed * Input.get_axis("ui_left", "ui_right")
	velocity = move_and_slide(velocity, Vector2.UP)
	print("is_on_floor()=%5s v=%s" % [ is_on_floor(), velocity ])

Steps to reproduce

Place a KinematicBody2D on the floor so the collision shapes will just "touch" each other. Then move that body in parallel to the floor's surface.

Minimal reproduction project

kb2d-is_on_floor-parallel-movement.zip

@Sslaxx
Copy link

Sslaxx commented Nov 14, 2021

This is a known issue. Best thing to do is to add a little bit to the y value of velocity to simulate gravity, keeping consistency for is_on_floor to work.

@kleonc
Copy link
Member Author

kleonc commented Nov 14, 2021

This is a known issue.

I've searched a little before and haven't found it reported. I don't see it in #45334 too.

Best thing to do is to add a little bit to the y value of velocity to simulate gravity, keeping consistency for is_on_floor to work.

Yeah, I know that workaround. Thanks nonetheless.

@Calinou Calinou added this to the 3.4 milestone Nov 14, 2021
@ludomosa
Copy link

The only thing that's not working as expected is returning true at all in this instance. The body is not moving into the floor, and so it doesn't collide with it, where a velocity of (0, 0) appears to be a corner case where it falsely reports a collision. You should always add gravity to the velocity to continuously push the body into the ground, in which case it should work as you expect.

This is not a workaround, it's just how the simulation operates; part of the work of the physics simulation is separating bodies that have overlapped each physics frame to ensure they are no longer overlapping. If you want the two objects to be constantly overlapping one another every frame (i.e. collide), you should constantly push them into one another, in this case via gravity on the KinematicBody2D.

@AttackButton
Copy link
Contributor

AttackButton commented Dec 11, 2021

As I mentioned in #49497 (comment), stop_on_slope can fix this type of bug even when the KB2D is out of a slope. I really don't know why.

This same situation happens in godot-4 I think (the comment in the link above is in godot-4).

The workaround is to use stop_on_slope:

Changing

velocity = move_and_slide(velocity, Vector2.UP)

to

velocity = move_and_slide(velocity, Vector2.UP, true)

is_on_floor_bug

@akien-mga akien-mga modified the milestones: 3.4, 3.x Jul 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants