Proper instance deletion

Godot Version

v4.3.stable.official [77dcf97d8]

Question

Hello! My friend and I are relatively new to game development and are having trouble understanding the proper way to remove instances from memory.

To give some context, we’re trying to make a pachinko/ball dropper idle game, where the player will be able to drop many balls at once consistently.

The “Spawn Ball” button click handler calls the following function, both in main.gd (which will likely need to be moved in the future):

var ball = preload("res://Scenes/Pachinko/ball.tscn")

func spawnBall () -> void:
	var instance = ball.instantiate()
	# set ball's position
	add_child(instance)

Once that ball enters a score zone, it should be despawned using the following function in score_zone.gd:

func _on_area_2d_body_entered(body: Node2D) -> void:
	# add score
	body.queue_free()

To solve the problem of a ball getting stuck balancing on the top of a peg, we do this in ball.gd:

@onready var rigid_body_2d: RigidBody2D = $RigidBody2D

func _process(delta: float) -> void:
	if is_instance_valid(rigid_body_2d):
		# adjust ball's velocity if it's 0
	else:
		print("invalid")

This is where the problem arises. Once the queue_free() is called on the ball, the body becomes invalid, as we expect. However, this script instance continues running and checking its validity each frame (as we can tell by the print()). Such is the case for every spawned ball. For only a few balls, this isn’t a problem, but as time goes on and more balls are spawned, the memory leak grows.

Shouldn’t the ball.gd script instance associated with a ball instance terminate once queue_free() is called on its corresponding ball? Is there something we’re missing to properly terminate this?

Any help/advice would be greatly appreciated. Thanks!

The body retrieved from the body_entered signal is your RigidBody2D, not the Ball parent node. So you are freeing only the child RigidBody2D, while the Ball Node is still there.
You’d need to free the parent:
body.get_parent().queue_free()
Or you change your scene structure so that the Ball’s root node is RigidBody2D (which would be my preferred way). You can then access its velocity etc. directly without referencing any child Nodes.

1 Like