get_current_scene() returning null in _ready()

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By GameVisitor

Hi all,

get_current_scene() is returning null when called in _ready(): method as below:

extends WorldEnvironment
func _ready():
         var sceneTree = get_tree()    //value returned is not null here 
         var curScene = sceneTree.get_current_scene()    //null !?!

Shouldn’t the node be initialized here, and a proper value returned ?
(WorldEnvironment is my scene root node and the script is attached to it)

Thanks.

Does it happen if you use Play Scene (F6)?
Is this scene your main scene?

hilfazer | 2018-12-22 13:59

Works fine for me.
How did you know that curScene is null? I don’t see any output here.

P! | 2018-12-22 21:51

@hilfazer, That’s interesting !

When hitting F6, it does have a value, when running the project it doesn’t…

Which brings us to your second suggestion: no, it is a scene loaded using deferred loading as per official documentation.

Maybe this _ready() is being called upon reaching : current_scene = s.instance()but for the call get_current_scene() to be successful get_tree().set_current_scene( current_scene ) needs to execute first.

Any idea how to bypass this ? (without changing goto_scene() method since it is used for all scene loading).

Thx for your suggestion so far !

GameVisitor | 2018-12-22 22:06

@P! in the debugger it shows as null, the issue is as suspected by @hilfazer, something to do the way the scene is loaded and added to the project.

GameVisitor | 2018-12-22 22:11

:bust_in_silhouette: Reply From: hilfazer

Since you are following official documentation getting null in _ready() is normal since it’s called before current scene changes

# Add it to the active scene, as child of root.
get_tree().get_root().add_child(current_scene) # _ready() is called here

# Optional, to make it compatible with the SceneTree.change_scene() API.
get_tree().set_current_scene(current_scene)

Following code in _ready() function did help but i don’t know if it’s guaranteed to work:

yield(get_tree(), "idle_frame")
var curScene = get_tree().get_current_scene()

[shamelessselfpromotion]
Or you may use my version of scene switcher that is based on official docs. It supports passing parameters and emits a signal after current scene is changed!
https://github.com/hilfazer/Projects/tree/master/Godot/SceneSwitcher
[/shamelessselfpromotion]

I was thinking of using emit_signal() before reading your answer (I never had to use a custom signal before) and it worked perfectly.

I didn’t use your class / project but it inspired the code I wrote for custom signal.
No problem with your shamelessselfpromotion
Thx for your help :slight_smile:

PS: You other projects on github for 3.X (ex: DungeonCrawler) are not loading using Godot 3.0.6

GameVisitor | 2018-12-23 14:55

Glad i could help.
I’ve added a 3.0.6 version of one of my projects. Others aren’t supposed to work in 3.0.6 ;p

hilfazer | 2018-12-23 20:44

Mmm the problem with the workaround is that calling :

get_tree().reload_current_scene()

Does not trigger the onCurrentChanged() event, although _ready() is still being called…

GameVisitor | 2018-12-24 10:34

I know, i wish there was a signal on changing current scene in SceneTree. Currently i don’t know how to detect a change of current_scene.

However, after reload_current_scene() in _ready(), get_tree().current_scene does not return a null but a Node that is calling _ready().

It means the engine can make a Node a current_scene before it’s added to SceneTree but we, via GDScript, can’t.

hilfazer | 2018-12-24 13:50

I found a dirty workaround but it’s working (on xmas eve :-P)
In case the scene detects it is being reloaded, directly call the previous function

var curScene = sceneTree.get_current_scene()
if( curScene != null):
	print("I am being reloaded !!!")
	onCurrentChanged()
	pass

:slight_smile:

GameVisitor | 2018-12-24 18:31