Unexplicable Area2D collision detection problems

Godot 4.3

essentially these areas with the same collision layers and masks, with children shapes that overlap, both monitoring and monitorable do not show up in each other’s overlapping_areas array (or cause an area_entered signal because of each other) at all and i have no clue of how to debug that because it looks like i did everything right(?)

a video of the problem, note that the array in the log is hitbox.get_overlapping_areas():

in the _physics_process of the attack area2d:

func _physics_process(_delta):
    var fern = get_tree().current_scene.get_node("player1/hitbox")
    print("here"+str(overlaps_area(fern)))
    print(fern.collision_layer)
    print(collision_mask)
    var s2 = get_tree().current_scene.get_node("player1/hitbox").get_child(0).shape
    var s1 = get_child(0).shape
    print(s1.collide(get_child(0).global_transform,s2,get_tree().current_scene.get_node("player1/hitbox").global_transform))
    if Time.get_ticks_msec()>spawntime+duration*1000:
        queue_free()
    return

the output of the print calls when the shapes overlap visibly (visible collision shapes):
herefalse
4
4
true

one possibility i considered is the engine using the area2d’s transform instead of that of the collisionshape2d, but accounting for that changed nothing (though it would be really helpful is someone could tell me which transform is used, because a system in my game heavily relies on the shape’s transform being used).

it would be really helpful is someone could tell me which transform is used, because a system in my game heavily relies on the shape’s transform being used

A global transform is just the node’s current transform plus the transforms of all parents until the highest reachable node in the tree (owner, I think). So say you have an Area2D and a CollisionShape2D childed to it. If the (local) position of the CollisionShape2D is Vector2(0,0) then its global_position is equal to the global_position of the Area3D. Same goes for transforms, which are just containers for position, rotation, scale and stretch data. So yes, an Area2D and its childed CollisionShape2D will have distinct transform data, and calling one shouldn’t return the other.

That said, don’t recommend relying on attributes of CollisionShape2Ds in calculations as they’re essentially just an attribute of whatever they’re childed to. If you need a collision box to rotate around a point in space I’d child the Area3D (or what have you) to a basic Node3D and rotate that. But that’s just an idea

Anyway judging by

var s2 = get_tree().current_scene.get_node("player1/hitbox").get_child(0).shape
var s1 = get_child(0).shape
print(s1.collide(get_child(0).global_transform,s2,get_tree().current_scene.get_node("player1/hitbox").global_transform))

you’re calling collide() not on the CollisionShape2D but on its shape resource, which is this thing


, not a node (I’m surprised it’s even working) (though since I’ve only ever done 3D so I may be wrong and that’s what you’re meant to do, it just seems odd)

Wait no I do see a mistake there:

print(s1.collide(get_child(0).global_transform,s2,get_tree().current_scene.get_node("player1/hitbox").global_transform))

should be

print(s1.collide(get_child(0).global_transform,s2,get_tree().current_scene.get_node("player1/hitbox").get_child(0).global_transform))

Try that

the stuff about global transform

I know what it is, I would like to know which global transform is used, I don’t need the collisionshape2D to rotate around a point, I need there to be more than 1 in some attacks.

the line correction

You are right but the relative position of the hitbox’collisionshape2d is Vector2(0,0), so yeah changing the line didn’t have an effect.

I know what it is

ah sorry probably coulda cut that down a bit

I need there to be more than 1 in some attacks

Is that for just having gaps in the attack range/different attack locations or receiving damage from the different ones independently (like if two of them hit it’d do double damage)? Because for the latter you’d need separate Area3D nodes

The first print returning false is concerning, can you explain that

Is that for just having gaps in the attack range/different attack locations

Yeah, each hitbox being included in the same immunity state is intended.
About the is_overlapping check returning false, yeah, that’s what I am having a problem with, I haven’t been able to explain it in the past two days…

maybe

for area in get_overlapping_areas():
    if area == fern: print("direct match")
    if area.name == fern.name: print("names match")

I don’t understand what you mean by that post, the areas do not overlap

I figured out what the problem was, this is the final _physics_process of the collisionshape2d:

func _process(_delta):
	var lived = Time.get_ticks_msec()-batch.spawntime
	position = (starting_position+transform_function.call(lived))*Vector2(batch.get_parent().horidir,1)		#FIXME AI/PLAYER ABSTRACTION
	#NOTE assigning the shape each frame breaks collisions because of in-engine delays
	var newkey = Fighter.sort_keyframe_array(hitboxes,lived)
	if currkey != newkey:
		shape = newkey.meta.call()
	return

Earlier I was doing shape = Fighter.sort_keyframe_array(hitboxes.lived).meta.call() every frame, apparently there are in-engine delays for the shape of a collisionshape2d registering with the physics server (in the shape2d object, not the collisionshape2d object), it would be nice if this sort of behavior was documented, a note in CollisionShape2D — Godot Engine (stable) documentation in English would have gone a long way for me.