How to delete a single instance of a scene rather than all instances

Godot Version

4.1.1

Question

I’m making the beginnings of a 2D Tower Defense game. The project is currently just a block cursor that follows the mouse and places a single tower wherever the player clicks, all snapped to a grid. I’m trying to figure out how to also be able to delete an individual tower when it’s right-clicked.

Scenes:

“weapon_01”: the placeable tower. It’s a Node2D containing an Area2D with collision, and a ColorRect and Sprite2D. Its script is currently empty.

“cursor”: basically the player scene. An Area2D with collision and a ColorRect, that follows the mouse pointer and snaps to a 64x64 grid. When a left-click is detected, it currently emits an “add_weapon_01(position)” signal. When a right-click is detected, it emits a “remove_weapon_01(position)” signal.

“world_01”: a Node2D that currently just contains the “cursor” scene. Its script preloads the “weapon_01” scene, and listens for the “add_weapon_01” and “remove_weapon_01” signals. To add a weapon to the world, which thankfully works, I’m doing this inside world_01’s signal receiver function:

	var weapon_01_instance = weapon_01.instantiate()
	add_child(weapon_01_instance)
	weapon_01_instance.position = position

My current attempt to delete a weapon, also from inside the “world_01” scene (and it fails) is this:

	weapon_01.queue_free()

…which returns an error: “Invalid call. Nonexistent function ‘queue_free’ in base ‘PackedScene’.” I didn’t really expect this to work as intended anyway, because it doesn’t specify which instance to delete.

In my original attempt to delete a weapon, I ran the following in the “weapon_01” script (not in the “world_01” script as the current attempt does):

	if Input.is_action_just_pressed("right-click") and get_node("weapon01Area2D").mouse_entered:
		print("right-clicked inside weapon01's Area2D")
		queue_free()

…and that would indeed delete the weapon, but it deleted all instances of it, instead of just the one whose Area2D was occupied by the mouse cursor.

I’m not a very experienced programmer; Godot is my first attempt at programming since making games in BASIC on the C64 :slight_smile: I lack a lot of knowledge of the way things are structured in Godot, so I’m assuming I have things set up in a way that won’t allow me to do what I want here. Any idea what I need to do to allow me to delete just the right-clicked instance of my scene?

Thanks in advance for any light you can shed!

-Mark

You should do weapon_01_instance.queue_free()

1 Like

Thanks for the quick reply. I just tried it, and since it’s in a different function than the one that created the variable “weapon_01_instance”, I get an error saying that it’s not declared in the current scope. I tried changing the way I set the variable by doing:

**export** var weapon_01_instance = weapon_01.instantiate()

to see if that would make it available to the “remove weapon” function, but it looks like “export var” doesn’t do what it did in a previous version of Godot I’d played with.

I guess you are trying to use queue_free in a place where the weapon_01_instance was not declared. You must pay attention where the object was created. If you create the variable in a method, you cannot invoke that object outside that method, for example.

1 Like

Send a signal to the script that creates the instance.

Have that script free it.