What does the "Can't change this state while flushing queries" error mean?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Diet Estus

I am working in Godot 3.1 alpha 4, downloaded from here.

I have a breakable box which spawns a coin when the player attacks it.

The breakable box is an Area2D and the coin is a KinematicBody2D. When my player attacks, he generates an attack box which is also an Area2D. This attack box calls a destroy() method on the breakable box during emission of its on_area_entered signal. The destroy() method in turn calls a function from a singleton which spawns a coin.

func create_coin(pos, vec, speed):
	var projectile = coin_scene.instance()
	get_node("Level").add_child(projectile)
	projectile.init(pos, vec, speed)
	return projectile

Everything seems to work fine in-game, but I see the following errors generated whenever a coin is spawned.

The traces indicate that the problem is rooted in the create_coin() method.

These errors were not present in Godot 3.0.6, before I ported over to Godot 3.1 alpha 4.

What do these errors mean and how can I avoid them?


Here are some of the C Sources and Stack Traces, in case they help.



:bust_in_silhouette: Reply From: uzimonkey

You’re trying to call this function in a notification generated by flush_queries. It appears that flush_queries is finding all the overlaps and pushing out notifications based on those, but it’s setting a variable flushing_queries to true while it’s doing that. Any other function that adds, removes, enables or disables collision data is disabled via the FLUSH_QUERY_CHECK macro at the beginning of those functions.

The short of it is it appears you can’t do that from a collision notification. It’s advising you to use call_deferred which will defer the physics-modifying code that’s causing the problem to the idle time.

Thanks for the answer! You seem to be correct. You cannot add new Area2Ds to a scene during a call of another Area2Ds on_area_entered(). Using call_deferred() solves the problem. It’s interesting that you don’t get these errors in Godot 3.0.6.

Diet Estus | 2018-12-31 23:01

I know I’m a little late for this, but can you explain a little more detailed about the call_deffered()? I tried using it instead of add_child()but then when I try to use the new “new child” tween node, it says that start: Tween was not added to the SceneTree!. What should I do?

`

MicasiO | 2020-05-12 14:11

MicasiO it means you are trying to start() a tween while it’s not in the tree yet. call_deferred executes a function later, not immediately. So if you want to call start after calling add_child in a deferred way, you must also call start using call_deferred. Alternatively, you can create a custom function doing these things and use call_deferred once on that function instead.

If you still have issues I suggest you create a new question because that’s unrelated to flushing queries.

Zylann | 2020-05-12 14:15