+1 vote

I was trying to get the name of the current scene by using get_tree().get_current_scene().get_name() but i'm getting the error:

Attempt to call function 'get_name' in base 'null instance' on a null
instance.

I found out that get_current_scene() was giving me null. This is after a change scene where the function was working as intended.
i.e.
get_tree().get_current_scene().get_name() in menu.gd returns menu
get_tree().get_current_scene().get_name() in game.gd returns the error because get_tree().get_current_scene() is null

levelManager.gd (autoloaded singleton) [full script]


extends Node const SCENE_PATH = "res://scenes/" func changescene(scenename):
deffercall("defferedchangescene", scene_name) func defferedchangescene(scenename):
var path = SCENEPATH + scenename + ".tscn"
var root = gettree().getroot()
var current = root.getchild(root.getchildcount() - 1)
current.free()
var scene
resource = ResourceLoader.load(path)
var newscene = sceneresource.instance()
gettree().getroot().addchild(newscene)
gettree().setcurrentscene(newscene) func process(delta):
if Input.isactionpressed("close"):
get_tree().quit() func deffercall(funcname, funcparam):
call
deferred(funcname, funcparam)

--[Shortened scripts:]--

menu.gd


extends Node func ready():
var scene
name = gettree().getcurrentscene().getname()
print(scene_name) # returns 'menu' on full version of the script, mechanism that called changescene here func changescene():
levelManager.change_scene("game")

game.gd

extends Node game variables declared here func ready():
var scene
name = gettree().getcurrentscene().getname()
print(scenename) #returns an error due to gettree().getcurrentscene() being null rest of the game logic code here

I want to know why this is the case. Is there something wrong with the way i changed scenes from levelManager.gd?

I resolved this issue by:
setting var current_scene_name in levelManager.gd
-- both in menu.gd and game.gd --
re-setting current_scene_name by calling self.get_name()

i.e.
levelManager.gd


var currentscenename

--menu.gd and game.gd --

var scenename = self.getname()
levelManager.currentscenename(scene_name)

^ This is obviously a workaround. It works but i still want to know why i'm getting different outputs after calling get_tree() while they practically are in the same remote location in the node.

link to screenshot because embedding images doesn't seem to work:
treeScreenshotBeforeAndAfterChangingScenes

This is probably a duplicate of this but this isn't exactly an answer and i'm not entirely sure it can be a comment there either.

in Engine by (87 points)

3 Answers

+1 vote
Best answer

It happens because _ready() gets called before new scene is set as a current scene.

get_tree().get_root().add_child(newscene) # _ready() is called here

get_tree().set_current_scene(newscene)

You can set new current scene when node enters SceneTree like this:

newscene.connect("tree_entered", get_tree(), "set_current_scene", [newscene], CONNECT_ONESHOT)

get_tree().get_root().add_child(newscene)

I presume menu.gd script is in your main scene and you're not using levelManager to go to this scene. In that case Godot sets this scene as current on its own, which happens before _ready() and even before _enter_tree().

by (2,164 points)
selected by

This makes sense when i saw the delay of the change when the tree was updating in the remote pane/window.

But i don't understand how menu.gd is not using levelManager to change scenes? Because there is no other code that commands to change scenes except inside levelManager.

I mean you're not changing current scene to menu.gd from other scene because your game starts with menu.gd. I could be wrong since i can't see all of your code.

Are you changing a scene to menu.gd from anywhere in your code? I expect the same problem you're having with game.gd if you do this.

You're correct.

I'm having the same issue upon calling get_tree().get_current_scene().get_name() when changing from game.gd to menu.gd

This helped a lot. Thank you!

0 votes

I've had the same problem with autoload as well. I believe when you autoload something, it only brings access to the script and variables of the node, not its children, parents, or even the node itself. That's why when you call any one of those get functions, its called from a null base. You're using an autoloaded, null base node.

To fix, a general solution would be to just create an on-ready var of the node that you want in the specific nodes you need it in, and not in an autoloaded node.

Like so: onready var levelManager = get_node("/root/Node2D/levelManager") #change the getNode path to whatever you need

by (25 points)

I believe when you autoload something, it only brings access to the script and variables of the node, not its children, parents, or even the node itself.

I'm sorry, can you expand on this? I don't get it.

I'm not sure if I'm getting this right, but it seems that this assumes I'm calling get_tree().get_current_scene.get_name() from inside the singleton?

If it is, i'm calling the function from outside of it, from menu.gd and game.gd, not levelManager.gd

You're right, I was assuming you were calling it from levelManager.gd. However, you do call your change scene function from levelManager, and maybe that's why the scene change isn't actually registering in your other nodes. Try unautoloading level manager, name the onready var levelManager (so you dont have to change code), and then retry it.

0 votes

Autoloaded scripts and scenes are being added before the first current scene is set up on the tree, you need to wait to check, or connect to the viewport's root or the tree to get when the current scene is added.

One signal you can use is node_added on SceneTree, there are notifications too for Viewport(Node) changes.

by (7,796 points)

I just read node_added in the documentation. It looks super useful! But i don't know how to use it. XD
Can you give a short, simple example how to implement this?

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.

Categories