Trying to understand the operation of reload_current_scene()

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By denxi

I had a problem that I have figured out a workaround for, however I’m curious as to what the mechanics behind it actually were, so I can better understand how to avoid it in the future. The problem was get_tree().reload_current_scene() causing other errors in my scene change set-up.

I’ve pulled the code for scene changes right out of the manual here: Singletons (AutoLoad) — Godot Engine (3.0) documentation in English

var current_scene = null

func _ready():
    var root = get_tree().get_root()
    current_scene = root.get_child(root.get_child_count() -1)

func goto_scene(path):
    call_deferred("_deferred_goto_scene", path)

func _deferred_goto_scene(path):
    # Free Current Scene
    current_scene.free()

# Load new scene.
    var s = ResourceLoader.load(path)

# Instance the new scene.
    current_scene = s.instance()

# Add it to the active scene, as child of root.
    get_tree().get_root().add_child(current_scene)

# Optional, to make it compatible with the SceneTree.change_scene() API.
    get_tree().set_current_scene(current_scene)

The problem I’m having is that when I use get_tree().reload_current_scene() is that it seems to wipe what my current_scene variable is. I was under the impression that reloading my current scene wouldn’t include any singletons, but I don’t have any other explanation for what’s happening. If someone could give me a heads up as to what I’m missing in the process, I’d appreciate it.

BTW the workaround I’m using is just

goto_scene(current_scene.filename)
:bust_in_silhouette: Reply From: Dlean Jeans

Directly from the source code:

Error SceneTree::reload_current_scene() {

	ERR_FAIL_COND_V(!current_scene, ERR_UNCONFIGURED);
	String fname = current_scene->get_filename();
	return change_scene(fname);
}

Error SceneTree::change_scene(const String &p_path) {

	Ref<PackedScene> new_scene = ResourceLoader::load(p_path);
	if (new_scene.is_null())
		return ERR_CANT_OPEN;

	return change_scene_to(new_scene);
}

Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) {

	Node *new_scene = NULL;
	if (p_scene.is_valid()) {
		new_scene = p_scene->instance();
		ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE);
	}

	call_deferred("_change_scene", new_scene);
	return OK;
}

void SceneTree::_change_scene(Node *p_to) {

	if (current_scene) {
		memdelete(current_scene);
		current_scene = NULL;
	}

	if (p_to) {
		current_scene = p_to;
		root->add_child(p_to);
	}
}

In GDScript-ish:

func reload_current_scene() -> Error:

    if not current_scene:
        printerr(ERR_UNCONFIGURED)
    var fname:String = current_scene.get_filename()
    return change_scene(fname)

func change_scene(p_path:String) -> Error:

    var new_scene:PackedScene = load(p_path)
    if not new_scene:
        return ERR_CANT_OPEN

    return change_scene_to(new_scene)

func change_scene_to(p_scene:PackedScene) -> Error:

    var new_scene:Node
    if p_scene.is_valid():
        new_scene = p_scene.instance()
        if not new_scene:
            printerr(ERR_CANT_CREATE)

        call_deferred("_change_scene", new_scene)
        return OK

func _change_scene():

    if (current_scene):
        current_scene.free()
        current_scene = NULL

    if (p_to):
        current_scene = p_to
        root.add_child(p_to)