Area3D not detecting imported collision as I expected

Godot Version

4.5

Question

I have 2 area3Ds (front edge area & back edge area)for detecting edge of the floor. If there is a physicbody (floor) in one and not the other then it would be the edge, using an edge_area bool.

I’m using this bool to associate my player’s conditions with it. eg,

  • When both areas are detecting the floor it should mean it is a flat floor (edge_area = false) and player can go into Crawl state

  • But if ONE of areas is not detecting anything then it is the edge (edge_area = true) player can only go into Crouch state.

  • If he is in crawl state and moves to the edge (edge_area = true) he will automatically goes into crouch state.

The problem is that this works fine when detecting primitive collision box shape BUT NOT for those imported collisions from Blender (using-colonly). On imported collisions if both areas are detecting floor the edge_area should return “false” but it returns “true” (therefore player can only go into Crouch but never Crawl on flat floor).

My tested code using signals:

func _on_front_edge_area_3d_body_entered(body: Node3D) -> void:
	front_area = true
func _on_back_edge_area_3d_body_entered(body: Node3D) -> void:
	back_area = true
func _on_front_edge_area_3d_body_exited(body: Node3D) -> void:
	front_area = false
func _on_back_edge_area_3d_body_exited(body: Node3D) -> void:
	back_area = false

func process():
	if front_area == false and back_area == false:
		edge_area = false
	elif front_area == false and back_area == true:
		edge_area = true
	elif front_area == true and back_area == false:
		edge_area = true
	elif front_area == true and back_area == true:
		edge_area = false

I have also tested with overlap_bodies() :

	if front_edge_area3d.monitoring == true and back_edge_area3d.monitoring == true:
		var overlapping_bodies_f = front_edge_area3d.get_overlapping_bodies()
		var overlapping_bodies_b = back_edge_area3d.get_overlapping_bodies()
		### if one of area not detecting floor
		if overlapping_bodies_f.is_empty() or overlapping_bodies_b.is_empty():
			edge_area = true
		### if both are detecting floor
		if !overlapping_bodies_f.is_empty() and !overlapping_bodies_b.is_empty():
			edge_area = false

How should I go about this?

Don’t use Area3D for this because they only update once per physics frame. Use a RayCast3D or ShapeCast3D which you can force to update as many times as you need with RayCast3D.force_raycast_update() or ShapeCast3D.force_shapecast_update()

2 Likes

I guess I’d have to use Raycast.

Regarding the imported collision, I’m guessing because it’s made up of small triangular collisions so Area has a hard time constantly checking?