Aller au contenu
Forma Roblox

Rechercher dans la formation

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

🎯 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 : Etape plutôt que EtapeMaximaleAtteinte.
  • 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 :

  1. créer les statistiques dans l’ordre voulu ;
  2. ajouter dans une statistique un BoolValue nommé IsPrimary, avec la valeur true, pour la placer en premier ;
  3. ajouter un NumberValue nommé 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 IsPrimary ou Priority pour choisir l’ordre.

Sources et pour aller plus loin

Quiz : vérifie tes acquis

6 questions · réussite à partir de 70 % · valide chaque réponse pour voir l’explication

  1. Question 1QCMComment doit s’appeler le dossier que Roblox transforme en tableau des scores ?
  2. Question 2Vrai ou fauxSi un LocalScript augmente Pieces.Value dans les leaderstats du joueur, le serveur et les autres joueurs voient la nouvelle valeur.
  3. Question 3QCMQuel objet choisir pour afficher un nombre entier de pièces ?
  4. Question 4Trouve le bugCe Script serveur doit afficher l’étape de chaque joueur dans le tableau des scores. Rien ne s’affiche. Où est le bug ?
    local Players = game:GetService("Players")
    
    Players.PlayerAdded:Connect(function(player)
    	local dossier = Instance.new("Folder")
    	dossier.Name = "Leaderstats"
    
    	local etape = Instance.new("IntValue")
    	etape.Name = "Etape"
    	etape.Value = 0
    	etape.Parent = dossier
    
    	dossier.Parent = player
    end)
  5. Question 5QCMComment faire apparaître Pieces en premier dans le tableau, même s’il a été créé après Etape ?
  6. Question 6Améliore ce promptTu veux que Claude Code déplace la création des leaderstats dans leur propre script. Quelle version du prompt donnera le meilleur résultat ?
    Le prompt de départ
    mets les leaderstats dans un script à part

    Choisis la meilleure version de ce prompt.