calling queue_free on large group of enemies closes game

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By blueStag
var enemies = get_tree().get_nodes_in_group("enemy")
for e in enemies:

This causes the game to close (crashes?) the next frame when I run the project in debug mode, but only if there are a lot of enemies, about 100 or more. Less enemies than that, and it works fine.

I do not get any error messages when the game closes.

I have made sure there are no other nodes that have a reference to any of the enemies.

What is causing the game to close, or how could I figure it out? Thanks for the help.

Hmmm… Are you positive that the enemy group contains only the nodes you expect - in every case? I wonder if logging each node name prior to freeing it might provide some useful information?

jgodfrey | 2023-01-31 22:33

I had considered this.
I put the code:

		if not e is Enemy:
	        push_error("not an enemy")

inside the loop, and the error never is triggered.
I also check the enemies array in debug mode, and they are all enemies.

blueStag | 2023-01-31 22:50

thank you so much for this informative answer, jgodfrey! you are a savior to all coders here! :slight_smile:

anonymous | 2023-01-31 23:17

Here’s another post that sound similar, that also mentions a workaround.

However, if such a workaround is necessary, it feels like a bug…

You could take a look at currently logged bugs related to queue_free to see if anything sounds similar. Here’s a start for that:

Issues · godotengine/godot · GitHub

jgodfrey | 2023-01-31 23:23

I managed to fix the issue similar to the poster in
Instead of calling queue_free, I added each enemy to an array which gets 10 elements queue_freed every frame.

While this workaround fixes the issue, it still does not explain why queue_freeing too many elements crashes the game.

edit: I was wrong. This only fixes the issue if I have a breakpoint in my code?!

blueStag | 2023-02-02 16:06

:bust_in_silhouette: Reply From: Gluon

Perhaps it is causing some kind of conflict with another process trying to run at the same time have you tried forcing it to wait until idle?

var enemies = get_tree().get_nodes_in_group("enemy")
    for e in enemies:

Thanks, but that did not fix the issue. I believe the issue is that game is trying to queue_free() to many enemies in one frame

blueStag | 2023-02-02 16:03

Okay another options might be to move the character off screen, then have a timer with a random time associated with it which links to a function which queue free’s the enemy. Technically if you were unlucky the random timer could choose the same time too many times but at least it might be a workaround. Something like

var enemies = get_tree().get_nodes_in_group("enemy")
    for e in enemies:
        e.global_position.y = e.global_position.y + 100000
        var timer =
	    timer.autostart = true
	    timer.one_shot = true
	    timer.wait_time = rand_range(1.0, 20.5)
	    timer.connect("timeout", e, "Despawn")

then just have a despawn function in each enemy with a self.queue_free() in it

Its not an elegant solution but could be a brute force alternative for you.

Gluon | 2023-02-02 17:31