How to check if rigid body is on floor

godot4

Question

how to check if rigid body is on floor is it possible?!?

pls anybody

You will need contact monitoring on and at least 1 max contacts reported. The most accurate way would be to use `_integrate_forces` and iterate over contacts looking for a â€śupâ€ť facing normal vector.

``````func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
var on_floor: bool = false
var i := 0
while i < state.get_contact_count():
var normal := state.get_contact_local_normal(i)
on_floor = normal.dot(Vector3.UP) > 0.99 # this can be dialed in
#  1.0 would be perfectly straight up
#  0.0 is a wall
# -1.0 is a ceiling
i += 1
``````

A less accurate way would be using on_body_entered signal and check if the other body is lower on the y axis.

im still kinda new. what is contact monitoring

a property of rigid bodies

ok. now would the function you made above return anything? how would i use it in the context of

if on_floor:
jump

The function above is an override of RigidBody3Dâ€™s `_integrate_forces` it cannot return anything. Data to be shared from this function needs to be stored elswhere, like a global variable. Also, multiple collisions might not be on the floor so some extra logic to merge per-frame collisions should help.

``````var on_floor: bool = false # now global!

func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
on_floor = false # reset on_floor for this physics frame

var i := 0
while i < state.get_contact_count():
var normal := state.get_contact_local_normal(i)
var this_contact_on_floor = normal.dot(Vector3.UP) > 0.99

# boolean math, will stay true if any one contact is on floor
on_floor = on_floor or this_contact_on_floor
i += 1``````

im getting this error

Parser Error: The function signature doesnâ€™t match the parent. Parent signature is â€ś_integrate_forces(PhysicsDirectBodyState2D) â†’ voidâ€ť.

nvrm just had to change from Vector3 to Vector2 also changed PhysicsDirectBodyState3D to PhysicsDirectBodyState2D. how do i call this function now

1 Like

it will be called automatically every physics frame. much like how `func _process` is called every frame automatically.

i did this and it only says false

``````func _physics_process(delta):
print(on_floor)
``````

i know that the function is running, the function just isnt working

Might be too accurate/particular `0.99` is little tolerance, might be running the function too often for non-physics processes to catch it. To try an deduce which letâ€™s use the last floor touched time instead

``````var on_floor_time: int = 0 # now numeral!

func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
# we do not reset time

var i := 0
while i < state.get_contact_count():
var normal := state.get_contact_local_normal(i)
var this_contact_on_floor = normal.dot(Vector3.UP) > 0.99

if this_contact_on_floor:
on_floor_time = Time.get_ticks_msec()
break
i += 1
``````

Now printing the `on_floor_time` should show a number other than zero at some point, otherwise our `0.99` really is a stickler and should be reduced. Try some incrementally lower numbers until it feels right.

now its just giving me 0 i tried changinmg the number but it didnt work

Strange, my minimal tests are working even with 0.99 (thinking about it more `> 0.0` would be prefered aka â€śnot a wallâ€ť). Are you sure contact monitoring is on and there is at least 1 max reportable contact?

that was the problem. i turned on contact monitoring and 1 max reportable contact (didnt work) then i turned on cast shape and now it works. thanks

is there a way to change the tolerence? example: if rigid body is like 10 pixels away from ground it still becomes true

I would say shrink the collision shape, a higher physics tick rate might also help but you would have to take the time since last floor hit approach.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.