-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
change_scene_to_*
needs to await for two process_frame
s
#86286
Comments
Okay, I thought it's because I put the code snippet inside But doesn't |
|
@Sauermann Where does it happen inside a frame relative to
|
That I don't know. I haven't yet looked into the order of things happening within a single frame. |
func change_scene(path: String) -> void:
print("------ changing to %s ------" % path)
var tree := get_tree()
print("[Before] %s" % tree.current_scene, " - frame: ", Engine.get_process_frames())
tree.change_scene_to_file(path)
await tree.process_frame
print("[after tree.process_frame] %s" % tree.current_scene, " - frame: ", Engine.get_process_frames())
await tree.process_frame
print("[after tree.process_frame] %s" % tree.current_scene, " - frame: ", Engine.get_process_frames()) Output:
The first await isn't really waiting, when the call comes from
The output will now be:
If nothing else, this works as a work-around for the MRP. |
This seems like an important caveat with |
It's kinda irrelevant whether it happens before/after The same can be told about the black interval in the diagram below. For awaiting single Note I kinda ignored threading when analyzing this so it might be not that simple. 🙃 Anyway here's I think a somehow reliable way to detect/await the scene change: extends Node
signal _scene_changed
@onready var _tree: SceneTree = get_tree()
func change_scene(path: String) -> Error:
var error: Error = _tree.change_scene_to_file(path)
if error == OK:
if not _tree.node_added.is_connected(_on_node_added):
_tree.node_added.connect(_on_node_added)
await _scene_changed
# Scene changed (and ready).
return error
func _on_node_added(node: Node) -> void:
if node == _tree.current_scene:
_tree.node_added.disconnect(_on_node_added)
# Here `_tree.current_scene` is already changed.
# But note we are in the middle of executing `tree.root.add_child(current_scene)`.
# So likely deferring it a little further is wanted, e.g. until its `ready` signal.
await _tree.current_scene.ready
_scene_changed.emit() Given it's autoloaded as It works because godot/scene/main/scene_tree.cpp Lines 1396 to 1406 in bf8dd73
|
Thanks for the workaround. I think |
I wish there was a signal Is there some proposal for this to happen? For reference, here's a processing diagram that I did for Godot 4. Here we can see how the input is handled at the very start of the frame and the scene is changed after the SceneTree.process_frame signal. Exactly as @kleonc explained. Another possible workaround could be a timer in idle processing mode. It would trigger just after the scene change. So |
Tested versions
Godot 4.2+
System information
Arch Linux
Issue description
change_scene_to_*()
methods always change scene in a deferred way.The documentation says scene change happens at the end of the frame. But I have to await
SceneTree.process_frame
twice instead of once since #78988.godot/doc/classes/SceneTree.xml
Lines 55 to 56 in 2d0ee20
Steps to reproduce
See above, or use the MRP.
Minimal reproduction project (MRP)
test-change-scene.zip
The text was updated successfully, but these errors were encountered: