et les changements d’états
Découvrir la vie d’un joueur dans Roblox avec un script « d’observation » :
- Quand un joueur se connecte (
PlayerAdded). - Quand son personnage apparaît (
CharacterAdded). - Quand son personnage change d’état (
StateChanged: saut, chute, atterrissage…).
Ce script n’est pas un jeu : c’est un script espion ! Il ne fait qu’afficher dans la console (Output) tout ce qui arrive aux joueurs. C’est l’outil parfait pour comprendre ces trois événements avant de les utiliser dans de vrais jeux (comme la zone anti-gravité ou les checkpoints !).
Introduction : La vie d’un joueur Roblox
Quand tu joues à un jeu Roblox, voici ce qui se passe dans l’ordre :
1. Le JOUEUR se connecte au jeu → événement PlayerAdded
2. Son PERSONNAGE apparaît dans le monde → événement CharacterAdded
3. Le personnage agit : court, saute, tombe, atterrit...
→ événements StateChanged (très fréquents !)
4. Le personnage meurt → il est détruit
5. Un NOUVEAU personnage apparaît → de nouveau CharacterAdded !
6. Le joueur quitte le jeu → événement PlayerRemoving
Les trois personnages-clés de ce tuto :
player: le compte du joueur (son nom, son UserId…). Il ne meurt jamais.character: le bonhomme 3D dans le monde (le Model). Il est détruit à chaque mort et recréé à chaque respawn !humanoid: l’ordinateur de bord du personnage : il gère la santé, la marche, les sauts… et ses états.
Les états d’un Humanoid (Enum.HumanoidStateType)
| État | Signification |
|---|---|
Running | Le personnage court au sol. |
Jumping | Il vient de sauter. |
Freefall | Il tombe dans les airs. |
Landed | Il vient d’atterrir. |
Climbing | Il grimpe à une échelle. |
Swimming | Il nage. |
Seated | Il est assis (dans un siège). |
Dead | Il est mort ! |
PlatformStanding / Physics | États spéciaux (plateformes, physique). |
C’est la même liste que celle utilisée dans le tutoriel de la zone anti-gravité (Jumping, Freefall, Landed) !
Voici le script commenté en français :
-- Récupérer le service des joueurs
local Players = game:GetService("Players")
-- Fonction appelée à chaque changement d'état du Humanoid
-- Paramètres : le joueur, l'ancien état, le nouvel état
local function onStateChanged(player, oldState, newState)
-- Affiche dans la console : nom du joueur, ancien état -> nouvel état
print(player.Name, "État changé :", oldState, "->", newState)
end
-- Fonction appelée à chaque apparition du personnage
local function onCharacterAdded(player, character)
-- Attendre que le Humanoid existe (le personnage se construit progressivement !)
local humanoid = character:WaitForChild("Humanoid")
-- Connecter le suivi des changements d'états de CE personnage
humanoid.StateChanged:Connect(function(oldState, newState)
onStateChanged(player, oldState, newState)
end)
end
-- Fonction appelée à chaque connexion d'un joueur
local function onPlayerAdded(player)
print(player.Name .. " est connecté")
-- Cas 1 : le personnage existe DÉJÀ (joueur connecté avant le script)
if player.Character then
task.spawn(onCharacterAdded, player, player.Character)
end
-- Cas 2 : chaque apparition/réapparition FUTURE (mort, respawn...)
player.CharacterAdded:Connect(function(character)
onCharacterAdded(player, player.Character and character)
end)
end
-- Nouveaux joueurs : événement pour chaque joueur qui se connecte
Players.PlayerAdded:Connect(onPlayerAdded)
-- Joueurs déjà connectés AVANT l'exécution du script
for _, player in ipairs(Players:GetPlayers()) do
task.spawn(onPlayerAdded, player)
end
Explications Détaillées : les 4 fonctions du script
Le script est construit comme des poupées russes : chaque fonction appelle la suivante !
onPlayerAdded ──► onCharacterAdded ──► onStateChanged
(1) (2) (3)
1. onStateChanged : l’espion des états
local function onStateChanged(player, oldState, newState)
print(player.Name, "État changé :", oldState, "->", newState)
end
oldState: l’état avant le changement (ex:Enum.HumanoidStateType.Freefall).newState: le nouvel état (ex:Enum.HumanoidStateType.Landed).- Rappel des tutoriels précédents :
print(...)avec plusieurs valeurs séparées par des virgules affiche tout sur une ligne (pas besoin de concaténer avec..!).
2. onCharacterAdded : l’espion des personnages
local function onCharacterAdded(player, character)
local humanoid = character:WaitForChild("Humanoid")
humanoid.StateChanged:Connect(function(oldState, newState)
onStateChanged(player, oldState, newState)
end)
end
WaitForChild("Humanoid"): quand le personnage apparaît, il se construit pièce par pièce (jambes, torse, tête, Humanoid…). Si on cherche leHumanoidtrop tôt, il n’existe pas encore → erreur !WaitForChildattend qu’il soit prêt. (Rappel : c’est pareil queWaitForChild("HumanoidRootPart")dans le tutoriel des checkpoints !)- On connecte
StateChangedpour ce personnage précis. Quand il mourra, ce personnage sera détruit — et sa connexion avec lui ! C’est pour ça qu’il faut reconnecterStateChangedà chaque nouveau personnage (d’où la fonction !).
3. onPlayerAdded : l’espion des joueurs (avec ses DEUX pièges !)
local function onPlayerAdded(player)
print(player.Name .. " est connecté")
-- Cas 1 : le personnage existe DÉJÀ
if player.Character then
task.spawn(onCharacterAdded, player, player.Character)
end
-- Cas 2 : apparitions futures
player.CharacterAdded:Connect(function(character)
onCharacterAdded(player, character)
end)
end
Piège n°1 : le joueur est arrivé AVANT le script !
- Le problème :
PlayerAddedne se déclenche que pour les joueurs qui arrivent après la connexion de l’événement. Si tu es déjà dans le jeu quand le script démarre (par exemple au lancement d’un test Studio), l’événement t’a raté ! - La solution en deux temps :
- Cas 1 :
if player.Character then→ le personnage existe déjà → on appelle directementonCharacterAdded. - Cas 2 :
player.CharacterAdded:Connect(...)→ on guette toutes les apparitions futures (respawn après mort !).
- Cas 1 :
Piège n°2 : CharacterAdded ne se déclenche pas à la connexion… mais un peu après !
- Quand un joueur se connecte,
PlayerAddedse déclenche, puis Roblox crée son personnage (quelques millisecondes plus tard) → c’est ensuite queCharacterAddedse déclenche. C’est pour ça que le Cas 2 attrape aussi la toute première apparition !
Pourquoi task.spawn ?
task.spawn(fonction, arguments...)lance la fonction dans un thread séparé : le script n’attend pas qu’elle soit finie pour continuer.- Indispensable ici :
onCharacterAddedcommence par unWaitForChild… qui peut bloquer quelques instants. Sanstask.spawn, un joueur « lent à charger » bloquerait le traitement des autres joueurs !
4. La boucle finale : rattraper tout le monde
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in ipairs(Players:GetPlayers()) do
task.spawn(onPlayerAdded, player)
end
Players.PlayerAdded:Connect(onPlayerAdded): tous les joueurs qui arriveront à partir de maintenant.Players:GetPlayers(): la liste des joueurs déjà présents (rappel : c’est une liste numérotée, donc on utiliseipairs, comme pour les checkpoints et les blocs de la pyramide !).- La boucle appelle
onPlayerAddedpour chacun : personne n’est oublié, même si le script a démarré en retard !
Le schéma complet :

Préparation et Test dans Roblox Studio
- Crée un
ScriptdansServerScriptServiceet colle le code corrigé. - Ouvre la fenêtre
Output(onglet View → Output) : c’est là que lesprints’affichent. - Lance le jeu en mode multi-joueurs (onglet Test → 2 Players) pour observer plusieurs joueurs !
- Expérimente et observe la console :
| Action | Ce que tu dois voir dans l’Output |
|---|---|
| Le jeu démarre | patrick est connecté (et celui du 2ème joueur !) |
| Tu marches | Rien (rester en Running ne change pas l’état !) |
| Tu sautes | Jumping puis Freefall |
| Tu atterris | Landed puis Running |
| Tu montes une échelle | Climbing |
| Tu tombes dans l’eau | Swimming |
| Tu t’assois sur un siège | Seated |
| Tu te reset (menu Echap → Reset) | Dead… puis re-connexion automatique de CharacterAdded ! |
Contrôle important : après ta mort, observe bien : onCharacterAdded est rappelé automatiquement pour ton nouveau personnage (le script continue d’afficher tes états, sans rien refaire !). C’est la preuve que le Cas 2 de onPlayerAdded fonctionne.
QCM : Teste ta compréhension !
Sur la vie du joueur :
- Dans quel ordre se passent les événements quand un joueur rejoint le jeu ?
- a)
PlayerAdded→CharacterAdded→ puis lesStateChanged. - b)
CharacterAdded→PlayerAdded→StateChanged. - c) Tout en même temps.
- a)
- Quelle est la différence entre
playeretcharacter?- a)
playerest le compte (ne meurt jamais) ;characterest le bonhomme 3D, détruit à chaque mort et recréé à chaque respawn. - b) Ce sont deux noms pour la même chose.
- c)
characterest le compte du joueur.
- a)
- Que se passe-t-il pour la connexion
StateChangedquand le personnage meurt et respawn ?- a) Elle est détruite avec l’ancien personnage ;
onCharacterAddedreconnecteStateChangedsur le NOUVEAU Humanoid. - b) Elle reste active sur l’ancien personnage.
- c) Roblox la reconnecte automatiquement tout seul.
- a) Elle est détruite avec l’ancien personnage ;
Sur les états du Humanoid :
- Dans quel ordre les états s’enchaînent-ils quand tu sautes d’une plateforme ?
- a)
Jumping→Freefall→Landed→Running. - b)
Running→Landed→Jumping. - c)
Freefall→Jumping→Running.
- a)
- Pourquoi ne voit-on rien s’afficher quand on marche normalement pendant longtemps ?
- a) Parce qu’on reste dans l’état
Running: sans changement d’état,StateChangedne se déclenche pas. - b) Parce que
printest cassé. - c) Parce que la marche est trop rapide.
- a) Parce qu’on reste dans l’état
- Quels sont les paramètres reçus par la fonction connectée à
StateChanged?- a) L’ancien état et le nouvel état (
oldState,newState). - b) Le joueur et le personnage.
- c) Rien.
- a) L’ancien état et le nouvel état (
Sur les deux pièges :
- Pourquoi le script a-t-il besoin de la boucle
for ... ipairs(Players:GetPlayers())à la fin ?- a) Pour rattraper les joueurs déjà connectés AVANT le démarrage du script (l’événement
PlayerAddedne se déclenche pas pour eux). - b) Pour déconnecter les joueurs.
- c) Pour afficher la liste des règles du jeu.
- a) Pour rattraper les joueurs déjà connectés AVANT le démarrage du script (l’événement
- Pourquoi utilise-t-on
task.spawn(onCharacterAdded, player, player.Character)?- a) Pour lancer la fonction dans un thread séparé et ne pas bloquer le script, car elle contient un
WaitForChildqui peut attendre. - b) Pour aller plus vite que
WaitForChild. - c) Parce que
onCharacterAddedest interdite ailleurs.
- a) Pour lancer la fonction dans un thread séparé et ne pas bloquer le script, car elle contient un
- Pourquoi
onCharacterAddedutilise-t-elleWaitForChild("Humanoid")?- a) Parce que le personnage se construit pièce par pièce : au moment de l’événement, le Humanoid n’existe peut-être pas encore.
- b) Pour faire joli.
- c) Parce que le Humanoid n’existe jamais.
- Dans
onPlayerAdded, à quoi sert leif player.Character then?- a) À vérifier si le personnage existe DÉJÀ (le joueur était là avant le script) pour ne pas rater son suivi.
- b) À créer un personnage.
- c) À détruire le personnage.
Résumé des concepts clés
| Concept | Description | Exemple |
|---|---|---|
PlayerAdded | Un joueur se connecte au jeu. | Players.PlayerAdded:Connect(onPlayerAdded) |
CharacterAdded | Un personnage apparaît (1ère fois OU respawn !). | player.CharacterAdded:Connect(...) |
StateChanged | Le Humanoid change d’état (saut, chute, atterrissage…). | humanoid.StateChanged:Connect(...) |
Enum.HumanoidStateType | La liste des états possibles. | Landed, Jumping, Freefall, Dead… |
GetPlayers() | Liste des joueurs déjà présents (rattrapage !). | for _, player in ipairs(...) do |
task.spawn | Lance une fonction sans bloquer le script. | task.spawn(onPlayerAdded, player) |
WaitForChild("Humanoid") | Attend que le personnage soit prêt. | Anti-erreur ! |
GetState() | Lit l’état ACTUEL (sans attendre un changement). | Utilisé dans la zone anti-gravité |
Astuce : Garde ce script espion dans un coin de tes projets : dès qu’un comportement te semble mystérieux (pourquoi mon joueur ne saute plus ?), les print des états te diront exactement ce qui se passe dans la tête du Humanoid ! C’est l’outil de débogage parfait
