Module 05 · Leçon 1 sur 6
Afficher des statistiques avec les leaderstats
Crée le tableau des scores de l’Obby des Nuages (Étape et Pièces) avec les leaderstats, et apprends à le mettre à jour uniquement depuis le serveur.
- ⏱️ 20 min
- 📝 Quiz de 6 questions
- 🔄 Vérifié le 24 octobre 2026
Sur cette page
- Ce que sont les leaderstats
- Créer les leaderstats de l’Obby des Nuages
- Pourquoi la boucle à la fin ?
- Mettre à jour les valeurs depuis le serveur
- Adapter le Script Progression du module 4
- Pourquoi « uniquement côté serveur » ?
- Choisir quoi afficher
- Changer l’ordre des colonnes
- Masquer le tableau
- Quiz de fin de leçon
🎯 Dans cette leçon, tu vas apprendre à…
- Créer des leaderstats pour chaque joueur qui rejoint la partie
- Mettre à jour les valeurs depuis le serveur, et seulement depuis le serveur
- Choisir les statistiques utiles à afficher et leur ordre
Dans un obby, les joueurs adorent voir où en sont les autres : « Il est déjà à l’étape 12 ? ». Roblox propose pour ça un tableau des scores intégré, et il suffit d’un petit dossier bien nommé pour le remplir. Au module 4, ton Script « Progression » a déjà créé des leaderstats minimales (Étape et Pièces). Dans cette leçon, tu comprends ce dossier en détail et tu lui donnes son propre script. Ces valeurs seront ensuite sauvegardées (leçon suivante) et dépensées en boutique (leçon 3).
Ce que sont les leaderstats
En haut à droite de l’écran, Roblox affiche la liste des joueurs (PlayerList). Elle sert aussi de tableau des scores (leaderboard). Pour y faire apparaître des colonnes, tu ranges dans chaque joueur un dossier nommé leaderstats, qui contient des objets « valeur ». Roblox lit ce dossier et affiche une colonne par valeur.
Les objets « valeur » les plus courants :
| Objet | Contient | Exemple |
|---|---|---|
IntValue |
un nombre entier | étape, pièces, victoires |
NumberValue |
un nombre à virgule | meilleur temps en secondes |
StringValue |
un texte | rang, équipe |
Chaque objet stocke sa donnée dans sa propriété Value. On écrit donc pieces.Value = 10, et pas pieces = 10.
Créer les leaderstats de l’Obby des Nuages
Les leaderstats se créent côté serveur, au moment où le joueur arrive. Au module 4, c’était la fonction initialiserJoueur du Script « Progression » qui s’en chargeait. On leur donne maintenant un script à part, car à la leçon 2 elles seront créées à partir des données sauvegardées.
Dans l’Explorer, survole ServerScriptService, clique sur le bouton ⊕ et choisis Script (pas LocalScript), comme au module 1. Renomme-le Leaderstats (clic droit › Rename), puis remplace son contenu par ce code :
-- Script « Leaderstats » dans ServerScriptService (côté serveur)
local Players = game:GetService("Players")
-- Crée le tableau des scores d'un joueur
local function creerLeaderstats(player: Player)
-- 1. Le dossier DOIT s'appeler « leaderstats », tout en minuscules
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
-- 2. Le numéro du dernier checkpoint validé : 0 avant le premier checkpoint
local etape = Instance.new("IntValue")
etape.Name = "Etape" -- ce nom s'affiche tel quel dans le tableau
etape.Value = 0
etape.Parent = leaderstats
-- 3. Les pièces ramassées
local pieces = Instance.new("IntValue")
pieces.Name = "Pieces"
pieces.Value = 0
pieces.Parent = leaderstats
-- 4. On range le dossier dans le joueur en dernier :
-- il arrive d'un coup, déjà rempli
leaderstats.Parent = player
end
-- Chaque nouveau joueur reçoit ses leaderstats
Players.PlayerAdded:Connect(creerLeaderstats)
-- Sécurité : les joueurs déjà présents avant le démarrage du script
for _, player in Players:GetPlayers() do
task.spawn(creerLeaderstats, player)
end
Avant de tester, fais la modification du Script « Progression » décrite plus bas (étape 2 du plan) : sinon, chaque joueur recevrait deux dossiers leaderstats, un par script. Lance ensuite un test (Play) : ton nom apparaît en haut à droite avec deux colonnes, Etape et Pieces, toutes deux à 0. Dans tout le projet, Etape contient le numéro du dernier checkpoint validé : 0 tant que le joueur n’a touché aucun checkpoint.
Pourquoi la boucle à la fin ?
PlayerAdded ne se déclenche que pour les joueurs qui arrivent après la connexion. En test dans Studio, il arrive que ton joueur soit déjà là quand le script démarre. La boucle sur Players:GetPlayers() rattrape ce cas. task.spawn lance chaque appel sans attendre le précédent.
Mettre à jour les valeurs depuis le serveur
Pour changer une statistique, on modifie la propriété Value de l’objet, depuis un Script serveur. Tes scripts du module 4 le font déjà : etape.Value = numero dans « Progression » (après toutes les vérifications), pieces.Value += VALEUR_PIECE dans « Pieces ». Comme d’autres scripts (la boutique, leçon 3) en auront besoin, voici une petite fonction qui retrouve une statistique de façon sûre :
-- Fonction utilitaire, à copier dans un Script serveur qui modifie les stats
-- Renvoie l'IntValue demandée (« Etape » ou « Pieces »), ou nil si elle n'existe pas encore
local function obtenirStat(player: Player, nomStat: string): IntValue?
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats == nil then
return nil -- les leaderstats ne sont pas encore créées
end
local stat = leaderstats:FindFirstChild(nomStat)
if stat and stat:IsA("IntValue") then
return stat
end
return nil
end
On utilise FindFirstChild plutôt que player.leaderstats.Pieces : si le dossier n’existe pas encore (joueur qui vient d’arriver), FindFirstChild renvoie nil au lieu de provoquer une erreur.
Adapter le Script Progression du module 4
Ton Script « Progression » (module 4, leçon 5) fait deux choses dans initialiserJoueur : il crée les leaderstats, puis il replace le personnage sur son dernier checkpoint à chaque réapparition. La création passe maintenant dans le Script « Leaderstats ». Remplace donc toute la fonction initialiserJoueur de « Progression » par le code ci-dessous. Tout le reste du script ne change pas, en particulier surContactCheckpoint et ses vérifications : étape suivante uniquement (Etape + 1), distance réelle avec Validation.estAPortee, journalisation des passages trop rapides. Ne les retire surtout pas : ce sont elles qui empêchent de tricher.
-- Dans le Script « Progression » (ServerScriptService, module 4) :
-- remplace l'ancienne fonction initialiserJoueur par ces deux fonctions.
-- obtenirEtape, dossierCheckpoints et Workspace sont déjà définis plus haut dans ce script.
-- Replace le personnage sur le dernier checkpoint validé
local function placerAuCheckpoint(player: Player, character: Model)
-- Les leaderstats viennent maintenant d'un autre script (et, dès la leçon 2,
-- elles n'apparaissent qu'une fois la sauvegarde chargée) : on les attend
player:WaitForChild("leaderstats", 60)
local etape = obtenirEtape(player)
if etape == nil or etape.Value == 0 then
return -- pas de leaderstats, ou premier départ : la SpawnLocation suffit
end
local checkpoint = dossierCheckpoints:FindFirstChild(tostring(etape.Value))
if not (checkpoint and checkpoint:IsA("BasePart")) then
return
end
-- Même précaution qu'au module 4 : on laisse Roblox finir de placer le personnage
if not character:IsDescendantOf(Workspace) then
character.AncestryChanged:Wait()
end
task.wait()
if player.Character ~= character or not character:IsDescendantOf(Workspace) then
return -- ce personnage a disparu entre-temps (joueur parti, nouvelle réapparition…)
end
character:PivotTo(checkpoint.CFrame + Vector3.new(0, 4, 0))
end
-- Ne crée plus les leaderstats : s'occupe seulement des réapparitions
local function initialiserJoueur(player: Player)
player.CharacterAdded:Connect(function(character: Model)
placerAuCheckpoint(player, character)
end)
-- Le personnage a pu apparaître avant que ce script ne s'occupe du joueur
if player.Character then
task.spawn(placerAuCheckpoint, player, player.Character)
end
end
Pourquoi attendre les leaderstats ? À la leçon 2, elles ne seront créées qu’après le chargement de la sauvegarde, ce qui peut prendre une ou deux secondes. Le premier personnage du joueur apparaît souvent avant. Grâce à cette attente, un joueur qui revient à l’étape 12 est replacé sur le checkpoint 12 dès que ses données sont prêtes, au lieu de rester sur la SpawnLocation.
Ton Script « Pieces » du module 4, lui, ne change pas : il retrouve déjà leaderstats.Pieces avec FindFirstChild et ajoute VALEUR_PIECE après ses vérifications (distance, cooldown). Les leaderstats deviennent la référence de l’étape et des pièces pendant la partie.
Pourquoi « uniquement côté serveur » ?
Souviens-toi du module 4 : ce que fait un LocalScript reste sur la machine du joueur. Si un LocalScript écrit pieces.Value = 9999, seul ce joueur voit 9999 ; le serveur, les autres joueurs et la sauvegarde gardent la vraie valeur. C’est pour ça que :
- toutes les modifications de leaderstats passent par des Scripts serveur ;
- le client peut lire les leaderstats (pour afficher un compteur, par exemple), mais jamais décider de leur valeur ;
- quand le client veut une action (acheter un objet), il demande au serveur via un RemoteEvent, et le serveur vérifie avant de modifier quoi que ce soit.
Choisir quoi afficher
Le tableau est petit, surtout sur téléphone. Quelques principes simples :
- Deux ou trois statistiques maximum. Chaque colonne prend de la place.
- Ce qui donne envie de progresser ou de comparer : l’étape atteinte est parfaite pour un obby. Le nombre de morts, par exemple, est plutôt démotivant.
- Des noms courts :
Etapeplutôt queEtapeMaximaleAtteinte. - Pas de données privées ou techniques : tout le monde voit ce tableau.
Changer l’ordre des colonnes
La documentation officielle propose trois façons de contrôler l’ordre :
- créer les statistiques dans l’ordre voulu ;
- ajouter dans une statistique un
BoolValuenomméIsPrimary, avec la valeurtrue, pour la placer en premier ; - ajouter un
NumberValuenomméPriority: plus la valeur est haute, plus la colonne apparaît tôt.
-- À ajouter dans le Script « Leaderstats », au-dessus de creerLeaderstats
-- Fait d'une statistique la colonne principale du tableau
local function rendrePrincipale(stat: IntValue)
local estPrincipale = Instance.new("BoolValue")
estPrincipale.Name = "IsPrimary"
estPrincipale.Value = true
estPrincipale.Parent = stat
end
Il suffit ensuite d’appeler rendrePrincipale(etape) dans creerLeaderstats, juste après la création de etape.
Masquer le tableau
Pendant un menu ou une cinématique, tu peux masquer la liste depuis un LocalScript :
-- LocalScript (par exemple dans StarterPlayerScripts)
local StarterGui = game:GetService("StarterGui")
-- Cache la liste des joueurs pour ce joueur uniquement
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, false)
C’est un réglage d’affichage local : il ne touche pas aux valeurs.
Ce qu’il faut retenir
- Un dossier
leaderstats(tout en minuscules) rangé dans le joueur remplit le tableau des scores. - Chaque colonne est un objet valeur (
IntValue,NumberValue,StringValue) dont on modifie la propriétéValue. - On crée les leaderstats dans un Script serveur, à
PlayerAdded, sans oublier les joueurs déjà présents. - Le Script « Progression » du module 4 ne crée plus les leaderstats, mais garde toutes ses vérifications de checkpoints (étape suivante, distance).
- On ne modifie les leaderstats que depuis le serveur ; le client se contente de les lire.
- Peu de colonnes, des noms courts, et
IsPrimaryouPrioritypour choisir l’ordre.