Lesson 13

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.

New code in this lesson

None of the earlier lessons use these. Each one shows the line where it appears here.

@export_file

Like @export, but the Inspector shows a file picker, so you choose a scene instead of typing its path.

level_base.gd
@export_file("*.tscn") var next_level_path: String = ""

The scenes

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

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

FileSystem

  • level_1.tscn
  • level_base.gd
  • hud.tscn
  • hud.gd
  • level_2.tscn
  • level_3.tscn
  • player.tscn
  • player.gd

game_events.gd

Switch it on once, under Project > Project Settings, on the Globals tab. Not made yet? Press Create Script to make it right there. Already made it? Press Select Script/Scene, pick it, and press Add. Its Name column should say GameEvents, which Godot fills in for you. That's the name your code uses.

The code

extends Node2D

@onready var goal_area: Area2D = %GoalArea

## 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.
	goal_area.body_entered.connect(_on_goal_reached)

# "body" is whatever touched the goal.
func _on_goal_reached(body: Node2D) -> void:
	# "Player" is the class_name at the top of player.gd.
	if body is Player:
		# 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()