i want to change to a scene and after that i want to call a method on that scene script. i tried this and it did not succeed, the current_scene property is null which leads to an error. first i tried a simpler version without await, same problem.
func _on_continue_game_button_pressed() -> void:
var newScene = await switchToGameScene()
newScene.ContinueStory()
func switchToGameScene () -> Node:
var tree = get_tree()
tree.change_scene_to_file("res://scenes/adventure_game.tscn")
await tree.process_frame
return tree.current_scene
at the end i found a workaround which works, but seems unnecessarily complicated to me to accomplish such a seemingly trivial task:
func switchToGameScene () -> Node:
var newScene = load("res://scenes/adventure_game.tscn") as PackedScene
var scene = newScene.instantiate()
var tree = get_tree()
var cur_scene = tree.get_current_scene()
tree.get_root().add_child(scene)
tree.get_root().remove_child(cur_scene)
tree.set_current_scene(scene)
return scene
Scenes are meant to be independent of each other. I assume that you are calling the scene change on an autoload/singleton/global, so it isn’t freed by the scene change? If so, you might want to look into custom scene changing since the default methods aren’t meant for anything more complicated than deleting all the nodes and loading a new scene.
If you are not using an autoload, then the node the script is on will be freed when the scene changes, and you can’t pass any information to the new scene.
Your workaround only works because the old scene is never freed and is instead orphaned.
i don’t know what do you mean by “it only works because i do not free the old scene”? i now added queue_free() and it still works:
func switchToGameScene () -> Node:
var newScene = load("res://scenes/adventure_game.tscn") as PackedScene
var scene = newScene.instantiate()
var tree = get_tree()
var cur_scene = tree.get_current_scene()
tree.get_root().add_child(scene)
tree.get_root().remove_child(cur_scene)
cur_scene.queue_free()
tree.set_current_scene(scene)
return scene
is there be a better way to call a method on a newly created scene?
queue_free() waits until the end of the frame to free the node. So it works here because you don’t free the node with the script on it immediately.
I think you already have implemented a custom scene manager. But you can’t really reuse the function because it’s on a node in a specific scene and calls a specific function. You could make a “root” node that will change the scene like the current script does, but it doesn’t get freed itself so you can reuse functions.