Objectif : Faire réagir ton jeu aux actions des joueurs ! Touches, clics, collisions... Ton monde devient interactif grâce aux événements.
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 !
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.
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)
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é
Se déclenche quand quelque chose touche l'objet.
part.Touched:Connect(function(hit) ... end)
Se déclenche quand on clique sur un ClickDetector.
clickDetector.MouseClick:Connect(function(player) ... end)
Se déclenche quand un joueur rejoint la partie.
game.Players.PlayerAdded:Connect(function(player) ... end)
Se déclenche quand une propriété change.
part:GetPropertyChangedSignal("Color"):Connect(...)
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)
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
Pour des interactions plus précises, Roblox propose des outils dédiés.
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)
Le ProximityPrompt affiche une invite quand le joueur est proche. C'est la méthode moderne et recommandée pour les interactions.
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)
Contrairement au ClickDetector, le ProximityPrompt fonctionne parfaitement sur mobile avec un bouton tactile. Utilise-le en priorité !
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)
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
5 questions pour valider tes acquis
Les portes s'ouvrent automatiquement mais consomment de l'énergie. Chaque ouverture coûte 2 ? ! Sans énergie, elles restent bloquées !
Modules 1 à 5 complétés (événements Touched/TouchEnded)
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 :
N'oublie pas de cocher Anchored pour chaque mur !
Crée une Part qui bouchera le trou. Elle doit être légèrement plus fine que les murs.
Crée une Part invisible qui servira de "tapis sensible" devant et derrière la porte.
💡 La zone doit traverser le mur pour qu'on puisse l'activer des deux côtés.
Insère un Script dans ZoneDetection (pas dans
la porte !). Renomme-le ScriptPorte.
zone (script.Parent),
porte
(workspace:WaitForChild("PorteAuto"))
positionFermee (porte.Position) et
calcule positionOuverte (positionFermee +
Vector3.new(0, 10, 0))
Touched : vérifie si
c'est un joueur, puis ouvre la porte
TouchEnded : attends
1s puis ferme la porte
La porte mène vers le vide spatial ! Pour éviter de tomber, construis un petit sas juste derrière la porte.
Ce couloir te permettra de sortir sans tomber dans le vide infini !
Approche-toi de la zone : la porte monte ! Éloigne-toi : elle redescend après 1 seconde. Marche dans le sas pour admirer l'espace.
Au lieu de monter, fais-la glisser sur le côté avec
Vector3.new(8, 0, 0) pour un effet de porte Star
Wars !
Prochaine étape ? Module 7 : Système Multijoueur
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.
Chaque porte est composée de plusieurs éléments. Voici la structure à créer pour une porte :
Crée un Model nommé
PorteReacteur entre le Hub et la SalleReacteur.
Ajoute les 3 parties du cadre :
Les portes coulissantes ont 2 battants qui glissent dans le mur.
Crée Porte_Gauche :
Duplique (Ctrl+D) pour créer Porte_Droite et
place-la de l'autre côté.
L'Indicateur montre si la porte peut s'ouvrir (énergie suffisante). La ZoneDetection détecte les joueurs qui approchent.
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
Touched → Détecte quand un joueur entreTouchEnded → Détecte quand un joueur sort:Connect(function) → Branche une fonction à un
événementPour que le système fonctionne, ajoute une IntValue dans le Réacteur pour stocker l'énergie partagée :
EnergieValue = 100GestionEnergie
du Module 4 pour qu'il utilise cette IntValue au lieu d'une
variable locale !
Lance le jeu avec F5 et teste :
Tes portes sont maintenant connectées au système d'énergie ! → Module 7 : Interface utilisateur (HUD) pour afficher les ressources