Menu
CoddyTech

Declaring and Emitting

Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 36 of 65.

Declare a signal with the keyword signal and a name, at the top of the class next to its variables. A signal name describes an event that already happened, in snake_case: died, door_opened, leveled_up. A class declares as many signals as it needs:

# player.gd
class_name Player
extends RefCounted

signal leveled_up
signal max_level_reached

const MAX_LEVEL := 3
var level := 1
var xp := 0

func add_xp(amount: int) -> void:
	xp += amount
	while xp >= 100 and level < MAX_LEVEL:
		xp -= 100
		level += 1
		leveled_up.emit()
		if level == MAX_LEVEL:
			max_level_reached.emit()

Emit a signal at the moment its event happens, and only then. add_xp(50) on a new player emits nothing. add_xp(250) after it brings xp to 300: leveled_up is emitted twice, once per level gained, and max_level_reached once, on the level-up that reaches level 3.

A property setter is a good place to emit, because the signal then fires whatever code changes the value:

signal died

var hp: int = 10:
	set(value):
		var was_alive := hp > 0
		hp = maxi(value, 0)
		if was_alive and hp == 0:
			died.emit()

was_alive keeps died from being emitted again when a hero with 0 HP is hit once more.

A signal can also be reached through its name as text: emit_signal("died") emits it, hero.connect("died", _on_hero_died) connects to it, and hero.has_signal("died") returns true. Connecting to a name the object does not declare is an error when that line runs.

challenge icon

Challenge

Easy

Write a Bomb that counts down and announces each step with signals.

  • Declare two signals: beeped and exploded.
  • tick() lowers fuse by 1. If the fuse is still above 0, emit beeped; if it has reached 0, emit exploded.
  • Once the fuse is 0, the bomb has exploded: further ticks do nothing and emit nothing.

The supplied code reads the starting fuse and how many ticks to run, connects to both signals by name and prints Beep and BOOM! from the connected functions, then the remaining fuse. For a fuse of 3 and 5 ticks it prints:

Beep
Beep
BOOM!
Fuse: 0

Your code goes in bomb.gd. main.gd holds the supplied input/output code and cannot be edited.

Try it yourself

extends Node

func _ready():
	# Supplied input/output code: keep it as it is
	var bomb := Bomb.new(int(OS.read_string_from_stdin()))
	# connect() with the signal's name as text
	bomb.connect("beeped", _on_beeped)
	bomb.connect("exploded", _on_exploded)
	var ticks := int(OS.read_string_from_stdin())
	for i in ticks:
		bomb.tick()
	print("Fuse: ", bomb.fuse)

func _on_beeped() -> void:
	print("Beep")

func _on_exploded() -> void:
	print("BOOM!")
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online GDScript compiler