CollisionPolygon2D not working when animated by code

Godot Version

3.5

Question

I want to draw and animate a polygon and then detect Area2D interactions with it.
If I build my CollisionPolygon2D on _ready everything seems to work properly. Then I wanted to animate it so I am recomputing the points in the polygon of the CollisionPolygon2D during _process. When I do that, if I enable “Debug/Visible collision shapes”, I can see the Area2D properly updated but _on_Area2D_area_shape_entered is not triggering.

I have setup a scene with a couple Area2D nodes one of which follows the mouse and reports collisions. Then I added a couple Area2D that I create on _ready, for now using just a circle with the code below:

extends Area2D

var npoints = 32
var nradius = 160

func _ready():
	var points = PoolVector2Array()
	for i in range(npoints):
		var coords = Vector2(cos(2.0*PI*i/npoints)*nradius, sin(2.0*PI*i/npoints)*nradius)
		points.push_back(coords)
	
	var polygon = CollisionPolygon2D.new()
	polygon.build_mode =CollisionPolygon2D.BUILD_SEGMENTS
	polygon.polygon = points
	polygon.one_way_collision_margin = 2
	call_deferred("add_child", polygon)
	
	var line = Line2D.new()
	line.width = 20
	call_deferred("add_child", line)
	var coords = Vector2(cos(0)*nradius, sin(0)*nradius)
	points.push_back(coords)
	line.points = points
	line.begin_cap_mode = Line2D.LINE_CAP_BOX

This works. Then I created another one that I try to animate with the code below:

extends Area2D

var npoints = 32
var nradius = 160
var nradius_change = 30
var points = []

var polygon: CollisionPolygon2D
var circle: Line2D


func update_shapes():
	var new_points = Array()
	for point in points:
		new_points.append(point*nradius)
	polygon.polygon = PoolVector2Array(new_points)
	new_points.append(new_points[0])
	circle.points = PoolVector2Array(new_points)
	

func _ready():
	for i in range(npoints):
		points.append(Vector2(cos(2.0*PI*i/npoints), sin(2.0*PI*i/npoints)))
	circle = Line2D.new()
	polygon = CollisionPolygon2D.new()
	update_shapes()	
	polygon.build_mode =CollisionPolygon2D.BUILD_SEGMENTS
	polygon.one_way_collision_margin = 2
	polygon.polygon = PoolVector2Array()
	#polygon.polygon.resize(npoints)
	#polygon.polygon.fill(Vector2.ZERO)
	call_deferred("add_child", polygon)
	
	circle.points = PoolVector2Array()
	#circle.points.resize(npoints+1)
	#circle.points.fill(Vector2.ZERO)
	circle.width = 20
	circle.begin_cap_mode = Line2D.LINE_CAP_BOX
	call_deferred("add_child", circle)
	
func _process(delta):
	nradius += nradius_change * delta
	if nradius>250:
		nradius_change *= -1
	elif nradius<150:
		nradius_change *= -1
	update_shapes()
	

Reading around I tried:

  • Adding set_physics_process(true) to _ready
  • Adding .set_physics_process(true) to _ready
  • Calling update_shapes() in _physics_process

What am I missing? I recorded the screen here:

output

p.s.
I was trying to use a single PoolVector2Array, initialize it once (using resize and fill), and then just update the points in it as needed. That didn’t seem to work. I am not sure how to work with PoolVector2Array. The documentation has some notes about how it is passed by value and not mutated, does that mean I need to recreate it every time like I’m doing already?

In case someone lands in this page with a similar issue, this was resolved by moving the code from _process to _physics_process .

Credit to reddit user MarcusMakesGames

https://www.reddit.com/r/godot/comments/1c6c1md/how_to_get_help_when_you_get_no_responses/#lightbox