I’m trying to set up an Area2D as a child of a character, made to detect whether or not it collides with any CollisionPolygon2D in the tree. Terrain’s CollisionPolygon2D need to be dynamic in-game, as part of the game will be adding to and removing from polygon2D at runtime. The scene tree looks like this:
┖╴Main
┠╴Character
┃ ┠╴Sprite2D
┃ ┠╴CollisionShape2D
┃ ┖╴testArea2D # ← area we’re testing has_colliding_bodies with
┃ ┠╴CollisionShape2D
┠╴TerrainStaticBody2D
┃ ┠╴TerrainPolygon2D # ← generates CollisionPolygon2D sibling based on itself in script
If I run has_overlapping_bodies() from Character’s script to see if testArea2D has any overlapping bodies, it will always return false. However, if I manually add a CollisionPolygon2D for TerrainPolygon2D (not generating it through code), it returns true during overlaps as expected.
If I debug and run print_tree_pretty(), it shows ┖╴@CollisionPolygon2D@11 as a child of TerrainStaticBody2D as expected, but overlaps will not show. Why are these different? Is there something I need to do in code to make it so has_overlapping_bodies() can see CollisionPolygons generated by script?
(Relevant code for generating/adding the CollisionPolygon2D)
Area2D.has_overlapping_bodies() is only updated once per physics step. If you add the CollisionPolygon2D after it won’t be detected until the next physics step.
Also, the code you posted adding/generating the CollisionPolygon2D does not have any polygon. Make sure you are giving it a polygon
This is some debug code I’m running in Main’s _process(_delta). It sticks a small Area2D (with a small collision polygon child) to the mouse’s position every frame, and lets me test if the terrain overlaps any bodies. As mentioned before, it’ll never read ‘true’ if I’ve got the collisionPolygons generated through a script in the terrainPolygon’s ready() function, but will read ‘true’ as expected if I manually create the collisionPolygons in the editor, and I don’t understand why they’re different.
Three things I would check.
Turn on visible collision shapes and see if you have a polygon (make sure your points are legit)
Next double check that you are adding the CollisionShape2D as a child of a collidable body (it is being added to where it should be)
Finally check the REMOTE tab and click on your dynamically added CollisionShape2D then look at the polygon points in the inspector to make sure they are valid.
Remember that polygon points are Vector2 points so the array must look something like this:
var pva:PackedVector2Array = [
Vector2(200,10),Vector2(400,10),Vector2(400,200), Vector2(200,200)
]
This is basically exactly my setup. Thanks for putting this together, I’ll pore over this and see what I did wrong!
Update - can’t figure it out still. Ran the exact same test as above and got the same results (it works). Dunno what I screwed up in my actual project, but I’ll dig it out.
Update2 - Found it! I was calling the collisionPolygon2D’s polygon to update outside of a physics frame, which apparently made it invisible to has_overlapping_areas(). I’m not smart enough to understand WHY that is, but making sure it updates the polygon’s vectors during a physics frame process (either during _physics_process or via await get_tree().physics_frame ) solves the issue and makes it work as expected.