Detect Area3D projectile collision with specific mesh in GridMap

Godot Version

4.6

Question

My projectile is an Area3D and I want to detect what specific mesh of a mesh lib I have hit when colliding with a GridMap. The two orange blocks are part of my GridMap.

Here my projectile script so far:

func _on_body_entered(body: Node3D) -> void:
		
	if body is GridMap:
		print("body.get_used_cells: " + str(body.get_used_cells()))

		var local_point = body.to_local(self.global_position)
		print("local_point: " + str(local_point))
		var cell_pos = body.local_to_map(local_point)
		print("cell_pos: " + str(cell_pos))
		
		var tile_under = body.get_cell_item(cell_pos)
		print("tile_under: " + str(tile_under))

These are the values returned:

body.get_used_cells: [(4, 0, 4), (2, 0, 0)]
local_point: (1.724375, 1.755784, -0.124894)
cell_pos: (3, 1, -1)
tile_under: -1

I am not sure what I am missing here to detect the correct item from the mesh lib?

OK, I have adjusted my code to check for the _on_body_shape_entered signal:

func _on_body_shape_entered(body_rid: RID, body: Node3D, body_shape_index: int, local_shape_index: int) -> void:
	print("body.get_used_cells: " + str(body.get_used_cells()))
	var local_point = PhysicsServer3D.body_get_shape_transform(body_rid, local_shape_index)
	print(local_point)
	print('--------------------------')
	
	#local_point.origin.y = 0
	var cell_pos = body.local_to_map(local_point.origin)
	print("cell_pos: " + str(cell_pos))
	
	var tile_under = body.get_cell_item(cell_pos)
	print("tile_under: " + str(tile_under))

This gives me:

body.get_used_cells: [(-9, 0, -3), (-9, 0, -7), (-9, 0, -11), (-9, 0, -15), (-9, 0, -19), (-9, 0, -23), (-9, 0, -27), (-9, 0, -31), (-9, 0, -35), (-6, 0, -36), (-2, 0, -36), (2, 0, -36), (6, 0, -36), (8, 0, -3), (8, 0, -7), (8, 0, -11), (8, 0, -15), (8, 0, -19), (8, 0, -23), (11, 0, -24), (15, 0, -24), (19, 0, -24), (23, 0, -24), (27, 0, -24), (10, 0, -36), (14, 0, -36), (18, 0, -36), (22, 0, -36), (26, 0, -36), (30, 0, -36), (34, 0, -36), (38, 0, -36), (42, 0, -36), (46, 0, -36), (28, 0, -21), (28, 0, -18), (28, 0, -14), (28, 0, -10), (38, 0, -23), (38, 0, -19), (38, 0, -15), (38, 0, -11), (38, 0, -7), (35, 0, -6), (31, 0, -6), (29, 0, -6), (41, 0, -24), (45, 0, -24), (49, 0, -24), (28, 0, -7), (19, 0, -8), (19, 0, -4), (50, 0, -36), (54, 0, -36), (59, 0, -36), (65, 0, -36), (70, 0, -36), (74, 0, -36), (75, 0, -39), (75, 0, -43), (75, 0, -53), (75, 0, -57), (75, 0, -61), (72, 0, -52), (68, 0, -52), (64, 0, -52), (60, 0, -52), (56, 0, -52), (52, 0, -52), (49, 0, -51), (49, 0, -47), (49, 0, -43), (49, 0, -39), (53, 0, -24), (57, 0, -24), (61, 0, -24), (65, 0, -24), (69, 0, -24), (73, 0, -24), (77, 0, -24), (81, 0, -24), (85, 0, -24), (86, 0, -27), (86, 0, -31), (86, 0, -35), (86, 0, -39), (86, 0, -43), (86, 0, -47), (86, 0, -51), (86, 0, -55), (86, 0, -59), (86, 0, -63), (86, 0, -67), (86, 0, -71), (86, 0, -75), (75, 0, -65), (75, 0, -69), (75, 0, -73), (75, 0, -77), (-1, 0, -2), (-1, 0, -6), (-1, 0, -10), (-1, 0, -14), (57, 0, 27), (54, 0, 95)]
[X: (0.0, 0.0, 1.0), Y: (0.0, 1.0, 0.0), Z: (-1.0, 0.0, 0.0), O: (-4.25, 1.0, -5.25)]
--------------------------
cell_pos: (-9, 1, -11)
tile_under: -1

What I still don’t get is why the cell_pos has a y-offset of 1 and even if I adjust it with

local_point.origin.y = 0

I still get a tile_under = -1

And here the solution: the trick is to subtract half the GridMap cell size from the local_point.

func _on_body_shape_entered(body_rid: RID, body: Node3D, body_shape_index: int, local_shape_index: int) -> void:
	if body is GridMap:
		var local_point = PhysicsServer3D.body_get_shape_transform(body_rid, local_shape_index)
		var new_point = local_point.origin - Vector3(0.25, 0.5, 0.25)
		var cell_pos = body.local_to_map(new_point)
		
		var tile_under = body.get_cell_item(cell_pos)
		
		var child = GameManager.meshLibBarrier.get_node(body.mesh_library.get_item_name(tile_under))
		if child:
			if child.is_in_group("barrier"):
				print("barrier")
				self.queue_free()