Applying gravity only when not on floor?

Godot Version

Godot Engine v4.6.stable

Question

Hi!

In a lot of the examples I checked about CharacterBody3D, I’ve seen that the gravity is applied only when “is_on_floor()” returns false.

if not body.is_on_floor():
	velocity += gravity * delta

Is it really the way to do it? Just a small optimization?
For most common use cases, this seems right and is working well, but in mine, it triggers an issue when moving on a curved surface with my custom gravity system (actually small planets, my gravity system updating CharacterBody3D.up_direction): “is_on_floor()” oscillate between true and false. I expected the same problem when walking down on slopes or on curved surface in static gravity conditions, but I didn’t notice anything.

I initially though of a problem with snapping function but I haven’t found a lot of information about it and couldn’t solve my problem that way.
What actually solved it without triggering any other issue is removing “is_on_floor()” check and simply applying gravity every frame.
So in practice, I no longer have any issue, everything is working as expected, but I’m questioning that practice or the way I solved my issue.

Is it wrong applying gravity that way? Did I miss something about the snapping function?

a code that works ; is the right code :moai:

for oscillation between true and false ; you should increase the gravity ; when your player is passing a curved floor . it can handle by a Raycast .

Yes, I guess you’re right. It’s more a discussion to better understand this and make sure I didn’t get something wrong than a request for help :slightly_smiling_face:

In very strong gravity condition, the character barely jumps, stick to the surface, but “is_on_floor” state still oscillate when moving.

Character bodies have a property for the “up” direction that determines what is a floor, wall and ceiling. For 2D see – CharacterBody2D — Godot Engine (stable) documentation in English and there’s a similar property for 3D.

3 Likes

Yes, my script is actually updating that up_direction property. I don’t think that is the issue.

You’re encountering a similar problem to what occurs with is_on_wall(). In that case, it is only true if the player is moving towards a wall. You have an edge case. There are two options. You can make gravity always apply like you did. Or, you can use a RayCast2D opposite of the UP direction to determine when to apply it.

I recommend considering using the Area2D gravity override properties. Then you can just use get_gravity() and apply it. What you’re doing is likely not causing the problem you’re seeing, but it might be, and it might cause other unforeseen problems in the future.

I’m working in 3d, but it is exactly what I’m doing. Are the Area2D/Area3D gravity override system supposed to automatically update the up_direction? I maybe should make another try not updating it manually.

Anyway, if there isn’t any problem with applying gravity all the time, I think I’ll stick with that solution.

Thanks you for your answers

1 Like

Sorry, my mistake. Works the same for 3D.

I took a look at up_direction again and it looks like there’s nothing wrong with updating it. It determines what is a floor, wall and ceiling. Personally, I use is_on_ceiling() instead of inverting it, but it makes sense with what you described.

1 Like