"Cannot call method 'is_in_group' on a previously freed instance." Issue

Godot Version

Godot 4.4

Question

Hello hello!! I have ran into a recent issue with my game that pertains to the handling of area3Ds; I have code within my PLAYER controller that detects whenever it enters an area3D, however, I have hit an error when the code attempts to check what kind of GROUP the area3D is in.

Some ENEMIES spit out an area3D as a projectile, this projectile is in a certain GROUP specific to enemy projectiles. When the projectile intersects with the PLAYER it does damage, and then runs the “queue_free()” command. However, after a few seconds, the game crashes and presents the “Cannot call method ‘is_in_group’ on a previously freed instance.” error.

This is because it is also trying to check if the projectile is part of another group, one for another entity, but cannot since it is queue_free()'d.

Is there a way to make it STOP checking which group the area is in if it is queue_free()'d?

I believe you can use is_instance_valid as a guard.

However I’m not entirely sure what you’re doing. Using is_instance_valid as a guard may stop the game crashing, but is potentially just working around some deeper design problem.

2 Likes

The overall design for the enemy projectiles might be flawed. Every projectile is a raycast that moves an Area3D in a set direction, and when it collides with something, whether it be the player or a wall/floor, it is supposed to do damage and delete itself.

I have not been able to find a better method for projectiles, so I have settled with this method for now.

If your projectiles are all the same, instead of a node group, how about adding a class_name Projectile to the projectiles? Then, you can do if object is Projectile instead of checking is_in_group. I don’t know if it fits in your problem, but it’s worth a try!
A fix for your current setup, like what @gentlemanhal said, is to use is_instance_valid to check for the instance of the projectile. Also, disconnect the projectile before running queue_free.

3 Likes

Hmmmmm, that sounds interesting! Apologies for asking, but how would I go about achieving something like that? I am a beginner with GDscript so I have no idea where to start.

1 Like

Thank you! This is very useful! If you also don’t mind me asking, how might I check if the projectile is in a specific class_name? I tried “if area is ENEMY_PROJECTILE” but that doesn’t seem right.

That area should be connected to a script that has class_name ENEMY_PROJECTILE under the extends line.

3 Likes

The is keyword is correct :+1:

Example from the docs:

# Cache the enemy class.
const Enemy = preload("enemy.gd")

# [...]

# Use 'is' to check inheritance.
if entity is Enemy:
	entity.apply_damage()

FYI (and kinda off topic), you can use whatever naming convention you like, but the built in classes all use PascalCase (aka CamelCase). See GDScript style guide for other naming conventions.

3 Likes

This one did the trick! I attached a script to the area of the projectile that puts it in the ENEMY_PROJECTILE class and that fixed the issue entirely! Thank you tons!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.