Cast Preloaded Scene Instance to its Class?

Godot Version



I’m experiencing some strange behavior that doesn’t appear to be consistent from one Scene to another. I have one scene where I have an exported variable that loads a PackedScene. When I instantiate that PackedScene, I can cast it to the class that it extends no problem:

However, when I do the exact same thing in another Scene, I get an error that the Scene cannot be cast to its class:

Why does the first one cast to its own BattleAction class without an issue, but the second one is showing its class as the base Control class instead of its own BattleMenu class?

Here are some screenshots showing that the script extends Node and the extends Control, not sure what the difference is here:

Here’s a screenshot showing the PackedScenes loaded in the editor UI:

This one works fine:

This one doesn’t:

Strangely, it appears that this was caused by overriding the _init method. Not sure why that caused the issue, but commenting this block out fixed it and allowed me to cast the scene to its class:

I think it may have to do with the fact that the _init method accepted an argument. When preloading scenes that have _init methods with arguments, I think there’s a sort of silent failure that doesn’t get reported in the output window.

Probably has to do with the fact that you’re doing this outside of _ready, i.e. compiler is trying to resolve the types before it knows what type instantiate() can return. Outside of functions, it performs static type checks, i.e. at code write time. When it sees similar assignment within the body of a function, it waits to perform type check until runtime.

The fix, I think, is to move the assignment to _ready(), like so:

var menu: BattleMenu

func _ready():
	menu = menu_scene.instantiate()
	# etc...

spitballing off the top of my head here, though, not testing it in code so ymmv.

1 Like

I appreciate the idea, I had tried that and it didn’t resolve the issue, but you’re not far off. It looks like the issue was the _init method rather than the _ready method. I think my _init override implementation was flawed and was causing the class to not load properly so it couldn’t be cast to anything other than a generic PackedScene. Removing that _init method fixed it.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.