Help with Collision Detection / await frame

Godot Version

Godot 4.4.1

Question

Hey everyone

I am trying to make a procedural map generation work and am close to finishing the base setup.

TL;DR:
The collision check in my script works most of the time, but sometimes, randomly doesn’t.
if I add a timer with 0.3 to 0.5 seconds wait to the method, it is way more consistent - so I suspect a race condition.
Need help for a proper replacement for the timer.

GitHub with the project files: GitHub - brueningmax/procedualGenFix: Files for bugfix
In the RNGManager, I put the seed to one that has that issue anyway

Quick overview over the flow:

  • I have “map-chunks” that have “anchor-points”
  • the anchor points have a position and rotation and are for aligning the map chunks to each other
  • to check for collisions, I build an AABB box from the chunk scene, since eventually it will consist out of multiple meshes.

Workflow:

  • add the first chunk to the scene

then in a loop / on timer:

  • get all chunks in the scene and pick one
  • get all anchors of that chunk that are not used for a chunk-connection
  • pick a chunk scene for the new chunk, instantiate and add it to the scene
  • get a random anchor from the new chunk and use it to rotate and align the new_chunk so it fits to the old_chunk
  • check if the new chunk is colliding with anything else
  • clean up the scene and mark the anchors as occupied if placement is fine, otherwise repeat

it mostly works but the collision check is a problem.
It works most of the time, but then suddenly just doesn’t for like one call and then works again for several.
Here is the method for it:

func check_is_colliding(new_chunk: Node3D) -> bool:	
	var aabb: AABB = new_chunk.get_global_bounds()
	var shape = BoxShape3D.new()
	shape.size = aabb.size
	
	var shape_cast = ShapeCast3D.new()
	shape_cast.enabled = true
	shape_cast.collide_with_bodies = true
	shape_cast.max_results = 1
	shape_cast.shape = shape
	shape_cast.debug_shape_custom_color = Color.RED
	shape_cast.rotation = new_chunk.rotation
	shape_cast.target_position = Vector3(0, 0, 0)
	
	new_chunk.add_child(shape_cast)
	
	#shape_cast.force_update_transform()
	shape_cast.force_shapecast_update()
	
	var is_colliding = shape_cast.is_colliding()

	#shape_cast.queue_free()
	return is_colliding

I am using the AABB box as base for the shape since I don’t want to add an Area or shape to each scene that wraps every mesh in the scene.

the shapecasts are even highlighted green but somehow are just ignored, thus placing overlapping meshes

Since you mention a possible race-condition, I looked over the documentation for GDScript’s await keyword and any related features.

As it currently stands, the code for your check_is_colliding() function does not contain any coroutine-specific functionality. As such, it is not recognized as a coroutine when used as such inside of create_new_chunk(). As stated in the documentation:

If you use await with an expression that isn’t a signal nor a coroutine, the value will be returned immediately and the function won’t give the control back to the caller.

As for how to transform the check_is_colliding() function into a coroutine, I’m afraid I’m not the best person to ask. My first thought would, like you, be to await a timer for a small amount of time. However, I imagine there is a way to await a physics update so you don’t have to rely on an arbitrary waiting period between collision check iterations.

Does this suggest that even with a timer the system is not 100% reliable?


Sorry I can’t be of more help than this right now. If I think of something, I’ll keep you posted.

By the way, thanks for making a post with adequate information. That rarely happens.

Thanks for your input!
Tonight i will probably do some more testing to get to the core of it.

Yes, even with the timer, it is still not 100% reliable. It feels like it is a bit more reliable, but that might be a false impression due to the randomness and since without it I see errors faster.

But generally, would my approach be correct?
I also thought about using a grid map to denote which spaces are occupiedm but that would limit me to 2 dimensions and also limit me in designing the chunks.