How to implement falling platforms? Why have these attempts failed?

Godot Version

v4.2.stable.official [46dc27791]

Question

Hi! I come from the Unity3D crowd and I am making a game just to start learning then engine.

I am trying to implement 3D falling platforms (platforms that fall after a few seconds after the player steps on them).

This is my player hierarchy:
CharacterBody3D
CollisionShape3D
MeshInstance3D

This is my platform hierarchy, I instantiate platforms from a scene:
RigidBody3D
CollisionPolygon3D
MeshInstance3D

The rigid body has “max_contacts” to 5 and “contact_monitor” activated.

My first attempt was from the platform script:

func _on_body_entered(otherBody):
print(“touched!”)

I linked that to the body entered signal, hit play and nothing happened. Tried a couple other signals and configurations of the rigidbody to no avail.

I decided to watch a tutorial and found one of this exact mechanic, just in 2D. I thought that it should work even if I am on 3D. It is done from the player script, wich I don’t think is good architecture, but since I am learning and doesn’t have to be perfect I try anyway.

func _physics_process(delta):

Add the gravity.

if not is_on_floor():
velocity.y -= gravity * delta

Handle jump.

if is_on_floor():
velocity.y = JUMP_VELOCITY
# Check platforms
for collision_index in get_slide_collision_count() - 1:
var current_collision = get_slide_collision(collision_index)
if current_collision != null :
print(current_collision.get_collision_count())
if current_collision.get_collision_count() > 0 :
for collider_index in current_collision.get_collision_count() :
if current_collision.get_collider(collider_index).has_method(“collide_with”):
current_collision.get_collider(collider_index).collide_with(current_collision, self)

I check every step of the way for null values because I got null references when trying to access the collider.
This gives me very erratic results, nothing happens when bouncing in the platform the player spawns in or others very close, but when moving around to other platforms I would get like 6 colliders from this print.

Should the final “current_collision.get_collider(collider_index).collide_with(current_collision, self)” be called, would that call the “_on_body_entered()” on the platform?

Why I am not getting collisions until I change platforms?

Why the “_on_body_entered()” was not called in my first attempt?

Thanks for your attention.

You need to call move_and_slide() to update the slide collisions information. Do it before checking them.

	# your movement code
	
	move_and_slide()

	for i in get_slide_collision_count():
		var collision = get_slide_collision(i)
		if collision.get_normal().is_equal_approx(Vector3.UP): # only if the character is totally on top of the platform
			var collider = collision.get_collider()
			if collider.has_method('start_fall_timer'):
				collider.start_fall_timer()

And here’s the RigidBody3D script:

extends RigidBody3D

@onready var timer: Timer = $Timer

func _ready() -> void:
	freeze = true


func start_fall_timer() -> void:
	if timer.is_stopped():
		timer.start(3)
		await timer.timeout
		freeze = false
1 Like

Thank you very much for your answer, I’ll keep in mind that move_and_slide updates de collisions.