CollisionShape2D.disabled = true not working as expected

Godot Version

4.4

Question

Hey y’all!
I am currently working on creating an asteroid for my space game and ran into a weird bug when setting CollisionShape2D.disabled = true. I want to be able to shoot the asteroid and while the death animation is playing fly through it, when I set CollisionShape2D.disabled = true in _ready or _process it works fine and I can fly though, when it is set via the player_bullet (second code snippet) the animation plays but the collision remains solid.
I printed out the CollisionShape disabled variable in process and it does change when shot but I still can’t fly through even when it says disabled is true. I also commented out the play death animation and it just sits there still colliding when shot. I also turned on view collision shape in the debug menu and both the original approach and set_deferred both disable the collision shape visually.
I googled it and found the $CollisionShape2D.set_deferred(“disabled”, true) which did work as intended but does anyone know why the other way does not? It seemed more intuitive to me.

Lastly, I found this archived post from 2021 while writing this post about this exact problem, still not resolved so I’m putting this back out there.

extends StaticBody2D

const SPEED = 300.0

func play_death() -> void:
	$AnimatedSprite2D.play("death")
	$CollisionShape2D.disabled = true    # Does not work
	#$CollisionShape2D.set_deferred("disabled", true) # Works

func _on_animated_sprite_2d_animation_finished() -> void:
	if $AnimatedSprite2D.animation == "death":
		queue_free()
extends Bullet

func _on_area_2d_body_entered(body: Node2D) -> void:
	if body.is_in_group("asteroid"):
		body.play_death()

I don’t know how to explain the mechanics behind this, or even know what they are, but there problem lies within the current frame and the process and physics_process functions

The frame in which some entity enters the area, it starts doing whatever you tell it to as the area is enabled. Within that same frame, you want to tell the computer to disable the area. But it only started doing your function because the area is enabled in this same frame! Is that paradoxical…?

Anyway, I think godot has some safety bumpers built in so the engine doesn’t crash when this occurs. Which is why that during an area_enetered function, you should defer what happens to the area on the next frame ( process / physics_process )

The same thing happens if you try to create new areas during an area_entered function (exploding projectiles or something), those need to be deferred to the next frame as well.