C# ChangeSceneToFile: Scene not freed?

Godot Version

Godot 4.4/Windows

Question

I have a C# script that does this:

public override void _Input(InputEvent e)
{
       if (e.IsActionPressed("ui_cancel"))
       {
                  this.GetTree().ChangeSceneToFile("res://scenes/mainmenu.tscn");
	}
}

The documentation says that ChangeSceneToFile will free the current scene, but this is not the case. _ExitTree is not called in that script unless I quit the whole game (then it is called the number of times I switched between scenes). Also when I changed scenes multiple times and I press ui_cancel, then the breakpoint hits in the _Input method the number of times i already had switched to this scene, so I suspect there are multiple instances already in parallel, listening to input events.

What am I missing here?

EDIT: i created a tiny reproducible example that shows my issue. could anyone expert have a look into it?

zipped file here: Filebin | gz69fo10zglzt9ro

in the example you immediately see that after pressing escape, the game scene is still visible in the background. but maybe iam just silly and did completely basic things wrong :frowning:

I will check this later,

In Unity, l experience similar things with ScriptableObjects, they disappear after no reference on changing scenes without calling any method. Maybe is something similar here.

Solution was to change flags to not unloading if no reference.

The SceneTree keeps track of the current_scene in its SceneTree.current_scene. You are side-stepping that when loading your adventure_game.tscn here:

extends Control

func _on_continue_game_button_pressed() -> void:
	var newScene = load("res://scenes/adventure_game.tscn")as PackedScene
	var scene = newScene.instantiate()
	get_tree().root.add_child(scene)
	get_tree().root.remove_child(self)
	self.call_deferred("free")

So:

  • Game starts with mainmenu.tscn
  • You load adventure_game.tscn manually side-stepping the SceneTree mechanism. SceneTree.current_scene is still pointing to an instance of mainmenu.tscn
  • SceneTree.change_scene_to_file() gets called:
    • It internally tries to free() the SceneTree.current_scene which is an instance of mainmenu.tscn that you manually freed before.
    • It then loads the scene in path (mainmenu.tscn) and updates SceneTree.current_scene to point to that instance.
  • Repeat

It’ll never free() the many adventure_game.tscn scenes you are manually loading.

1 Like

How did you conclude that the exit tree is not working?

image

this override not override anything.

i changed your mainmenu.gd to:

extends Control

func _on_continue_game_button_pressed() -> void:
	get_tree().change_scene_to_file("res://scenes/adventure_game.tscn")

Now everything works as expected; previously, adding lots of scenes to the tree was causing issues.

yes the override was just to set a breakpoint there.