Game Development with Godot & GDScript Module 1 – Godot, the editor and your first scene
Nodes, scenes and instancing
Build Godot 4.7 scenes from nodes, instance them many times, read the .tscn text format and change a scene safely with inherited scenes and editable children.
What you will learn
- Describe nodes, the scene tree and scenes, and name a node's path in a running game
- Build a scene and instance it several times, overriding a property on one instance
- Read a .tscn file and find its nodes, external resources, instances and overrides
- Use inherited scenes and editable children to change a scene without editing its source
Before you start
What you’ll learn · Before you start
What you will learn
- Describe nodes, the scene tree and scenes, and name a node's path in a running game
- Build a scene and instance it several times, overriding a property on one instance
- Read a .tscn file and find its nodes, external resources, instances and overrides
- Use inherited scenes and editable children to change a scene without editing its source
Before you start
On this page
A level with 40 coins needs one coin scene, not 40 coins: change the scene once and every coin follows, except the ones you deliberately made different. That rule, and the text file where Godot records the exceptions, decide how easy a game is to change a month from now.
Here you build a player from nodes and see it in the running scene tree, instance a coin scene five times and watch an
override survive a change to the coin, read the .tscn files Godot saves, and change scenes through inherited scenes
and editable children without touching their source.
A node does one job, and a scene is a tree of them
A node: A building block of a Godot game with one job, such as drawing a picture or following the player with a camera. Every node has a name, properties and callbacks, and it can have child nodes. is one building block with one job: a Sprite2D draws a picture, a CollisionShape2D
gives a body its shape, a Camera2D decides what the screen shows. Every node has a name, properties you edit in the
Inspector, callbacks the engine calls every frame, and a place in a tree: it can have children, and those children
can have children. A scene: A tree of nodes with a single root node, saved to a file such as player.tscn so that it can be instanced as often as needed. is such a tree with a single root node, saved to a file so that it
can be used again.
This program builds the player of the Godot documentation’s own example, a CharacterBody2D with a sprite, a collision
shape and a camera, and adds it to the running game:
extends SceneTree
# A player made of four nodes, as the Scene dock would show it, added to the running scene tree.
func _initialize() -> void:
var player := CharacterBody2D.new()
player.name = "Player"
for part in [["Sprite", Sprite2D.new()], ["Hitbox", CollisionShape2D.new()], ["Camera", Camera2D.new()]]:
part[1].name = part[0]
player.add_child(part[1])
root.add_child(player)
await process_frame
player.print_tree_pretty()
print("Path of the camera: ", player.get_node("Camera").get_path())
print("Parent of Player: ", player.get_parent().name, ", a ", player.get_parent().get_class())
# Siblings need different names, and Godot renames a newcomer that clashes.
var names := []
for readable in [false, true, false]:
var coin := Node.new()
coin.name = "Coin"
player.add_child(coin, readable)
names.append(String(coin.name))
print("Three children named Coin became: ", ", ".join(names))
quit() from session import files, run
files("project.godot", "tree_tour.gd")
run("""
godot --headless --no-header --script tree_tour.gd
""") Output
$ godot --headless --no-header --script tree_tour.gd
┖╴Player
┠╴Sprite
┠╴Hitbox
┖╴Camera
Path of the camera: /root/Player/Camera
Parent of Player: root, a Window
Three children named Coin became: Coin, Coin2, @Node@2
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 tree_session.py
print_tree_pretty() draws the same tree the Scene dock shows: Player with its three children, in the order they
were added. Once the game runs, the scene sits inside the scene tree: The one tree of nodes of a running game, with a Window named root at the top. Every node in it has a path from the top, such as /root/Player/Camera. of the whole game,
under a node called root, a Window the engine creates. That gives every node a path, here /root/Player/Camera,
read like a folder path from the top.
The Player scene inside the running scene tree
Text description of the diagram
The diagram shows the tree from top to bottom.
- At the top is root, the Window the engine creates for every running game.
- Its child is Player, a CharacterBody2D, the root node of the Player scene.
- Player has three children: Sprite, a Sprite2D that draws the picture; Hitbox, a CollisionShape2D that gives the body its shape; and Camera, a Camera2D, whose path in the running tree is /root/Player/Camera.
Siblings need different names, because a path must lead to one node. The last line of the run shows what Godot does
with three children called Coin: the first keeps the name, and the others are renamed, to Coin2 when add_child()
is asked for a readable name and to @Node@2 when it is not. The editor picks readable names for you; code that
adds nodes should name them itself.
Name nodes in PascalCase
The project organisation guide recommends PascalCase for node names, like Godot’s own node types, and snake_case for
files: a Player node saved as player.tscn.
Checkpoint
Check: Nodes, scenes and the scene tree
Instances follow their scene until you override them
An instance: A copy of a saved scene placed inside another scene. It takes every property from its scene except the ones changed on it, its overrides, which survive later changes to the scene. is a copy of a saved scene placed in another scene. In the editor, the chain-link button of the Scene dock adds one, and every instance starts identical to its scene. Change the scene and save it, and every instance changes with it, except in the properties you changed on that instance: those are overrides, and they win.
Step through a coin scene used five times in a level, the case of the next program, and watch where each coin’s colour comes from:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- One scene, one node. coin.tscn holds a single node, Coin, a Node2D whose modulate colour is gold. Saved, it is a scene that can be used again and again.
- Five instances. level.tscn adds five instances of coin.tscn, Coin1 to Coin5, each a node of its own in the level. They take their colour from coin.tscn, so all five are gold.
- Positions are overrides. Coin2 to Coin5 move to x = 40, 80, 120 and 160. Each new position is an override, stored in level.tscn for that instance only; Coin1 stays at the scene's own position.
- Coin5 turns red. Changing Coin5's colour in the level overrides it too. level.tscn now stores modulate for Coin5 alone, and the editor shows a revert arrow beside that property.
- The scene changes. coin.tscn is edited to sky blue and saved. Coin1 to Coin4 never overrode the colour, so they follow it; Coin5 keeps its red, as the run printed.
- Revert brings it back. Clicking the revert arrow beside Coin5's modulate deletes the override, and Coin5 takes the scene's sky blue like the others.
The program does exactly that: it saves a gold coin scene, instances it five times with positions 40 pixels apart, turns Coin5 red, then recolours the coin scene sky blue and loads the level again:
extends SceneTree
# Saves a coin scene, instances it five times in a level, changes one instance and then the coin scene itself.
func _initialize() -> void:
var coin := Node2D.new()
coin.name = "Coin"
coin.modulate = Color.GOLD
_save(coin, "res://coin.tscn")
var coin_scene := load("res://coin.tscn") as PackedScene
var level := Node2D.new()
level.name = "Level"
for i in 5:
# GEN_EDIT_STATE_INSTANCE keeps the scene's own values, as the editor does, so saving stores only changes.
var instance := coin_scene.instantiate(PackedScene.GEN_EDIT_STATE_INSTANCE) as Node2D
instance.name = "Coin%d" % (i + 1)
instance.position = Vector2(40 * i, 0)
level.add_child(instance)
instance.owner = level
level.get_node("Coin5").modulate = Color.RED
_save(level, "res://level.tscn")
# Recolour the coin scene, as editing coin.tscn and saving it would.
coin.modulate = Color.SKY_BLUE
_save(coin, "res://coin.tscn")
ResourceLoader.load("res://coin.tscn", "", ResourceLoader.CACHE_MODE_REPLACE)
var level_scene := ResourceLoader.load("res://level.tscn", "", ResourceLoader.CACHE_MODE_IGNORE) as PackedScene
var reloaded := level_scene.instantiate()
for c: Node2D in reloaded.get_children():
print(c.name, " at ", c.position, " is #", c.modulate.to_html(false))
reloaded.free()
level.free()
coin.free()
quit()
func _save(root_node: Node, path: String) -> void:
var packed := PackedScene.new()
packed.pack(root_node)
ResourceSaver.save(packed, path) from session import files, run
files("project.godot", "instancing.gd", "plain_level.gd")
# Godot gives every node a random unique_id when it first saves a scene; the session shows those ids as <random id>.
# The last two commands show a common mistake: a level saved after a plain instantiate().
run("""
godot --headless --no-header --script instancing.gd
cat level.tscn
cat coin.tscn
godot --headless --no-header --script plain_level.gd
cat plain_level.tscn
""", mask=[(r"unique_id=\d+", "unique_id=<random id>")]) Output
$ godot --headless --no-header --script instancing.gd
Coin1 at (0.0, 0.0) is #87ceeb
Coin2 at (40.0, 0.0) is #87ceeb
Coin3 at (80.0, 0.0) is #87ceeb
Coin4 at (120.0, 0.0) is #87ceeb
Coin5 at (160.0, 0.0) is #ff0000
$ cat level.tscn
[gd_scene format=3]
[ext_resource type="PackedScene" path="res://coin.tscn" id="1_u52ul"]
[node name="Level" type="Node2D" unique_id=<random id>]
[node name="Coin1" parent="." unique_id=<random id> instance=ExtResource("1_u52ul")]
[node name="Coin2" parent="." unique_id=<random id> instance=ExtResource("1_u52ul")]
position = Vector2(40, 0)
[node name="Coin3" parent="." unique_id=<random id> instance=ExtResource("1_u52ul")]
position = Vector2(80, 0)
[node name="Coin4" parent="." unique_id=<random id> instance=ExtResource("1_u52ul")]
position = Vector2(120, 0)
[node name="Coin5" parent="." unique_id=<random id> instance=ExtResource("1_u52ul")]
modulate = Color(1, 0, 0, 1)
position = Vector2(160, 0)
$ cat coin.tscn
[gd_scene format=3]
[node name="Coin" type="Node2D" unique_id=<random id>]
modulate = Color(0.5294118, 0.80784315, 0.92156863, 1)
$ godot --headless --no-header --script plain_level.gd
$ cat plain_level.tscn
[gd_scene format=3]
[ext_resource type="PackedScene" path="res://coin.tscn" id="1_buv6t"]
[node name="Level" type="Node2D" unique_id=<random id>]
[node name="Coin1" type="Node2D" parent="." unique_id=<random id> instance=ExtResource("1_buv6t")]
modulate = Color(0.5294118, 0.80784315, 0.92156863, 1)
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 instancing_session.py
The first five lines are the result: Coin1 to Coin4 are #87ceeb, sky blue, because they never changed their colour,
and Coin5 is still #ff0000, red. In the editor, an overridden property shows a revert arrow beside it; clicking it
deletes the override, and the instance follows its scene again.
Key idea
An instance takes every property from its scene except the ones you changed on it, and those overrides are kept even when the scene changes.
Checkpoint
Check: Instances and overrides
A .tscn file lists nodes and stores only what differs
The same run printed level.tscn and coin.tscn, and a third file that the mistake at the end of this section
explains. A .tscn file is the text form of a scene, made to be readable and to diff well in version control. Read
level.tscn from the top, using this map:
| Line in level.tscn | What it records |
|---|---|
[gd_scene format=3] |
the file descriptor: a scene saved by Godot 4 (Godot 3 wrote format=2) |
[ext_resource type="PackedScene" path="res://coin.tscn" id="1_u52ul"] |
a file the scene uses, with a local id |
[node name="Level" type="Node2D" …] |
the root node: a name and a type, no parent |
[node name="Coin2" parent="." … instance=ExtResource("1_u52ul")] |
an instance of coin.tscn under the root, with no type of its own |
position = Vector2(40, 0) |
an override: a property that differs from the instanced scene |
Look at what is not there. Coin1 has no property lines at all, because nothing about it differs from coin.tscn.
None of the instances stores a colour except Coin5, which is why the recolour reached the other four. coin.tscn
holds one property, modulate; every other property of its node is at its default and is not written, the same rule
as in project.godot. parent="." means a child of the scene’s root, and deeper nodes write a path such as
parent="Arm/Hand".
New in Godot 4.6
Every node line carries a unique_id: scenes saved with 4.6 or later give each node a unique internal id, so that
Godot can follow it through renames and moves. The ids are random when a node is first saved, which is why the
session shows them as <random id>.
A scene saved by an older Godot has no ids yet and may carry load_steps= in its first line, which 4.6 and later
ignore; it gets its ids the next time it is saved.
Instancing from code without the editor's state
A script that instances a scene with a plain instantiate() and then packs and saves the result stores the scene’s
own values as overrides. plain_level.gd, below, does that, and the session’s last file shows the result: in
plain_level.tscn, Coin1 has a type of its own and the coin’s modulate, so a later recolour of coin.tscn would
never reach it. instancing.gd passes PackedScene.GEN_EDIT_STATE_INSTANCE, which the editor uses and only editor
builds have, so only real overrides are saved.
extends SceneTree
# The mistake: one coin instanced with a plain instantiate(), then the level packed and saved.
func _initialize() -> void:
var coin_scene := load("res://coin.tscn") as PackedScene
var level := Node2D.new()
level.name = "Level"
var coin := coin_scene.instantiate() as Node2D
coin.name = "Coin1"
level.add_child(coin)
coin.owner = level
var packed := PackedScene.new()
packed.pack(level)
ResourceSaver.save(packed, "res://plain_level.tscn")
level.free()
quit() Checkpoint
Check: Reading a .tscn file
Inherited scenes and editable children change a scene without touching it
Overrides on an instance work in one place. Two more tools let you change a scene’s insides without editing the scene
itself. An inherited scene: A scene built on a base scene with Scene > New Inherited Scene. It saves only its differences from the base and follows every other change made to the base. is a new scene built on a base: Scene > New Inherited
Scene creates one whose root is an instance of the base, and it saves only its differences. Here fast_enemy.tscn
inherits from enemy.tscn, a Node2D with a Body sprite and a Name label, halves the body and gives the label its
own text. The session then edits the base twice, the second time by renaming its Name node:
from session import files, run
files("slimes=.")
# enemy.tscn is the base scene; fast_enemy.tscn inherits from it, as Scene > New Inherited Scene makes it.
run("""
godot --headless --quiet --import
cat fast_enemy.tscn
godot --headless --no-header --script show_enemies.gd
godot --headless --no-header --script edit_base.gd -- move
godot --headless --no-header --script show_enemies.gd
godot --headless --no-header --script edit_base.gd -- rename
godot --headless --no-header --script show_enemies.gd
""") Output
$ godot --headless --quiet --import
$ cat fast_enemy.tscn
[gd_scene format=3 uid="uid://bfdge71m070fq"]
[ext_resource type="PackedScene" uid="uid://myliukswiblc" path="res://enemy.tscn" id="1_enemy"]
[node name="FastEnemy" unique_id=971141019 instance=ExtResource("1_enemy")]
[node name="Body" parent="." index="0" unique_id=1998074536]
scale = Vector2(0.5, 0.5)
[node name="Name" parent="." index="1" unique_id=1428043951]
text = "Fast slime"
$ godot --headless --no-header --script show_enemies.gd
Enemy: Body at (0.0, 0.0), scale (1.0, 1.0); Name "Slime"
FastEnemy: Body at (0.0, 0.0), scale (0.5, 0.5); Name "Fast slime"
$ godot --headless --no-header --script edit_base.gd -- move
$ godot --headless --no-header --script show_enemies.gd
Enemy: Body at (0.0, -8.0), scale (1.0, 1.0); Name "Big slime"
FastEnemy: Body at (0.0, -8.0), scale (0.5, 0.5); Name "Fast slime"
$ godot --headless --no-header --script edit_base.gd -- rename
$ godot --headless --no-header --script show_enemies.gd
Enemy: Body at (0.0, -8.0), scale (1.0, 1.0); Title "Big slime"
WARNING: res://fast_enemy.tscn: A node in the scene this one inherits from has been removed or moved, so a recovery process needs to take place. Please re-save this scene to avoid the cost of this process next time.
at: instantiate (scene/resources/packed_scene.cpp:292)
GDScript backtrace (most recent call first):
[0] _initialize (res://show_enemies.gd:6)
FastEnemy: Body at (0.0, -8.0), scale (0.5, 0.5); Title "Fast slime"
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 inherit_session.py
The first edit moved the base’s Body up 8 pixels and changed its label to “Big slime”. FastEnemy took the new
position, because it never overrode it, and kept its own scale and its own “Fast slime”. The second edit renamed Name
to Title in the base, which before 4.6 could break the inherited scene’s change to that node. Godot 4.7.2 found the
renamed node, as the unique ids of 4.6 allow, printed a warning asking you to re-save the inherited scene, and applied
“Fast slime” to Title.
editable children: An option on one instance that shows its inner nodes in the scene holding it, so they can be changed for that instance alone without editing the instanced scene. serve a single instance instead: right-click an instance in the
Scene dock, choose Editable Children, and its inner nodes appear in that scene for you to change. This level places one
enemy as Guard and changes its label only there:
extends SceneTree
# A level with one enemy whose children are made editable, and one of them changed only in this level.
func _initialize() -> void:
var level := Node2D.new()
level.name = "Level"
var guard := (load("res://enemy.tscn") as PackedScene).instantiate(PackedScene.GEN_EDIT_STATE_INSTANCE)
guard.name = "Guard"
level.add_child(guard)
guard.owner = level
level.set_editable_instance(guard, true)
guard.get_node("Name").text = "Gate guard"
var packed := PackedScene.new()
packed.pack(level)
ResourceSaver.save(packed, "res://level.tscn")
level.free()
print(FileAccess.get_file_as_string("res://level.tscn"))
quit() from session import files, run
files("slimes=.")
# Godot gives every new node a random unique_id when it first saves a scene; the session shows those ids as <random id>.
run("""
godot --headless --quiet --import
godot --headless --no-header --script guard_level.gd
""", mask=[(r"unique_id=\d+", "unique_id=<random id>")]) Output
$ godot --headless --quiet --import
$ godot --headless --no-header --script guard_level.gd
[gd_scene format=3]
[ext_resource type="PackedScene" path="res://enemy.tscn" id="1_u52ul"]
[node name="Level" type="Node2D" unique_id=<random id>]
[node name="Guard" parent="." unique_id=<random id> instance=ExtResource("1_u52ul")]
[node name="Name" parent="Guard" index="1" unique_id=<random id>]
text = "Gate guard"
[editable path="Guard"]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 editable_session.py
The override is stored as a node line with parent="Guard", an inner node of the instance, and the last line,
[editable path="Guard"], records that the instance’s children are editable. enemy.tscn itself did not change.
| You want | Use | Where the change is saved |
|---|---|---|
| One instance to differ in a property of its root | an override in the Inspector | the scene that holds the instance |
| One instance to differ inside, in its child nodes | Editable Children on that instance | the scene that holds the instance |
| A family of variants that share a base and each change it | an inherited scene per variant | each variant’s own .tscn |
Re-save after a warning
When Godot warns that a node of the base scene “has been removed or moved”, open the inherited scene and save it once. The recovery then happens one last time, and the file records the new node.
Checkpoint
Check: Inherited scenes and editable children
Practise: build a player and a level, then check them
Build these two scenes in your own Godot 4.7.2 project, in the editor:
player.tscn: aCharacterBody2Droot namedPlayer, with aSprite2DnamedSpriteand aCollisionShape2DnamedHitboxas its children.level.tscn: aNode2Droot namedLevel, with one instance ofplayer.tscn, still namedPlayer, moved to position (64, 32) in the Inspector.- Save
check_scenes.gdin the project’s folder and rungodot --headless --script check_scenes.gd -- level.tscnin a terminal there.
extends SceneTree
# Checks player.tscn and a level against the practice task:
# godot --headless --script check_scenes.gd -- level.tscn
var passed := 0
var failed := 0
func _initialize() -> void:
var args := OS.get_cmdline_user_args()
var level_path := "res://" + (args[0] if args.size() > 0 else "level.tscn")
var player := (load("res://player.tscn") as PackedScene).get_state()
_check(player.get_node_name(0) == &"Player" and player.get_node_type(0) == &"CharacterBody2D",
"player.tscn: the root is a CharacterBody2D named Player")
_check(_child_of_root(player, "Sprite") == &"Sprite2D", "player.tscn: a Sprite2D named Sprite under the root")
_check(_child_of_root(player, "Hitbox") == &"CollisionShape2D", "player.tscn: a CollisionShape2D named Hitbox under the root")
var level := (load(level_path) as PackedScene).get_state()
_check(level.get_node_name(0) == &"Level" and level.get_node_type(0) == &"Node2D", "level: the root is a Node2D named Level")
var index := _index_of_child(level, "Player")
var instance := level.get_node_instance(index) if index >= 0 else null
_check(instance != null and instance.resource_path == "res://player.tscn", "level: Player is an instance of player.tscn")
_check(instance != null and _property(level, index, "position") == Vector2(64, 32), "level: the instance overrides position to (64, 32)")
print("%d of %d checks passed" % [passed, passed + failed])
quit(1 if failed else 0)
func _check(ok: bool, what: String) -> void:
if ok:
passed += 1
print("PASS ", what)
else:
failed += 1
print("FAIL ", what)
func _child_of_root(state: SceneState, child: String) -> StringName:
var i := _index_of_child(state, child)
return state.get_node_type(i) if i >= 0 else &""
func _index_of_child(state: SceneState, child: String) -> int:
for i in state.get_node_count():
if state.get_node_path(i) == NodePath("./" + child):
return i
return -1
func _property(state: SceneState, node: int, property: String) -> Variant:
for p in state.get_node_property_count(node):
if state.get_node_property_name(node, p) == StringName(property):
return state.get_node_property_value(node, p)
return null Here is the checker run on two scenes that meet the task, and on a level whose Player was added as a plain
CharacterBody2D instead of an instance:
from session import files, run
# The checker of the practice task, run on two scenes that meet the task and on a level whose Player is not an instance.
files("practice=.")
run("""
godot --headless --quiet --import
godot --headless --no-header --script check_scenes.gd -- level.tscn
!godot --headless --no-header --script check_scenes.gd -- level_without_instance.tscn
""") Output
$ godot --headless --quiet --import $ godot --headless --no-header --script check_scenes.gd -- level.tscn PASS player.tscn: the root is a CharacterBody2D named Player PASS player.tscn: a Sprite2D named Sprite under the root PASS player.tscn: a CollisionShape2D named Hitbox under the root PASS level: the root is a Node2D named Level PASS level: Player is an instance of player.tscn PASS level: the instance overrides position to (64, 32) 6 of 6 checks passed $ godot --headless --no-header --script check_scenes.gd -- level_without_instance.tscn PASS player.tscn: the root is a CharacterBody2D named Player PASS player.tscn: a Sprite2D named Sprite under the root PASS player.tscn: a CollisionShape2D named Hitbox under the root PASS level: the root is a Node2D named Level FAIL level: Player is an instance of player.tscn FAIL level: the instance overrides position to (64, 32) 4 of 6 checks passed [exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 check_session.py
Every line says what it checked, and the exit status is 1 when any check fails, so the checker also works in a build
script. Your output should end with 6 of 6 checks passed. Then go over the four parts of this page once more;
each question explains its answer as soon as you choose, starting from the part you have got wrong most often:
Practice that adapts to you
Practise this lesson
8 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up: what is the difference between a node and a scene in Godot?
A node is a single building block with one job, such as a Sprite2D that draws a picture or a Camera2D that
decides what the screen shows; it has a name, properties and children. A scene is a tree of nodes with one root,
saved to a file such as player.tscn, that you can instance as often as you like: in the editor an instance looks
like one node, with the scene’s nodes inside. A running game is itself one big tree, the scene tree, with a Window
called root at the top, so every node has a path such as /root/Player/Camera. In short: nodes are the parts,
scenes are the saved, reusable assemblies of parts.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
A designer recoloured coin.tscn, and 37 of the 40 coins in a level changed, but 3 kept the old colour. Nobody edited the coins' scripts. Why did those 3 not change, how do you find them quickly, and how do you fix them without losing anything else they were meant to keep?
-
Mid to senior
A game needs 30 enemy types that share movement and health but differ in sprite, speed and hit points. Would you use one enemy scene with overrides on each instance, an inherited scene per type, or 30 separate scenes? Defend your choice, and say what happens when the shared part changes.
Key takeaways
- A node does one job and has a name, properties and children; a scene is a tree of nodes with one root, and in a
running game every node has a path from
/root, such as/root/Player/Camera. - An instance takes all its properties from its scene except its overrides, which survive changes to the scene and disappear when you revert them.
- A
.tscnfile lists external resources and nodes and stores only properties that differ, from the defaults or from the instanced scene, plus aunique_idper node since 4.6. - Inherited scenes save only their differences from a base and follow its changes, and editable children let one instance change its inner nodes; neither touches the source scene.
Terms in this lesson
- editable children
- An option on one instance that shows its inner nodes in the scene holding it, so they can be changed for that instance alone without editing the instanced scene.
- inherited scene
- A scene built on a base scene with Scene > New Inherited Scene. It saves only its differences from the base and follows every other change made to the base.
- instance
- A copy of a saved scene placed inside another scene. It takes every property from its scene except the ones changed on it, its overrides, which survive later changes to the scene.
- node
- A building block of a Godot game with one job, such as drawing a picture or following the player with a camera. Every node has a name, properties and callbacks, and it can have child nodes.
- scene
- A tree of nodes with a single root node, saved to a file such as player.tscn so that it can be instanced as often as needed.
- scene tree
- The one tree of nodes of a running game, with a Window named root at the top. Every node in it has a path from the top, such as /root/Player/Camera.
References
- Nodes and scenes (Godot Engine)
- Creating instances (Godot Engine)
- TSCN file format (Godot Engine)
- PackedScene class reference (Godot Engine)
- SceneState class reference (Godot Engine)
- Node class reference: add_child and print_tree_pretty (Godot Engine)
- Godot 4.6 release page (unique node IDs) (Godot Engine)
- Project organization (naming conventions) (Godot Engine)
Report a problem with this lesson
Kept only in this browser. Your Learn progress