Auto-Updating CollisionPolygon2D

Description

It's not uncommon to create Polygon2D objects intended for collision detection with a CollisionObject2D, such as an Area2D or PhysicsBody2D, where we want the collider to be a CollisionPolygon2D that uses the same polygon shape as the Polygon2D we have drawn. This can be easily done in code using something like

my_collision_polygon.polygon = my_polygon2D.polygon

since both the Polygon2D and CollisionPolygon2D store their polygons as a PackedVector2Array of vertices.

If you want the collision shape to follow the polygon automatically, as you create the polygon in the editor, you can do that by making a script inherit from CollisionPolygon2D with the @tool decoration (or [Tool] attribute if using C#).

Setting a class_name also lets you easily select this type when adding a new node in the editor. (In C# you would want to use the [GlobalClass] attribute instead.)

The following is a bit rough just to get the point across, so you'll want to adjust to your needs. (It's safer to obtain a reference to the Polygon2D object via some other approach, such as an @export variable, rather than calling get_parent twice. It would also be cleaner to place code having the same effect in the Polygon2D object instead, since then that object is managing its children rather than the other way around.)

You can set interval to whatever time delay you want before the polygon updates.

Notice the line if not Engine.is_editor_hint(): return ensures that the polygon shape is only updated while in the editor. This is important, since (for example) since it likely wastes processor cycles and changing the polygon while running the game will cause events to re-trigger, which is undesirable. (So, for example, if you are listening to the Area2D's mouse_entered and mouse_exited signals, these would go off every half-second when the polygon is reset.) If you do want additional _process code to run in-game, then this should be adjusted accordingly. If you intend the Polygon2D object's vertices to change in-game through code, then it is probably better to just assign the polygon when that happens, rather than use continuous polling in the _process method.

    Main code

    @tool
    class_name AutoUpdateCollisionPolygon2D
    extends CollisionPolygon2D
    
    var interval : float = .5
    var timer : float = 0. 
    var following : Polygon2D
    
    func _ready():
    	var area = get_parent()
    	if area:
    		var grandparent = area.get_parent()
    		if grandparent:
    			following = grandparent
    
    func _process(delta):
    	if not following: return
    	if not Engine.is_editor_hint(): return
    	
    	timer += delta
    	if timer > interval:
    		timer = 0.
    		self.polygon = following.polygon	
    

    Comments