Signaux Godot pour debutants : creer un Menu Play Quit et faire reagir un Label
Formations

Signaux Godot pour debutants : creer un Menu Play Quit et faire reagir un Label

Antharuu Antharuu
9 min de lecture
godot 4 gdscript tutoriel godot hud godot signaux godot ui godot button pressed godot connecter un signal godot timer timeout godot menu godot développement jeu vidéo

Vous en etes la : vous avez une scene principale avec un Player et un HUD, tout est bien en place... mais c'est encore un peu le calme plat (rien ne reagit, rien ne repond). Et c'est justement la que les signaux entrent en scene : c'est ce qui transforme une interface "statique" en jeu qui ecoute et reagit. Accrochez-vous, on va voir ca ensemble, tranquillement, et surtout en testant a chaque etape.


1) Contexte rapide (ou on en est)

Vous avez deja :

  • une scene Main.tscn (souvent Node2D ou Control en racine),
  • un noeud Player (immobile pour l'instant, et c'est ok),
  • un noeud HUD (avec au moins un Label).

Ce qu'il manque, c'est le "clic" (au sens propre) : un menu, un bouton, une reaction visible. Et ca, c'est exactement le job des signaux.


2) Objectifs du module (clairs et mesurables)

A la fin de ce module, vous saurez :

  1. Expliquer ce qu'est un signal dans Godot (et pourquoi c'est utile).
  2. Creer un premier bouton Play dans une scene de menu simple.
  3. Connecter un signal pressed() d'un Button depuis l'editeur.
  4. Reagir a ce signal avec une action verifiable (print puis changement de Label).
  5. Connecter un signal par code avec .connect(...) (optionnel, mais tres utile).
  6. Utiliser un Timer et son signal timeout() pour comparer (bonus).
  7. Verifier votre scene avec une checklist finale + un mini quiz (pour etre sur que tout marche).

3) Mini glossaire (simple, sans jargon)

  • Signal : un evenement emis par un noeud (ex : "on a clique", "le timer a fini").
  • Emettre : le noeud annonce "il vient de se passer X".
  • Ecouter : un autre noeud dit "quand X arrive, je veux etre prevenu".
  • Connecter : relier un signal a une methode pour que Godot l'appelle au bon moment.
  • Recepteur (receiver) : le noeud/script qui recoit le signal et reagit.
  • Callback / methode : la fonction appelee quand le signal arrive (souvent _on_X_pressed()).
  • Decouplage : deux noeuds collaborent sans se connaitre trop intimement (plus propre, plus flexible).
  • @onready : permet de recuperer un noeud une fois la scene prete (evite des null).

4) Comprendre "emettre" vs "ecouter" (analogie simple)

Imaginez une sonnette chez vous.

  • Le bouton de sonnette, c'est un noeud qui emet un evenement : "quelqu'un a appuye".
  • Vous, dans la maison, vous ecoutez cette sonnette : quand ca sonne, vous faites quelque chose (ouvrir, parler, ignorer...).
  • La connexion entre la sonnette et votre reaction, c'est le fait de dire : "quand ca sonne, appelle cette action".

Dans Godot c'est pareil :

  • Le Button emet le signal pressed().
  • Votre script ecoute le signal.
  • Quand le signal est emis, Godot appelle votre methode.

L'avantage : le bouton n'a pas besoin de connaitre toute votre logique de jeu. Il se contente d'emettre "pressed". Et vous, vous decidez quoi faire.


5) Pas a pas guide (avec checkpoints)

Etape 1 : Creer une scene de menu dediee (Menu.tscn)

  1. Scene > New Scene
  2. Choisissez Control en racine (ideal pour l'UI).
  3. Renommez la racine en Menu
  4. Sauvegardez : res://Menu.tscn

Checkpoint

  • Vous avez Menu.tscn avec un noeud racine Menu (Control).

Etape 2 : Ajouter un bouton "Play"

  1. Clic droit sur Menu > Add Child Node...
  2. Ajoutez un Button
  3. Renommez-le Play
  4. Dans l'Inspector :
    • Text : Play
    • (optionnel) ajustez position/taille pour le voir facilement

Optionnel (mais pratique) : ajoutez un Label titre, genre Mon Premier Menu !.

Hierarchie typique :

Menu (Control)
├── TitleLabel (Label)   (optionnel)
└── Play (Button)

Checkpoint

  • Le bouton Play est visible dans la scene (dans l'editeur).

Etape 3 : Ajouter un Label pour un retour visuel (recommande)

Un print() dans l'Output, c'est bien. Mais voir un texte changer a l'ecran, c'est encore mieux pour un debutant.

  1. Sous Menu, ajoutez un Label
  2. Renommez-le StatusLabel
  3. Texte initial : Appuyez sur Play

Hierarchie :

Menu (Control)
├── TitleLabel (Label)      (optionnel)
├── Play (Button)
└── StatusLabel (Label)

Checkpoint

  • StatusLabel existe et affiche "Appuyez sur Play" dans l'editeur.

Etape 4 : Ajouter un script au Menu

  1. Clic droit sur Menu > Attach Script
  2. Enregistrez : res://Menu.gd
  3. Gardez extends Control

Vous avez un squelette du genre :

extends Control

func _ready():
	pass

Checkpoint

  • Menu.gd est attache a Menu.

Etape 5 : Connecter pressed() depuis l'editeur (methode visuelle)

Vous vous demandez peut-etre "ou sont les signaux dans Godot ?" C'est dans l'onglet Node (a cote de Inspector).

  1. Selectionnez le noeud Play (le bouton)
  2. A droite, ouvrez l'onglet Node
  3. Dans la liste des signaux, double-cliquez sur pressed()
  4. Dans la fenetre :
    • Receiver : Menu
    • Methode : laissez Godot proposer _on_play_pressed (ou similaire)
  5. Cliquez Connect

Godot ajoute automatiquement une fonction dans Menu.gd.

Checkpoint

  • Vous voyez une methode _on_play_pressed() (ou proche) dans Menu.gd.
  • Le signal pressed() est connecte (dans l'onglet Node, vous voyez la connexion).

6) Code par petits blocs (et test a chaque bloc)

Bloc 1 : Reaction simple avec print

Dans Menu.gd, completez la methode creee par Godot :

extends Control

func _on_play_pressed():
	print("Game started")

Pourquoi on commence par print ?

  • C'est le test le plus simple : si vous voyez le message dans l'Output, le signal est bien connecte.
  • Ensuite seulement, on ajoute des effets plus "visuels".

Test

  1. Sauvegardez Menu.tscn
  2. Pour tester, il faut l'afficher depuis Main.tscn (etape suivante), ou lancer Menu.tscn directement si vous la mettez en scene principale temporairement.

Checkpoint

  • Quand vous cliquez sur Play, vous voyez Game started dans l'onglet Output.

Etape 6 : Instancier Menu dans Main pour un test "reel"

Comme votre contexte dit que Main.tscn charge deja Player et HUD, on va juste ajouter le menu en plus pour le moment.

Dans Main.tscn :

  1. Ouvrez Main.tscn
  2. Ajoutez Menu.tscn en enfant (glisser-deposer Menu.tscn dans la hierarchie, ou Instance Child Scene)
  3. Lancez Main.tscn (F6)

Checkpoint

  • Le menu s'affiche dans le jeu.
  • Cliquer sur Play affiche Game started dans Output.

Bloc 2 : Changer un Label (plus visible qu'un print)

Maintenant on veut une reaction a l'ecran, pas seulement dans la console.

Dans Menu.gd, on recupere StatusLabel et on change son texte au clic :

extends Control

@onready var status_label = $StatusLabel

func _on_play_pressed():
	status_label.text = "Game started"
	print("Game started")

Note sur @onready :

  • Sans @onready, vous risquez de lire $StatusLabel trop tot (avant que la scene soit prete).
  • Avec @onready, Godot initialise la variable au bon moment.

Test

  • Lancez, cliquez Play.

Checkpoint

  • Le texte du label change quand vous cliquez.
  • Le print("Game started") apparait toujours.

7) Bonus : comparer avec un Timer (signal automatique)

Un bouton, c'est l'utilisateur qui declenche. Un Timer, c'est le jeu qui declenche tout seul (et c'est tres utile pour des cooldowns, des clignotements, des spawns, etc).

Etape Timer : Ajouter un Timer et connecter timeout()

Dans Menu.tscn :

  1. Ajoutez un Timer sous Menu
  2. Renommez-le DemoTimer
  3. Dans l'Inspector :
    • Wait Time : 2.0
    • Autostart : On

Connectez timeout() :

  1. Selectionnez DemoTimer
  2. Onglet Node
  3. Double-clic sur timeout()
  4. Connectez au Menu

Dans Menu.gd, ajoutez :

func _on_demo_timer_timeout():
	status_label.text = "Timer tick... " + str(Time.get_time_dict_from_system().second)

Test

  • Lancez la scene, observez le label (il change toutes les 2 secondes).

Checkpoint

  • Sans cliquer, le label change tout seul (toutes les 2s).

8) Connecter un signal via le code (quand vous voulez du dynamique)

La connexion par l'editeur, c'est parfait pour debuter (et souvent suffisant). Mais si vous instanciez des scenes a la volee, ou si vous voulez centraliser la logique dans le script, vous pouvez connecter par code.

Dans Menu.gd, vous pouvez connecter dans _ready() :

extends Control

@onready var status_label = $StatusLabel
@onready var play_button = $Play

func _ready():
	play_button.pressed.connect(_on_play_pressed)

func _on_play_pressed():
	status_label.text = "Game started"
	print("Game started")

Attention :

  • Si vous aviez deja connecte pressed() via l'editeur, vous risquez d'appeler la methode deux fois.
  • Choisissez une seule methode de connexion pour eviter les surprises.

Checkpoint

  • Le clic appelle la methode une seule fois (pas de double print).

9) Erreurs frequentes (si tu vois X, c'est surement Y)

  • Tu cliques, rien ne se passe
    • souvent : signal non connecte, ou vous testez une autre scene que celle modifiee, ou vous n'avez pas lance Main.tscn.
  • Erreur "Invalid get index" / null
    • souvent : $StatusLabel n'existe pas, mauvais nom, ou vous avez oublie @onready.
  • La fonction ne se declenche pas
    • souvent : vous avez connecte pressed() puis vous avez renomme le bouton, ou le script n'est pas sur le bon noeud.
  • Ca se declenche deux fois
    • souvent : connecte via l'editeur + via code en meme temps.
  • Le menu disparait derriere
    • souvent : ordre d'affichage UI / Control mal ancre (pas bloquant ici, mais a garder en tete).

10) Exercices (1 facile + 1 challenge)

Exercice facile : "Play" affiche "Game started" dans Output

Objectif :

  • Au clic sur Play, faire :
    • print("Game started")

Critere de reussite :

  • Vous voyez le message dans Output a chaque clic.

Challenge : ajouter un bouton "Quit" ou "Options"

Ajoutez un second bouton sous Play.

Option A (desktop) : Quitter le jeu

  1. Bouton : Quit
  2. Connectez pressed()
  3. Code :
func _on_quit_pressed():
	get_tree().quit()

Option B (placeholder) : Options

func _on_options_pressed():
	status_label.text = "Options : bientot implemente !"

Bonus (si vous etes chaud) : afficher/masquer un Panel d'options (meme vide), juste pour pratiquer le "toggle".


11) Recap + checklist (ce qui doit etre vrai a la fin)

Ce que vous avez fait, c'est simple, mais c'est un enorme pas : vous avez une scene UI qui reagit sans que tout le projet soit en spaghetti.

Checklist finale :

  • Menu.tscn existe (racine Control)
  • Play (Button) existe et est cliquable
  • pressed() est connecte (editeur ou code)
  • Un clic affiche print("Game started")
  • (Recommande) Un clic change le texte de StatusLabel
  • Bonus : un Timer emet timeout() et met a jour le label
  • Vous savez reperer les erreurs classiques (signal pas connecte, mauvais chemin, double connexion)

Mini quiz (2 minutes, pour verifier)

  1. Un signal dans Godot, c'est plutot :

    • A) une variable
    • B) un evenement emis par un noeud
    • C) un fichier de configuration
  2. Qui "emet" pressed() ?

    • A) le script du Menu
    • B) le Button
    • C) le HUD
  3. Que fait une connexion de signal ?

    • A) Elle renomme automatiquement vos noeuds
    • B) Elle dit a Godot quelle methode appeler quand l'evenement arrive
    • C) Elle lance la scene principale

(Reponses : 1B, 2B, 3B)


12) Pont vers le module suivant (sans spoiler)

Maintenant que votre jeu sait "ecouter" et "reagir", la suite logique, c'est de brancher ces signaux sur du concret : afficher/mettre a jour le HUD, declencher le mouvement du Player, et organiser proprement le passage "Menu -> Jeu". Bref, on passe de l'interface qui clique a l'action qui joue (et c'est vraiment le moment ou le projet prend vie).

Articles similaires