All lessons
Lesson 14

Multiple Levels

One script, three scenes. Each level fills in where to go next, so the same code sends you somewhere different.

Loading the game engine. This takes a moment the first time.

One script, three scenes. The same file is attached to all three, so the code exists in one place. What makes the levels behave differently is the value each scene stores in next_level_path: a script can be shared, but every scene keeps its own copy of the @export values you fill in.

The scenes

UI node · 2D node · % unique name · .tscn instanced scene

level_1.tscn
  • Level1 Node2D level_base.gd
  • LevelPlayer CharacterBody2D player.tscn
  • GoalArea Area2D %
  • ColorRect
  • CollisionShape2D
  • HUD CanvasLayer hud.tscn
hud.tscn
  • HUD CanvasLayer hud.gd
  • MarginContainer
  • LevelLabel Label %
  • HomeButton Button %
level_2.tscn
  • Level2 Node2D level_base.gd
  • LevelPlayer CharacterBody2D player.tscn
  • GoalArea Area2D %
  • ColorRect
  • CollisionShape2D
  • Wall StaticBody2D
  • CollisionShape2D
  • Visual ColorRect
  • HUD CanvasLayer hud.tscn
level_3.tscn
  • Level3 Node2D level_base.gd
  • LevelPlayer CharacterBody2D player.tscn
  • GoalArea Area2D %
  • ColorRect
  • CollisionShape2D
  • Wall1 StaticBody2D
  • CollisionShape2D
  • Visual ColorRect
  • Wall2 StaticBody2D
  • CollisionShape2D
  • Visual ColorRect
  • HUD CanvasLayer hud.tscn
player.tscn
  • LevelPlayer CharacterBody2D player.gd
  • Sprite2D
  • CollisionShape2D
extends Node2D

## Which scene to load when the player reaches the goal.
## Leave this EMPTY on the last level. Empty means "you finished them all".
@export_file("*.tscn") var next_level_path: String = ""

func _ready() -> void:
	# GoalArea is the green zone. We put the name "_on_goal_reached" inside
	# ".connect()". That is the function Godot runs when it gets touched.
	%GoalArea.body_entered.connect(_on_goal_reached)

# "body" is whatever touched the goal.
func _on_goal_reached(body: Node2D) -> void:
	# "LevelPlayer" is the class_name at the top of player.gd.
	if body is LevelPlayer:
		# An empty path means there is no next level, so this was the last one.
		if next_level_path != "":
			# Throw this whole scene away and load the next one. Anything not
			# saved somewhere outside the scene is gone for good.
			get_tree().change_scene_to_file(next_level_path)
		else:
			# The last level is done. hud.gd connects to "goal_reached" and
			# puts the finish message on screen.
			GameEvents.goal_reached.emit()