Clueless on strange issues when making placeable areas for objects

Godot Version

4.6.1

Question

I currently have a system where a player can place a 3D item and pick it back up again. This has worked fine, so I decided to try to implement a system where the player can only place items where there is enough room. As such I created an Area3D with a collision box. This Area3D goes to where the player is about to place their item and checks if itself is colliding with anything, if it is, it aborts the placing of the item. This seemed simple enough to code in, but I have struggled to actually make it work.

There are so many weird issues with it sometimes working and other times not, the player being able to place an item ON THE AREA3D! I have explored collision masks/layers, but I’ve found them to behave odd as well, if I were to change the Area3D’s layer/mask where it can no longer be placed on, the Area3D will also no longer function as it won’t collide with other objects. I’ve also tried switching “monitoring” or “monitorable” on/off both in the editor and in the code and this doesn’t seem to help either.

The code for my player placing down an item is as follows:

func putdown():

	if raycast.is_colliding():
		raycastcollisionpoint = raycast.get_collision_point()
		currentplayerrotation = $Pivot/Camera3D.global_rotation
		$Area3D.global_position = raycastcollisionpoint
		$Area3D.global_position.y = raycastcollisionpoint.y + 1.1
		if $Area3D.has_overlapping_bodies():
			return
		elif $Area3D.has_overlapping_areas():
			return
		else:
			emit_signal("sendraycastcollision",raycastcollisionpoint,currentplayerrotation)

The code for my raycast that check the position of where the player wants to place an item:

func pickup():
# if not colliding, go back
	if !raycast.is_colliding():
		return

	print ("raycast hit something")

	print(str(raycast.get_collider()))
# get what raycast is hitting, otherwise nothing spefic can happen
	var obj = raycast.get_collider()
# if object is collidable but is NOT in group "items", its not an item, ignore
	if !obj.is_in_group("items"):
		print (str(obj) + " is not an item")
		return
	print ("this is an item")
# if object is collidable AND in group "items" but does NOT have a "func picked_up():" code, ignore (failsafe)
	if !obj.has_method("picked_up"):
		print ("can't pick this up as no function to pick up!")
		return
	print(obj.name)
# call "func picked_up():" on the object
	obj.picked_up()
	print (str(obj) + " is an item")

I’ve also linked a video which shows the problem in MUCH greater detail here:

The area doesn’t update it’s overlapping bodies/areas until the next frame, are you storing the cylinder in an area with other bodies/areas it could be overlapping?

You could try to use direct physics queries instead for instant results, you could follow along this tutorial but use intersect_shape instead of intersect_ray

By “storing” are you referring to the node tree? The Area3D I have is a child of the player’s character, whose root node is a CharacterBody3D

Storing meaning I don’t know what you do with the Area3D when it’s not raycasting, what is it’s position before putdown() is called? Eitherway the overlaps do not update immediately, so you will have to account for that, probably best by using direct physics queries as mentioned