+1 vote

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!

asked May 13 in Engine by MaaaxiKing (291 points)
edited May 13 by MaaaxiKing

1 Answer

0 votes

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.

answered May 13 by Zylann (26,153 points)

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.

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.

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

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.