Apprendre à afficher une bulle de chat au-dessus de la tête du joueur quand il touche une Part, avec un cooldown pour éviter le spam. Ce tutoriel explique :
- Le service
Chatet la fonctionChat:Chat(). - Le tableau de cooldown (avec une nouveauté : ici la clé est le personnage, pas le joueur !).
- La détection de collision avec
Touched. - Au passage : corriger les noms de variables pour qu’ils soient en anglais (bonne pratique de programmeur !).
Introduction : À quoi sert ce script ?
Dans beaucoup de jeux, on veut féliciter le joueur quand il atteint une zone :
- « Bien joué ! » quand il touche la ligne d’arrivée.
- « Bravo ! » quand il trouve un secret.
Dans ce script, quand un joueur touche la Part (la ligne d’arrivée par exemple), une bulle verte s’affiche au-dessus de sa tête avec le message « bien jouer ».
Mais il y a un piège ! L’événement Touched se déclenche des dizaines de fois par seconde tant que le joueur touche la Part (une fois par partie du corps qui la touche : pied, jambe, bras…). Sans protection, on verrait des dizaines de bulles de chat en même temps ! C’est pour cela qu’on utilise un cooldown de 10 secondes.
Préparation dans Roblox Studio
- Créer la Part :
- Dans
Workspace, ajoute unePart(ex: une ligne d’arrivée plate et large). - Positionne-la au sol dans ton niveau.
- Dans
- Ajouter le script DANS la Part (important !) :
- Clic droit sur la
Part→ Insert Object → Script. - Le script devient enfant de la
Part(c’est ce quescript.Parentutilise).
- Clic droit sur la
- Coller le code corrigé ci-dessus dans ce script.
- Tester :
- Lance le jeu et marche sur la
Part:- Une bulle verte « Bien joué ! » apparaît au-dessus de ta tête.
- Reste sur la Part ou re-touche-la : rien ne se passe pendant 10 secondes (le cooldown !).
- Après 10 secondes, retouche-la : la bulle réapparaît !
- Lance le jeu et marche sur la
Script commenté :
-- Récupérer la Part parente du script (la Part qui déclenche le message)
local wellDonePart = script.Parent
-- Récupérer le service Chat pour afficher des bulles de dialogue
local chatService = game:GetService("Chat")
-- Tableau de cooldown : [character] = true si le personnage est en cooldown
local cooldowns = {}
-- Détecter quand quelque chose touche la Part
wellDonePart.Touched:Connect(function(hit)
-- Récupérer le personnage (Model) qui touche la Part
local character = hit.Parent
if not character then return end
-- VÉRIFIER LE COOLDOWN : si ce personnage a déjà déclenché le message, on arrête
if cooldowns[character] then return end
-- Trouver la tête du personnage (là où la bulle de chat apparaît)
local head = character:FindFirstChild("Head")
if not head then return end
-- Afficher une bulle de chat verte au-dessus de la tête avec le message
chatService:Chat(head, "Bien joué !", Enum.ChatColor.Green)
-- ACTIVER LE COOLDOWN pour ce personnage pendant 10 secondes
cooldowns[character] = true
task.wait(10) -- Attendre 10 secondes
cooldowns[character] = false -- Réautoriser le message
end)
Explications Détaillées
1. script.Parent : le script est DANS la Part !
local wellDonePart = script.Parent
- Grande nouveauté par rapport aux tutoriels précédents : ici, le script est placé directement dans la
Part(dans l’arborescence :Part > Script), pas dansServerScriptService. script.Parent= l’objet parent du script, c’est-à-dire laPartelle-même !- Avantage : le script fonctionne n’importe où où tu copies la Part. Tu peux dupliquer la Part, le script fonctionne tout seul dans chaque copie !
2. Le service Chat et la fonction Chat:Chat()
local chatService = game:GetService("Chat")
chatService:Chat(head, "Bien joué !", Enum.ChatColor.Green)
game:GetService("Chat"): service Roblox qui gère les bulles de dialogue.chatService:Chat(...): affiche une bulle de message au-dessus d’une partie du corps. Elle prend 3 paramètres :
| Paramètre | Valeur ici | Rôle |
|---|---|---|
| 1. La partie | head | Là où la bulle apparaît (au-dessus de la tête du personnage). |
| 2. Le message | "Bien joué !" | Le texte affiché dans la bulle. |
| 3. La couleur | Enum.ChatColor.Green | La bulle est verte (il existe aussi Blue, Red, White…). |
- Différence avec le chat normal :
Chat:Chat()ne fait qu’afficher une bulle au-dessus du personnage (comme quand un joueur parle dans le jeu). Ce n’est pas un message envoyé dans la fenêtre de chat.
3. Le tableau de cooldown… avec le PERSONNAGE comme clé !
local cooldowns = {}
if cooldowns[character] then return end
cooldowns[character] = true
task.wait(10)
cooldowns[character] = false
- Rappel des tutoriels précédents : un cooldown, c’est un temps d’attente pour éviter qu’une action se déclenche trop souvent.
- La nouveauté ici : la clé du tableau n’est ni
player, niuserId, maischaracter(le Model du personnage) ! - Pourquoi
characteret pasplayer?- On n’a pas besoin du joueur : on a déjà son personnage (
hit.Parent), et c’est lui qu’on vérifie. - Ça économise une étape (pas besoin de
Players:GetPlayerFromCharacter).
- On n’a pas besoin du joueur : on a déjà son personnage (
- ⚠️ Mais attention, il y a un piège avec ce choix ! Regarde la fin du cooldown :luaCopier
cooldowns[character] = false -- Ici on met falseDans les tutoriels précédents, on mettaitnil(on supprimait l’entrée). Ici on metfalse… mais la vérificationif cooldowns[character]fonctionne quand même ! Pourquoi ? Parce que la condition vérifie simplement que la valeur n’est nifalseninil. Les deux solutions marchent :cooldowns[character] = nil→ l’entrée n’existe plus (table plus propre).cooldowns[character] = false→ l’entrée existe mais vautfalse(accepté par leif).
- Autre piège subtil : quand le joueur meurt et respawn, son personnage est détruit et un nouveau Model est créé. L’ancienne entrée
cooldowns[ancienCharacter]reste dans le tableau avecfalse… mais elle ne gêne pas (elle ne sera plus jamais utilisée). Dans un vrai jeu, on nettoierait avecPlayers.PlayerRemovingcomme dans les tutoriels précédents !
4. La détection de collision avec Touched
wellDonePart.Touched:Connect(function(hit)
local character = hit.Parent
if not character then return end
hit: la partie du corps (ou objet) qui touche laPart.hit.Parent: le Model du personnage (si un pied touche la Part,hit= le pied,hit.Parent= le personnage entier).if not character then return end: sihitn’a pas de parent (impossible normalement), on arrête.- ⚠️ Petit trou dans le filet : ce script vérifie seulement si
hit.Parentexiste. Une Part libre qui roule sur la ligne d’arrivée a aussi unParent… mais elle n’a pas deHead, donc la vérificationif not head then return endla rejette ! C’est la recherche de laHeadqui filtre les vrais joueurs.
5. Pourquoi chercher la Head ?
local head = character:FindFirstChild("Head")
if not head then return end
- La bulle de chat apparaît au-dessus de la partie qu’on donne en paramètre.
- On donne la tête pour que la bulle apparaisse au-dessus de la tête du joueur (comme dans le tutoriel des messages cliquables !).
- Si le personnage n’a pas de tête (ex: un objet qui touche la Part), on arrête : pas de tête, pas de bulle !
QCM : Teste ta compréhension !
Sur le service Chat :
- Que fait
chatService:Chat(head, "Bien joué !", Enum.ChatColor.Green)?- a) Affiche une bulle verte « Bien joué ! » au-dessus de la tête du personnage.
- b) Envoie un message dans la fenêtre de chat globale.
- c) Change la couleur du personnage en vert.
- À quoi sert le paramètre
Enum.ChatColor.Green?- a) À définir la couleur de la bulle de chat.
- b) À définir la couleur de la Part.
- c) À définir la vitesse du personnage.
Sur script.Parent :
- Que vaut
script.Parentsi le script est placé DANS une Part ?- a) La Part qui contient le script.
- b) Le Workspace.
- c) Le joueur.
- Quel est l’avantage de placer le script dans la Part avec
script.Parent?- a) On peut dupliquer la Part, et chaque copie fonctionne toute seule.
- b) Le script va plus vite.
- c) Le message est plus long.
Sur le cooldown :
- Pourquoi un cooldown est-il indispensable ici ?
- a) L’événement
Touchedse déclenche des dizaines de fois par seconde, on aurait des dizaines de bulles. - b) Pour économiser la batterie.
- c) Pour changer la couleur du message.
- a) L’événement
- Quelle est la clé du tableau
cooldownsdans ce script ?- a) Le personnage (
character). - b) Le pseudo du joueur.
- c) Le nom de la Part.
- a) Le personnage (
- Que se passe-t-il pendant les 10 secondes de cooldown si le joueur re-touche la Part ?
- a) La fonction s’arrête immédiatement à
if cooldowns[character] then return end, aucune bulle ne s’affiche. - b) La bulle s’affiche quand même.
- c) Le jeu plante.
- a) La fonction s’arrête immédiatement à
- Ce script remet le cooldown avec
cooldowns[character] = false. Quelle autre écriture était aussi possible (comme dans les tutoriels précédents) ?- a)
cooldowns[character] = nil(supprimer l’entrée du tableau). - b)
cooldowns[character] = "stop". - c)
cooldowns = {}(vider tout le tableau, ce qui supprimerait les cooldowns des AUTRES joueurs !).
- a)
Sur la détection de collision :
- Que vaut
hitquand un joueur touche la Part avec son pied ?- a) Le pied (la Part du corps qui touche).
- b) Le personnage entier.
- c) Le joueur.
- Pourquoi la vérification
if not head then return endest-elle utile, en plus de chercher la tête ?- a) Elle filtre les objets qui ne sont pas des personnages (une Part qui roule sur la ligne d’arrivée n’a pas de Head).
- b) Elle accélère le script.
- c) Elle change la couleur de la bulle.
Idées pour aller plus loin
1. Personnaliser le message avec un attribut (rappel du tutoriel des messages cliquables !)
- Objectif : Chaque copie de la Part affiche son propre message, sans modifier le script.
- Comment faire ?
- Ajoute un attribut
Message(type String) sur la Part, puis :luaCopierlocal message = wellDonePart:GetAttribute("Message") or "Bien joué !" chatService:Chat(head, message, Enum.ChatColor.Green) - Duplique la Part, change juste l’attribut :
"Niveau 1 terminé !","Zone secrète trouvée !"…
- Ajoute un attribut
2. Créer un mini-jeu : une course avec score
- Objectif : La Part donne des points à chaque passage.
- Comment faire ?luaCopier
local Players = game:GetService("Players") local player = Players:GetPlayerFromCharacter(character) if player then local leaderstats = player:FindFirstChild("leaderstats") if leaderstats then leaderstats.Score.Value += 1 end end
3. Ajouter un effet visuel et sonore (rappel du tutoriel des particules !)
- Comment faire ?luaCopier
local emitter = wellDonePart:FindFirstChildOfClass("ParticleEmitter") local sound = wellDonePart:FindFirstChildOfClass("Sound") if emitter then emitter.Enabled = true end if sound then sound:Play() end task.delay(2, function() if emitter then emitter.Enabled = false end end)
4. Nettoyer le tableau quand le joueur quitte (bonne pratique !)
- Objectif : Éviter que le tableau
cooldownsgarde des entrées inutiles. - Comment faire ? Comme dans le tutoriel flip/flop, utilise un cooldown basé sur le joueur (
player.UserIdcomme clé, comme le tutoriel des checkpoints) + un nettoyage :luaCopierlocal Players = game:GetService("Players") local player = Players:GetPlayerFromCharacter(character) if not player then return end if cooldowns[player.UserId] then return end cooldowns[player.UserId] = true task.delay(10, function() cooldowns[player.UserId] = nil end) Players.PlayerRemoving:Connect(function(leavingPlayer) cooldowns[leavingPlayer.UserId] = nil end)- Bonus : avec
task.delayau lieu detask.wait, la fonctionTouchedne reste pas bloquée 10 secondes et peut traiter d’autres joueurs !
- Bonus : avec
Résumé des concepts clés
| Concept | Description | Exemple |
|---|---|---|
script.Parent | L’objet qui contient le script (ici, la Part). | local wellDonePart = script.Parent |
game:GetService("Chat") | Service pour afficher des bulles de dialogue. | chatService:Chat(head, message, color) |
Chat:Chat() | Affiche une bulle au-dessus d’une partie, avec un message et une couleur. | Enum.ChatColor.Green |
Touched | Événement déclenché à chaque contact avec la Part (très fréquent !). | wellDonePart.Touched:Connect(...) |
hit.Parent | Le personnage (Model) qui touche la Part. | local character = hit.Parent |
FindFirstChild("Head") | Cherche la tête (et filtre les non-personnages). | if not head then return end |
| Tableau de cooldown | [character] = true pendant 10 secondes pour bloquer le spam. | if cooldowns[character] then return end |
task.wait(10) | Attend 10 secondes avant de réautoriser le message. | À la fin du cooldown |
