Événements & Interactions

Objectif : Faire réagir ton jeu aux actions des joueurs ! Touches, clics, collisions... Ton monde devient interactif grâce aux événements.

Tout est Événement

La base de l'interactivité

Un joueur touche une pièce ? elle disparaît. Il clique sur un bouton ? une porte s'ouvre. Tout ça, c'est grâce aux événements. Ce sont des signaux que Roblox envoie quand quelque chose se passe, et toi tu décides comment réagir !

1. Se Connecter aux Événements

En Luau, on écoute un événement avec la méthode :Connect(). Quand l'événement se produit, la fonction associée s'exécute automatiquement.

1.1 Syntaxe de Base

Structure d'une connexion

-- L'objet qui a l'événement
local part = script.Parent

-- On se connecte à l'événement "Touched"
part.Touched:Connect(function(autreObjet)
    print("Quelqu'un m'a touché !")
end)
Décryptage

part.Touched = L'événement "touché" de la Part
:Connect() = Branche une fonction à exécuter
function(autreObjet) = La fonction reçoit l'objet qui a touché

1.2 Événements Courants

.Touched

Se déclenche quand quelque chose touche l'objet.

part.Touched:Connect(function(hit) ... end)
.MouseClick

Se déclenche quand on clique sur un ClickDetector.

clickDetector.MouseClick:Connect(function(player) ... end)
.PlayerAdded

Se déclenche quand un joueur rejoint la partie.

game.Players.PlayerAdded:Connect(function(player) ... end)
.Changed

Se déclenche quand une propriété change.

part:GetPropertyChangedSignal("Color"):Connect(...)

2. Le Debounce (Anti-Spam)

Problème : quand un joueur touche une Part, l'événement .Touched peut se déclencher des dizaines de fois par seconde ! Pour éviter ça, on utilise une technique appelée debounce.

Sans debounce = CHAOS

-- ? MAUVAIS : Se déclenche 50x par seconde !
part.Touched:Connect(function(hit)
    player.leaderstats.Coins.Value += 1  -- Le joueur devient millionnaire
end)

Avec debounce = PARFAIT ?

local debounce = false  -- Variable de contrôle

part.Touched:Connect(function(hit)
    if debounce then return end  -- Si déjà en cours, on sort
    debounce = true              -- On bloque
    
    -- TON CODE ICI
    print("Touché UNE fois !")
    player.leaderstats.Coins.Value += 1
    
    task.wait(1)                 -- Attente de 1 seconde
    debounce = false             -- On débloque
end)

Le Pattern Debounce

1. Crée une variable debounce = false
2. Au début de la fonction, vérifie if debounce then return end
3. Met debounce = true pour bloquer
4. Fais ton action
5. Attends avec task.wait()
6. Remet debounce = false

3. ClickDetector & ProximityPrompt

Pour des interactions plus précises, Roblox propose des outils dédiés.

3.1 ClickDetector

Ajoute un ClickDetector dans une Part pour la rendre cliquable. Le curseur change automatiquement quand on passe dessus.

Bouton cliquable

local bouton = script.Parent
local clickDetector = bouton:FindFirstChild("ClickDetector")

clickDetector.MouseClick:Connect(function(joueur)
    print(joueur.Name .. " a cliqué sur le bouton !")
    
    -- Change la couleur du bouton
    bouton.BrickColor = BrickColor.Random()
end)

3.2 ProximityPrompt

Le ProximityPrompt affiche une invite quand le joueur est proche. C'est la méthode moderne et recommandée pour les interactions.

Propriétés Clés
  • ActionText = Texte affiché ("Ouvrir")
  • ObjectText = Nom de l'objet ("Coffre")
  • KeyboardKeyCode = Touche (E par défaut)
  • MaxActivationDistance = Distance max
Avantages
  • Interface native et moderne
  • Fonctionne sur mobile (bouton)
  • Temps de maintien configurable
  • Cooldown intégré

Interaction avec ProximityPrompt

local coffre = script.Parent
local prompt = coffre:FindFirstChild("ProximityPrompt")

prompt.Triggered:Connect(function(joueur)
    print(joueur.Name .. " ouvre le coffre !")
    
    -- Donne une récompense
    joueur.leaderstats.Coins.Value += 100
    
    -- Désactive le prompt (coffre vide)
    prompt.Enabled = false
end)
📱 Mobile-Friendly

Contrairement au ClickDetector, le ProximityPrompt fonctionne parfaitement sur mobile avec un bouton tactile. Utilise-le en priorité !

4. Détecter le Joueur

Quand quelque chose touche une Part, c'est souvent une pièce du personnage (bras, jambe...). Comment savoir si c'est un joueur et récupérer ses infos ?

Pattern de détection complet

local piece = script.Parent

piece.Touched:Connect(function(hit)
    -- hit = la partie qui a touché (ex: "RightFoot")
    
    -- Cherche le personnage (Model parent)
    local character = hit.Parent
    
    -- Cherche l'Humanoid (preuve que c'est un personnage)
    local humanoid = character:FindFirstChild("Humanoid")
    
    if humanoid then
        -- C'est bien un joueur !
        local player = game.Players:GetPlayerFromCharacter(character)
        
        if player then
            print(player.Name .. " a touché la pièce !")
            -- Accède aux leaderstats, etc.
            player.leaderstats.Coins.Value += 10
            piece:Destroy()
        end
    end
end)
Hiérarchie du Personnage

hit ? La Part touchée (ex: RightFoot)
hit.Parent ? Le Model du personnage
Humanoid ? Composant qui prouve que c'est un personnage
GetPlayerFromCharacter() ? Récupère l'objet Player

💻 Sandbox Luau
Simulateur v2.0
1 2 3 4 5 6 7 8 9 10
👉 Clique sur Exécuter pour tester le debounce...

Quiz : Événements & Interactions

5 questions pour valider tes acquis

1. Quelle méthode permet de brancher une fonction à un événement ?

  • :Bind()
  • :Connect()
  • :Link()
  • :Attach()

2. À quoi sert le pattern "debounce" ?

  • Accélérer le code
  • Éviter que l'événement se déclenche trop souvent
  • Connecter plusieurs événements
  • Créer des animations

3. Quel événement détecte un clic sur un ClickDetector ?

  • .Clicked
  • .MouseClick
  • .OnClick
  • .Touched

4. Quelle méthode récupère le Player depuis un Character ?

  • game.Players:FindPlayer()
  • game.Players:GetPlayer()
  • game.Players:GetPlayerFromCharacter()
  • character:GetPlayer()

5. Quel composant prouve qu'un Model est un personnage ?

  • Player
  • Character
  • Humanoid
  • Script
Challenge Code

Connecte l'Événement

Complète ce script pour qu'il affiche un message quand un joueur touche la Part.

15-50 Points
TouchEvent.lua
-- Récupère la zone de soin (Part avec ce script)
local zoneHeal = script.Parent
-- Fonction appelée quand un joueur touche la zone
local function (autreObjet)
  local humanoid = autreObjet.Parent:("Humanoid")
  if humanoid then
    humanoid. = 100 -- Soigne le joueur à 100%
  end
end
-- Connecte l'événement Touched à la fonction
zoneHeal.:Connect(soigner)
🚪
Étape 6/10

Portes Automatiques

Les portes s'ouvrent automatiquement mais consomment de l'énergie. Chaque ouverture coûte 2 ? ! Sans énergie, elles restent bloquées !

1
2
3
4
5
6
7
8
9
10
Prérequis

Modules 1 à 5 complétés (événements Touched/TouchEnded)

Construction des Portes

1
Préparer l'Ouverture (Le Cadre)

Actuellement, la station est une boîte fermée. Il faut percer le mur !
Dans l'Explorer, supprime Mur_Sud (Sélectionne et appuie sur Suppr/Del).

Remplace-le par ces 3 murs pour créer un cadre de porte :

Mur_Sud_Gauche25, 15, 2 | Pos: -17.5, 8.5, 30
Mur_Sud_Droit25, 15, 2 | Pos: 17.5, 8.5, 30
Mur_Sud_Haut (Linteau)10, 3, 2 | Pos: 0, 14.5, 30

N'oublie pas de cocher Anchored pour chaque mur !

2
Crée la Porte

Crée une Part qui bouchera le trou. Elle doit être légèrement plus fine que les murs.

Size8, 12, 1
Position0, 8, 30
MaterialMetal
ColorMedium stone grey
Anchored✓ Coché
Nom"PorteAuto"
3
Crée la Zone de Détection

Crée une Part invisible qui servira de "tapis sensible" devant et derrière la porte.

Size10, 1, 14
Position0, 2.5, 30
Transparency 1 (invisible) ou 0.8 (pour tester)
CanCollide✗ Décoché (Très important!)
Anchored✓ Coché
Nom"ZoneDetection"

💡 La zone doit traverser le mur pour qu'on puisse l'activer des deux côtés.

4
Script avec Événements

Insère un Script dans ZoneDetection (pas dans la porte !). Renomme-le ScriptPorte.

À toi de coder !
1. Crée les variables : zone (script.Parent), porte (workspace:WaitForChild("PorteAuto"))
2. Stocke positionFermee (porte.Position) et calcule positionOuverte (positionFermee + Vector3.new(0, 10, 0))
💡 Utilise Vector3.new(0, 12, 0) pour monter de 12 studs
3. Connecte l'événement Touched : vérifie si c'est un joueur, puis ouvre la porte
💡 game.Players:GetPlayerFromCharacter(hit.Parent) retourne le joueur
4. Connecte l'événement TouchEnded : attends 1s puis ferme la porte
💡 N'oublie pas task.wait(1) pour le délai !
🔒
Solution verrouillée
Utilise les indices ci-dessus et ce que tu as appris sur les événements !
5
Crée le Sas Extérieur

La porte mène vers le vide spatial ! Pour éviter de tomber, construis un petit sas juste derrière la porte.

Sol_Sas10, 2, 20 | Pos: 0, 1, 40
Mur_Sas_Gauche1, 15, 20 | Pos: -4.5, 8.5, 40
Mur_Sas_Droit1, 15, 20 | Pos: 4.5, 8.5, 40
Plafond_Sas10, 1, 20 | Pos: 0, 15.5, 40

Ce couloir te permettra de sortir sans tomber dans le vide infini !

6
Teste ta Porte

Approche-toi de la zone : la porte monte ! Éloigne-toi : elle redescend après 1 seconde. Marche dans le sas pour admirer l'espace.

Bonus : Porte Coulissante

Au lieu de monter, fais-la glisser sur le côté avec Vector3.new(8, 0, 0) pour un effet de porte Star Wars !

🎉

Portes automatiques installées !

Prochaine étape ? Module 7 : Système Multijoueur

🚪
🚀 SURVIE SPATIALE - Étape 6/10

Système de Portes Sécurisées

Les portes de la station consomment de l'⚡ Énergie pour s'ouvrir ! Sans énergie, impossible de passer. Utilise les événements pour créer un système de portes réactif et intelligent.

1
2
3
4
5
6
7
8
9
10
Contexte : Ta station a un réacteur et une zone de collecte. Maintenant, il faut des portes automatiques qui consomment de l'énergie pour s'ouvrir. Sans énergie, les portes restent bloquées !
1
📐 Architecture du Système de Portes

Chaque porte est composée de plusieurs éléments. Voici la structure à créer pour une porte :

▼ Station
▼ 📦 PorteReacteur (nouveau!)
🧱 Cadre_Gauche
🧱 Cadre_Droit
🧱 Cadre_Haut
🚪 Porte_Gauche
🚪 Porte_Droite
👁️ ZoneDetection
💡 Indicateur
📜 ControleurPorte
Portes coulissantes : Contrairement au projet V1 (porte qui monte), nous allons créer des portes qui s'ouvrent sur les côtés, style Star Wars ! Plus immersif pour une station spatiale.
2
🏗️ Créer le Cadre de Porte

Crée un Model nommé PorteReacteur entre le Hub et la SalleReacteur. Ajoute les 3 parties du cadre :

Cadre_Gauche

Size1, 10, 3
MaterialDiamondPlate
Color[60, 60, 70]
Anchored

Cadre_Droit (même chose, autre côté)

Cadre_Haut (linteau)

Size8, 2, 3
MaterialDiamondPlate
3
🚪 Créer les Deux Battants

Les portes coulissantes ont 2 battants qui glissent dans le mur. Crée Porte_Gauche :

NamePorte_Gauche
Size3, 8, 0.5
MaterialMetal
Color[80, 80, 90]
Anchored

Duplique (Ctrl+D) pour créer Porte_Droite et place-la de l'autre côté.

Positionnement : Les deux portes doivent se toucher au milieu quand elles sont fermées. Utilise l'outil Move avec précision !
4
💡 Indicateur + Zone de Détection

L'Indicateur montre si la porte peut s'ouvrir (énergie suffisante). La ZoneDetection détecte les joueurs qui approchent.

Indicateur (au-dessus de la porte)

NameIndicateur
ShapeCylinder
Size0.3, 1, 1
MaterialNeon
Color[0, 255, 100]

ZoneDetection (invisible, devant/derrière la porte)

NameZoneDetection
Size10, 8, 8
Transparency1
CanCollide✗ (false)
Anchored
5
📜 Script ControleurPorte avec Événements

Crée un Script dans le Model PorteReacteur. Ce script utilise les événements Touched/TouchEnded du cours :

-- ControleurPorte.lua -- Gère l'ouverture/fermeture avec consommation d'énergie local modele = script.Parent local porteGauche = modele:WaitForChild("Porte_Gauche") local porteDroite = modele:WaitForChild("Porte_Droite") local zone = modele:WaitForChild("ZoneDetection") local indicateur = modele:WaitForChild("Indicateur") -- Configuration local ENERGIE_PAR_OUVERTURE = 5 local DISTANCE_OUVERTURE = 3 -- Studs de décalage -- États local estOuverte = false local enMouvement = false local joueursProches = 0 -- Positions d'origine (fermées) local posGaucheFermee = porteGauche.Position local posDroiteFermee = porteDroite.Position -- FONCTION : Vérifier l'énergie disponible local function getEnergie() local reacteur = workspace:FindFirstChild("Station") and workspace.Station:FindFirstChild("SalleReacteur") and workspace.Station.SalleReacteur:FindFirstChild("Reacteur") if reacteur then local energie = reacteur:FindFirstChild("Energie") if energie then return energie.Value end end return 100 -- Défaut si pas de réacteur end -- FONCTION : Consommer de l'énergie local function consommerEnergie(quantite) local reacteur = workspace.Station.SalleReacteur:FindFirstChild("Reacteur") if reacteur and reacteur:FindFirstChild("Energie") then reacteur.Energie.Value = reacteur.Energie.Value - quantite end end -- FONCTION : Mettre à jour l'indicateur local function updateIndicateur() if getEnergie() >= ENERGIE_PAR_OUVERTURE then indicateur.Color = Color3.fromRGB(0, 255, 100) -- Vert else indicateur.Color = Color3.fromRGB(255, 50, 50) -- Rouge end end -- FONCTION : Ouvrir la porte (coulissante) local function ouvrirPorte() if estOuverte or enMouvement then return end if getEnergie() < ENERGIE_PAR_OUVERTURE then warn("⚠️ Énergie insuffisante pour ouvrir!") return end enMouvement = true consommerEnergie(ENERGIE_PAR_OUVERTURE) print("🚪 Porte ouverte (-" .. ENERGIE_PAR_OUVERTURE .. " énergie)") -- Animation simple : déplace les portes for i = 1, 10 do porteGauche.Position = porteGauche.Position - Vector3.new(DISTANCE_OUVERTURE/10, 0, 0) porteDroite.Position = porteDroite.Position + Vector3.new(DISTANCE_OUVERTURE/10, 0, 0) task.wait(0.03) end estOuverte = true enMouvement = false end -- FONCTION : Fermer la porte local function fermerPorte() if not estOuverte or enMouvement then return end enMouvement = true for i = 1, 10 do porteGauche.Position = porteGauche.Position + Vector3.new(DISTANCE_OUVERTURE/10, 0, 0) porteDroite.Position = porteDroite.Position - Vector3.new(DISTANCE_OUVERTURE/10, 0, 0) task.wait(0.03) end -- Repositionne exactement porteGauche.Position = posGaucheFermee porteDroite.Position = posDroiteFermee estOuverte = false enMouvement = false print("🚪 Porte fermée") end -- ÉVÉNEMENT : Joueur entre dans la zone zone.Touched:Connect(function(touche) local joueur = game.Players:GetPlayerFromCharacter(touche.Parent) if joueur then joueursProches = joueursProches + 1 ouvrirPorte() end end) -- ÉVÉNEMENT : Joueur quitte la zone zone.TouchEnded:Connect(function(touche) local joueur = game.Players:GetPlayerFromCharacter(touche.Parent) if joueur then joueursProches = math.max(0, joueursProches - 1) if joueursProches == 0 then task.wait(1.5) -- Délai avant fermeture if joueursProches == 0 then fermerPorte() end end end end) -- Mise à jour régulière de l'indicateur while true do updateIndicateur() task.wait(1) end
Concepts du cours appliqués :
Touched → Détecte quand un joueur entre
TouchEnded → Détecte quand un joueur sort
:Connect(function) → Branche une fonction à un événement
• Compteur de joueurs → Évite de fermer si quelqu'un est encore là
6
⚡ Ajouter l'IntValue Energie au Réacteur

Pour que le système fonctionne, ajoute une IntValue dans le Réacteur pour stocker l'énergie partagée :

  1. Va dans Workspace → Station → SalleReacteur → Reacteur
  2. Clic droit → Insert Object → IntValue
  3. Renomme en Energie
  4. Mets Value = 100
Important : Modifie aussi ton script GestionEnergie du Module 4 pour qu'il utilise cette IntValue au lieu d'une variable locale !
7
🎮 Tester le Système

Lance le jeu avec F5 et teste :

  • 🟢 Indicateur vert → Assez d'énergie, la porte s'ouvre
  • 🔴 Indicateur rouge → Pas assez d'énergie, porte bloquée
  • 🚪 Animation coulissante → Les deux battants glissent
  • ⏱️ Fermeture automatique → 1.5s après ton départ
Bonus : Améliore le Système !
  • Ajoute un Sound d'ouverture/fermeture (whoosh!)
  • Crée plusieurs portes pour toutes les salles de la station
  • Ajoute un Touched sur la porte fermée qui affiche "Énergie insuffisante" au joueur
🚪

Système de portes opérationnel !

Tes portes sont maintenant connectées au système d'énergie ! → Module 7 : Interface utilisateur (HUD) pour afficher les ressources