0 votes

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 gettree().reloadcurrent_scene() causing other errors in my scene change set-up.

I've pulled the code for scene changes right out of the manual here: http://docs.godotengine.org/en/3.0/getting_started/step_by_step/singletons_autoload.html

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 gettree().reloadcurrentscene() is that it seems to wipe what my currentscene 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)
asked Feb 7, 2019 in Engine by denxi (403 points)

1 Answer

0 votes

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)
answered Feb 7, 2019 by Dlean Jeans (3,891 points)
edited Feb 7, 2019 by Dlean Jeans
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.