How to extend from Scene

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

I have the scene BaseGame and I want other scenes to have the same main concept from it. Example is Fruit Ninja where you have multiple modes to play (Arcade, Survival etc.). It would be nice if I didn’t have to have every node in every scene just because there’s no option for extending from a scene. I thought I could use extends "res://Scenes/BaseGame.tscn" but that doesn’t work. I can use extends "res://Scripts/BaseGame.gd" but then I can’t access BaseGame.tscn’s nodes! Please add this possibility to the engine!

:bust_in_silhouette: Reply From: Zylann

You can’t have a script extend a scene, that doesn’t make sense. Those are two distinct concepts.
A script only extends other scripts (or engine classes), and scenes only inherit other scenes.
So yes you can have a scene inherit another. And you also can have the root script of the derived scene to also extend from the root script of the base scene, it just needs to be like this:

DerivedScene.tscn ---inherits---> BaseScene.tscn
DerivedScript.gd ---extends---> BaseScript.gd (optionally)

Note that if you used embedded scripts (i.e not saving them to a file), then of course it’s going to be difficult to extend from. Embedded scripts are completely anonymous (so can’t be referred to) and are just a byproduct of the fact resources in general can be embedded. Besides, that doesn’t even work with C#.

I can use extends “res://Scripts/BaseGame.gd” but then I can’t access BaseGame.tscn’s nodes!

You can. Maybe auto-complete doesn’t work correctly in that case, but accessing nodes will definitely work.
You also can even if you decide to have the same, or a completely different script on your root node.

Sorry, I didn’t explain well what I meant with accessing BaseGame.tscn’s nodes.

Survival.tscn:

Node (script attached)

Survival.gd:

extends "res://Scripts/BaseGame.gd"

func _ready():
print("you have chosen survival mode")

BaseGame.tscn:

Node (script attached)

Control

Container

BaseGame.gd:

extends Node
func _ready():
$Control/Container.rect_position = Vector2(0, 50)

If I press a button, I will be changing scene to scene Survival. It will call BaseGame script’s _ready() function because survival script extends BaseGame script but the Container couldn’t be found because the BaseGame scene isn’t loaded. I don’t want to have BaseGame.tscn or Survival.tscn autoloaded by the way.

MaaaxiKing | 2020-05-13 13:53

It will call BaseGame script’s _ready() function because survival script extends BaseGame script but the Container couldn’t be found because the BaseGame scene isn’t loaded

That’s because, as I said, you need to do both kinds if inheritances. They are not necessarily linked or even required, but here it looks like you want them both.

Your script should extend BaseGame.gd (which you did) so it will call the base _ready.
But your Survival.tscn scene should also inherit BaseGame.tscn if you want it to contain the same base nodes. Normally a derived scene is created by going to Scene -> New Inherited Scene.... It’s a choice made at scene creation. However I don’t know how to make an existing scene inherit another (I imagine it can be quite a challenge given the possible conflicts that could arise from existing nodes).
I can’t find an article in the doc explaining this in detail (maybe I just missed it?).

So I usually never use such functionality, I keep using composition with instances instead which I find more flexible, so another way in your case would be to make your Control/Container a re-usable scene which would also be instanced under Survival. That’s only my way of doing though. All that’s required for your game to work is the presence of a Control/Container node under your script’s node, so inheritance isn’t the only way to achieve this.

Zylann | 2020-05-13 15:14

Alright, thanks. Now I inherited the scene. I don’t know why but I don’t like this way xD

MaaaxiKing | 2020-05-13 15:17