+1 vote

I want to change scenes but remember the state of the previous scene, like in Pokemon where you enter the battle and then return to the world just as it was before you entered the battle.

I couldn't find anything in the documentation on this but it might just be that I don't know what terms to search.

I was reading this question HERE and I thought maybe I could accomplish this using a PackedScene but it seems like it might not be the best solution for the problem?

Is there a better way or will a PackedScene be best for what I'm trying to accomplish?


in Engine by (103 points)

1 Answer

+4 votes
Best answer

You can store the scene (that is, its root node) in some variable, then call remove_child on it (removing it from the tree, effectively freezing it). When you want it back, reinsert it.

Just be careful not to call any functions on the stored scene's nodes that require them to be part of the tree while it's removed

EDIT: With PackedScene, be aware that it only saves exported variables. For your problem, that's probably not what you want.

by (1,080 points)
selected by

Thanks so much for the answer. Could you maybe direct me just a bit more with my attempt. I don't think I have a super great understanding of the scene tree yet. This is what I'm trying:

# I'm using a singleton node here to store the scene
var saved_scene = null

func save_scene():
    saved_scene = get_tree().get_current_scene()

func load_scene():
    if saved_scene != null:
        var root = get_tree().get_root()
        var current_scene = get_tree().get_current_scene()
        saved_scene = null

I get an error when I try to call queuefree() on the current scene and an error when I try to call addchild on the root (very end). The error messages aren't very helpful and I'm not sure what I'm doing wrong.

The saved scene is never removed from the tree, so it can't be added again, that's why root.add_child(saved_scene) fails.
current_scene.queue_free() fails because queue_free() can only be called on a node in the tree, while current_scene is removed in the line right before.

Here's a version that should work as an AutoLoad node:

extends Node

var saved_scene

func switch_scene( temp_scene ):
    # save scene and remove it from the tree
    saved_scene = get_tree().get_current_scene()
    get_tree().get_root().remove_child( saved_scene )
    # instance and add temporary scene as current scene
    var new_scene = load(temp_scene).instance()
    get_tree().get_root().add_child( new_scene )
    get_tree().set_current_scene( new_scene )

func load_scene():
    if saved_scene != null:
        # free temporary scene
        # add saved scene back to the tree
        saved_scene = null

For this example, I renamed save_scene() to switch_scene() and pass the name of the scene file to temporarily switch to.

Also, keep in mind that _enter_tree() and _ready() are called on all the restored scene's nodes when the scene is reinserted.

I think this is closer, now it breaks on me when I try and remove the child (line 2 of the switch scene function). It is closer, though, and I appreciate the help. I'll see if I can work through the errors on my own.

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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.