strange, it prints 'didexplode'
but not the overlapping bodies in the area3D

That code might have to be in _physics_process() actually. So something like this:

extends Node3D
@export var area : Area3D
@export var force = 5.0
var check_bodies = false

func addexplosionforce():
	print("didexplode")
	check_bodies = true

func _physics_process(_delta):
	if not check_bodies: 
		return
	for body in area.get_overlapping_bodies():
		if body is RigidDynamicBody3D:
			print(body.name)
			var direction_vector = body.global_transform.origin - area.global_transform.origin
			var distance = direction_vector.length()
			var collision_force = (force / distance) * body.mass
			body.apply_impulse(Vector3.ZERO, direction_vector.normalized() * collision_force)
	check_bodies = false

func _on_visible_on_screen_notifier_3d_screen_exited():
	self.queue_free()

same result, might be an issue with my layer and mask settings
cause it prints 'didexplode' and 'should explode'

extends Node3D
@export var area : Area3D
@export var force = 5.0
var check_bodies = false

func addexplosionforce():
	print("didexplode")
	check_bodies = true

func _physics_process(_delta):
	if not check_bodies: 
		return
	print("should explode")
	for body in area.get_overlapping_bodies():
		if body is RigidDynamicBody3D:
			print(body.name)
			var direction_vector = body.global_transform.origin - area.global_transform.origin
			var distance = direction_vector.length()
			var collision_force = (force / distance) * body.mass
			body.apply_impulse(Vector3.ZERO, direction_vector.normalized() * collision_force)
	check_bodies = false
func _on_visible_on_screen_notifier_3d_screen_exited():
	self.queue_free()

Yeah, I would double check the layers most likely.

ive checked my masks
every rigid bodie is on layer 4

what am i doing wrong?

anyone got an idea what issue is causing it not detecting the bodies?

The arguments to apply_impulse are in the wrong order,
but that shouldn't be stopping them from being detected at all.

It seems to be working for me. Either something is off with the layers (check both the area and the rigid bodies) or maybe you are not re-enabling the area properly. I used process_mode and that seems to work good.

extends Node2D

@export var area : Area3D
var touch = 0

func _ready():
	area.process_mode = Node.PROCESS_MODE_DISABLED

func _physics_process(_delta):
	for body in area.get_overlapping_bodies():
		if body.name == "Cube":
			touch += 1
			print("Touched the Cube ", touch)

func _input(event):
	if event.is_action_pressed("start"):
		area.process_mode = Node.PROCESS_MODE_ALWAYS

so it now prints out the bodies, my layers where correct.
i dont understand i need to put the code in physics process, and cant just call it from a func.
however the apply impulse code is wrong, just like @spacecloud said, what should go there?

extends Node3D
@export var area : Area3D
@export var force = 5.0
const EXPLOSION_TIME = 0.5
var explosion_timer = 0.0
var exploded = false
func _ready():
	set_physics_process(false)
	
func addexplosionforce():
	set_physics_process(true)
	print("didexplode")
	exploded = true

func _physics_process(delta):
	if not is_instance_valid(area):
		return
	for body in area.get_overlapping_bodies():
		if body is RigidDynamicBody3D:
			print(body.name)
			var direction_vector = body.global_transform.origin - area.global_transform.origin
			var distance = direction_vector.length()
			var collision_force = (force / distance) * body.mass
			body.apply_impulse(Vector3.ZERO, direction_vector.normalized() * collision_force)
	
	if exploded:
		explosion_timer += delta
		if explosion_timer >= EXPLOSION_TIME:
			area.monitoring = false
			area.queue_free()
			
func _on_visible_on_screen_notifier_3d_screen_exited():
	self.queue_free()

Physics process is synced to the physics engine (that is why it has the name). If you call or query any aspect of the physics engine, it is not guaranteed to work unless in physics process. This is because it may be on the wrong frame (maybe before the collision has been detected) or if you try to apply a force, it may be overwritten on the next physics tick (since it didn't get fully applied at the correct time). Not sure about the impulse, I can look at it later.

The arguments are in the order (force, position), so what you want is

body.apply_impulse(direction_vector.normalized() * collision_force, Vector3.ZERO)
  • DJM replied to this.