Bulletproof scene change with call_deferred
Always use call_deferred when calling change_scene_to_file. Calling synchronously from _input or _ready can cause crashes or freezes. Wrap the call in a guard that checks _transitioning flag to prevent multiple simultaneous transitions.
Scene load error handling with fallback
Always check the return value of get_tree().change_scene_to_file(path). If it returns a value other than OK, push_error with the path and error code, then change to a known-good fallback scene like res://scenes/main_menu.tscn. Never call change_scene_to_file without checking the error return value.
Splash screen stuck when using Tween alone
Do not rely solely on Tweens for splash screen transitions. If a Tween fails, the tween_callback may not fire and the splash screen becomes stuck forever. Instead, use three independent advance paths: a Timer node, a pressed signal connection to a button, and an _input handler for any key press.
Splash screen timer and button implementation
Implement splash screen with a Timer node (autostart=true, wait_time=2.0) connected to _go(), an Enter button with pressed signal connected to _go(), and an _input handler that calls _go() on any key press. Each path checks _transitioning flag and calls deferred _do_change. This provides three redundant paths to advance the screen.
Mouse filter for splash/menu screen elements
Set mouse_filter = IGNORE (value 2) on non-interactive splash/menu screen elements: BG ColorRect, decorative VBox, and Logo Label. Leave mouse_filter at default (STOP) for Button nodes. When non-interactive elements do not ignore mouse events, clicks on the background never reach _input handlers.
Silent change_scene_to_file failures and their causes
change_scene_to_file fails silently when: (1) target scene has a parse error in its script, visible in the Output panel; (2) scene references a script path that was renamed (missing ExtResource); (3) circular dependency exists (scene A instances B which instances A); (4) autoload script crashes, blocking all subsequent scenes. Always check the return value and log errors.
Loading screen with threaded resource loading
For large scenes, use ResourceLoader.load_threaded_request(path) in _ready to load on a background thread. In _process, poll ResourceLoader.load_threaded_get_status(path) which returns THREAD_LOAD_LOADED, THREAD_LOAD_FAILED, or THREAD_LOAD_IN_PROGRESS. On THREAD_LOAD_LOADED, call ResourceLoader.load_threaded_get(path) to retrieve the PackedScene and pass it to get_tree().change_scene_to_packed(packed). Use load_threaded_get_status(path, progress_array) to get progress[0] as a ratio for progress bar display.
Passing data between scenes via SceneTree metadata
For one-shot data passing between scenes, use SceneTree metadata instead of scattered globals. In the source scene, call get_tree().set_meta(key, value) before change_scene_to_file. In the target scene's _ready, check get_tree().has_meta(key), retrieve with get_tree().get_meta(key), and immediately remove it with get_tree().remove_meta(key). This ensures data is consumed once and does not leak across subsequent transitions.
Persistent state with Autoload singleton
For state that must persist across multiple scene transitions, use an Autoload singleton script. Define properties like current_save_slot, pending_action, etc. on the autoload. All scenes can read and write to this singleton, which remains alive across scene changes. This is preferable to SceneTree metadata for state that is not a one-shot transfer.
Signal disconnection in _exit_tree for autoload callbacks
When changing scenes, the old scene is freed but autoload singletons persist. If an autoload has signals connected to nodes in the old scene, explicitly disconnect them in _exit_tree() before the scene is destroyed. Check is_connected() before disconnecting to avoid warnings in strict mode. Failing to disconnect can cause push_warning in Godot 4.6 strict mode even if the callable becomes invalid.
Recommended scene flow hierarchy for narrative games
Implement scene flow in this order: splash_screen.tscn (2 sec with button advance) → main_menu.tscn (autosave check, settings, load list) → loading.tscn (optional, for big assets) → game.tscn (main gameplay) → credits.tscn (rolling credits). Each transition is explicit, deferred, and error-checked.