Godot Version
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
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.