Error: Can´t change this state while flushing queries

Godot Version

4.2.2

Hello,

I have the code below and I encounter this error:

E 0:00:03:0877 game_level.gd:82 @ _on_spawn_area_area_entered(): Can’t change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.
<C++ Error> Condition “area->get_space() && flushing_queries” is true.
<C++ Source> servers/physics_2d/godot_physics_server_2d.cpp:355 @ area_set_shape_disabled()
game_level.gd:82 @ _on_spawn_area_area_entered()

As far as I understand this comes from the area overlap causing some physics calculation going on. And the trigger seems to be in my case the add child line which is being executed within the function of a signal.

I tried to use “call_deferred(“add_child”, enemy)” instead but this results in a delay of more than a second. The game isn´t bloat up whatsoever. There are no bigger physics interactions going on. I don´t have negative side effects.

How can I solve this error notification anyways? I would like to understand.

Best regards!

func _on_spawn_area_area_entered(_area):
	print("spawn area detected")
	if $TimerSpawn.time_left == 0.0:
		$TimerSpawn.start()
		var picked_indices = []
		var random_num = randi_range(1, 2)  # Choose randomly if one or two or three markers to be chosen
		#create probability for third enemy object (asteroid) that needs to be #destroyed with swipe up
		if random_num ==2:
			var random_num_asteroid = randi_range(1,3)
			if random_num_asteroid == 1:
				random_num =3
		while picked_indices.size() < random_num:
			var random_index = randi_range(0, markers.size() - 1)
			if random_index not in picked_indices:
				picked_indices.append(random_index)
				
		var picked_markers = []
		for index in picked_indices:
			picked_markers.append(markers[index])
		for spawn_position in picked_markers:
			var selected_spawn_object = spawn_objects.pick_random()
			var enemy = selected_spawn_object.instantiate() as Area2D
			add_child(enemy)
			enemy.position = spawn_position.position

call_deferred shoudn’t had a big delay like that because will just wait the next idle frame, but if for some reason is taking too long to work your alternative is pool the enemies (let a certain amount of enemies already added but in a disabled state somewhere where player can’t see) so instead of instanciate a new enemy you’ll just reposition him and active the enemy (make visible, turn on code that move him, etc).

If you do that you also need to check the size of the pool to make sure always has enemies to use, so when the pool reach a certain amount you need to refill the pool (using call_deferred, but in this case the enemy will not appear directly to player so its fine if has a delay to add)

1 Like

Hi ,

I had the same problem, mine is spawning collectibles randomly,

here’s the solution I got, you need to separate the function for add_child

func _on_spawn_area_area_entered(_area):
for spawn_position in picked_markers:
call_deferred(“_spawn”) ### ← you need to put the function name as string

func _spawn():
var selected_spawn_object = spawn_objects.pick_random()
var enemy = selected_spawn_object.instantiate() as Area2D
add_child(enemy)

1 Like