Remove intersecting instances

Godot Version

4.3 `

Question

I have a 3D scene.
I want to immediately instantiate a number of tiles, corridors and intersections, that all connect to each other.
They have collision shapes associated with them.
So far everything works.
But I don’t want them to overlap each other.
So the way I want it to work is place a tile, check for collision, if collision, remove.
But all the collision checks happen after instancing.
I’ve tried sending signals from the collision boxes to the script.
And to compare the tiles direct_space_state shape and transform to the worlds direct_space_state. And if intersection occurs, remove.
But so far I can’t get it to work, I’ve been stuck on this for two days.

func placeCorridorAtMarker(marker):
	
	corridorList = [tile5, tile10, tile15] 
	
	var tileInstance = corridorList.pick_random().instantiate()
	add_child(tileInstance)
	tileInstance.position = marker.global_position
	tileInstance.rotation = marker.global_rotation
	
	#Check for overlaps before finalizing
	if is_tile_overlapping(tileInstance):
		print("Overlap detected, removing the new tile.")
		tileInstance.queue_free()
	else:
		print("No overlap, tile added successfully.")
		corridorArray.append(tileInstance)

func is_tile_overlapping(tileInstance) -> bool:
	# Find the CollisionShape3D within the tile instance
	var collision_shape = tileInstance.get_node("MeshInstance3D/Area3D/CollisionShape3D")
	if not collision_shape:
		print("Error: No CollisionShape3D found in tile!")
		return true  # Assume overlap if there's no collision shape
	
	# Use the CollisionShape3D's shape and global transform for the test
	var shape = collision_shape.shape
	if not shape:
		print("Error: CollisionShape3D has no shape!")
		return true  # Treat as overlapping by default (or false if you'd prefer)
			
	var transform = collision_shape.global_transform
	# Debug: Print transform and shape info
	print("Tile transform: ", transform)
	print("Tile shape: ", shape)
	# Access the direct space state
	var space_state = get_viewport().get_world_3d().direct_space_state
		
	#prepare the physicsShapeQueryParameters3D
	var query = PhysicsShapeQueryParameters3D.new()
	query.shape = shape
	query.transform = transform
	query.margin = 0.1  # Small margin to handle precision issues
		
	var result = space_state.intersect_shape(query, 32)  # Max 32 results
	if result.size() > 0:
		print("Overlap detected! Result: ", result)
		return true  # Overlap detected
	else:
		print("No overlap, tile added successfully.")
		return false  # No overlap

What exactly are the tiles? Is this a GridMap?

No gridMap
they are Meshinstance3D with CollisionShape3D
they have different sizes

I can’t immediately see anything that’s wrong, at least not without the help of the editor.

I would start off by setting a breakpoint at the end of your placeCorridorAtMarker() function, just underneath your if-else (typed out, not through the red dot). Then, once the breakpoint trips, I would look at the Debugger tab to check if there are any values that are inconsistent from what I’d expect.

For help on breakpoints and other debugging tools, here’s the doc: Overview of debugging tools — Godot Engine (stable) documentation in English

1 Like

I got it working sort of
I had to set the PhysicsShapeQueryParameters3D to search for collide with areas.
And put await get_tree().physics_frame inbetween the placement of tiles.
Its’s adding tiles, and removing the ones that intersect.
But another issue I have noticed is I geet tiny offsets between the placed tiles:

add_child(tileInstance)
	corridorArray.append(tileInstance)
	tileInstance.position = entrance.global_position
	print("entrance pos:", entrance.global_position)
	print("tile pos;", tileInstance.global_position)

gives this output:

entrance pos:(5, -0, -0)
tile pos;(4.99997, 0.011949, -0.011669)

1 Like

My Parent node in the scene was slightly rotated, that’s the reason for the offsets.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.