godot-docs
godot-docs copied to clipboard
Teach how to work with `change_scene_to_packed` and `change_scene_to_file`
Your Godot version:
4.2.1
Game context:
- Player leaves level
- Screen fades to black
- Scene is switched
- Black fades away to reveal the new scene
Issue description:
I just upgraded Godot and now logic executed directly after scene switching (via change_scene_to_packed) is broken. I assume due to the following (docs):
The current scene node is immediately removed from the tree. From that point, Node.get_tree called on the current (outgoing) scene will return null. current_scene will be null, too, because the new scene is not available yet.
I generally like that the behaviour is now more predictable ... but I couldn't find any information on how to work with it.
What didn't work:
-
await get_tree().process_frame
-> Doesn't work due toget_tree()
being null -
await get_tree().create_timer(duration).timeout
-> Doesn't work due toget_tree()
being null -
await Engine.get_main_loop().process_frame
didn't work (idea source) -
call_deferred()
-> Never got triggered (I assume because scene didn't exist anymore) - No signal exists like
tree_created()
What would have worked:
- I assume the new scene's
_ready
function would have triggered correctly but as the transitions should happen in each level switch I didn't want to add code to each level's_ready
-function
My current workaround
In one scene – e.g. level_1
– I now call the autoload singleton LevelSwitcher.switch_to("res://level_2.tscn")
instead of executing the code directly. This works, but my approach to detect the new scene is really dirty (see below).
level_switcher.gd
extends Node
var current_scene
signal scene_changed
func _process(delta):
# Feels dirty
if current_scene != get_tree().get_current_scene():
emit_signal("scene_changed")
current_scene = get_tree().get_current_scene()
func switch_to(scene_file_path):
# 1. Trigger "leaving level"-transition and await its end
# 2. Switch scene
var scene = ResourceLoader.load_threaded_get(scene_file_path) # This was loaded before somewhere else
get_tree().change_scene_to_packed(scene)
# 3. Await switch
await scene_changed
# 4. Spawn player and trigger "entering level"-transition
URL to the documentation page (if already existing):
Proposal
Change the "Change scenes manually"-page to "How to change scenes" with the following content:
-
Automatic scene switching: Most basic example for
change_scene_to_file
-
Automatic scene switching (advanced): Loading scene in the background using
change_scene_to_packed
and trigger something right after the scene switch (I still don't know how to do this correctly) - Manual scene switching: The content the page currently is focussed on
This probably relates to #8846
I agree that better docs info on this would be super helpful! I'm running into a similar problem right now. After I use change_scene_to_packed, my _ready() functions on scripts in the new scene don't run.
I can also recommend this tutorial by "The Shaggy Dev". I now combined my approach mentioned above with his transition logic and it works really well.