1
\$\begingroup\$

I have a situation where _notificaion doesn't work as intended.

I have three scenes: game scene (named Puzzle), main menu scene (MainMenu) and Victory scene.

When player on android phone presses back key on Puzzle, he/she gets back to MainMenu.

I use this code inside _notification and it works fine.

if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST:
   get_tree().change_scene("res://scenes/MainMenu.tscn")

When puzzle is solved, I add Victory scene to the root node by using get_tree().root.call_deferred('add_child', victoryScene) while puzzle screen is the current scene. Then, after victoryScene finishes its start_animation, I remove puzzle from root by queue_free using a signal called 'finished' that is emitted when start_animation is completed.

The issue I encounter is that I am using the same code of going back to MainMenu inside _notification function of victoryScene, but it doesn't work.

I tried using the following code inside _notification of Puzzle and Victory, and it worked fine while testing scenes individually using play scene button.

if get_tree().current_scene.name == "Puzzle":
    get_tree().change_scene("res://scenes/MainMenu.tscn")

However, I get an error saying that get_tree().current_scene is null when I use play project button.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

You have described that you got rid of the current scene:

When puzzle is solved, I add Victory scene to the root node by using get_tree().root.call_deferred('add_child', victoryScene) while puzzle screen is the current scene. Then, after victoryScene finishes its start_animation, I remove puzzle from root by queue_free using a signal called 'finished' that is emitted when start_animation is completed.

Emphasis mine.

Since you freed the current scene, get_tree().current_scene becomes invalid.


You could, for example, tell Godot that the victoryScene is the current scene when you call queue_free on the puzzle scene:

get_tree().current_scene = victoryScene

About the back button, you could have a field in the victoryScene that stores where to go back to. For example:

var back_button_scene:String

So you can do this:

if back_button_scene != "":
    get_tree().change_scene(back_button_scene)

And have the puzzle scene set it:

victoryScene.back_button_scene = "res://scenes/MainMenu.tscn"

And you would do something similar everywhere you need the victoryScene.


I submit to your consideration to have an autoload (singleton) handle all this logic, in such way that nothing access get_tree().current_scene and related methods except said the autoload.

So, either the other scenes call the autoload, or the autoload handles the notifications directly. So you don't have to replicate this logic for every scene.

Since the autoload would be handling changes between scene, it could also implement loading screens and transitions (fades, et.al.).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .