Catégories
Jeu vidéo ROBLOX

Afficher un chrono du temps de parcours

Ce système affiche un chrono qui mesure le temps mis par un joueur pour aller d’un bloc de départ à un bloc d’arrivée.

Le script serveur est placé sur les blocs (départ/arrivée) : il détecte quand le joueur les touche (Touched) et décide quand le chrono doit démarrer ou s’arrêter.

Le LocalScript, lui, tourne uniquement sur l’ordinateur du joueur : il gère l’affichage du chrono à l’écran (le TextLabel).

Le serveur ne peut pas modifier directement l’écran d’un joueur : il doit envoyer un message au client via un RemoteEvent.

Le RemoteEvent fonctionne comme une messagerie entre le serveur et le client : quand le joueur touche le bloc de départ, le serveur « fire » (envoie) l’événement StartEvent.

Le LocalScript écoute cet événement avec OnClientEvent:Connect(...) et, dès qu’il le reçoit, enregistre l’heure de départ (tick()) et active running = true.

De la même façon, quand le joueur touche le bloc d’arrivée, le serveur envoie WinEvent, et le LocalScript reçoit ce signal pour arrêter le chrono (running = false).

Pendant que running est actif, la fonction RunService.Heartbeat recalcule et affiche le temps écoulé à chaque frame (60 fois par seconde environ).

La fonction formatTime transforme le nombre de secondes brut en un affichage lisible du type 01:23 (minutes:secondes).

En résumé : le serveur décide (quand démarrer/arrêter), les RemoteEvents transmettent l’info, et le LocalScript affiche le résultat à l’écran du joueur.

    Petit rappel pour bien comprendre

    • Script serveur : tourne sur l’ordinateur qui héberge la partie. Il contrôle les règles du jeu, mais ne peut pas modifier ce qui s’affiche à l’écran d’un joueur précis.
    • LocalScript : tourne uniquement sur l’ordinateur du joueur. Il gère l’affichage (interface, sons, caméra…) mais ne peut pas être utilisé pour des règles importantes du jeu (sinon un joueur pourrait tricher).
    • RemoteEvent : le « pont » entre les deux. Le serveur envoie une info avec FireClient(), et le LocalScript la reçoit avec OnClientEvent:Connect().

    QCM pour bien comprendre

    1. Où s’exécute un LocalScript ?
    A. Sur le serveur du jeu
    B. Sur l’ordinateur du joueur uniquement
    C. Sur tous les ordinateurs en même temps
    D. Nulle part, c’est juste un fichier texte

    2. Pourquoi ne peut-on pas modifier directement le TextLabel depuis le script serveur ?
    A. Parce que c’est interdit par Roblox
    B. Parce que le serveur n’a pas accès à l’affichage local de chaque joueur
    C. Parce que le TextLabel n’existe pas sur le serveur
    D. Parce que ça coûte trop cher en mémoire

    3. À quoi sert un RemoteEvent ?
    A. À supprimer un joueur du jeu
    B. À transmettre une information entre le serveur et un client
    C. À changer la couleur d’un bloc automatiquement
    D. À sauvegarder les données du joueur

    4. Que fait startEvent:FireClient(player) côté serveur ?
    A. Il supprime le joueur
    B. Il envoie un signal au client précis pour déclencher une action
    C. Il démarre le jeu pour tous les joueurs
    D. Il crée un nouveau RemoteEvent

    5. Que fait RunService.Heartbeat dans ce script ?
    A. Il vérifie les battements de cœur du joueur
    B. Il exécute du code à chaque frame, ici pour actualiser l’affichage du chrono
    C. Il redémarre le serveur régulièrement
    D. Il compte le nombre de joueurs connectés

    6. Que se passe-t-il si running vaut false ?
    A. Le chrono continue de s’incrémenter
    B. Le texte du chrono arrête de se mettre à jour
    C. Le joueur est téléporté au départ
    D. Le RemoteEvent est détruit

    Crée un part pour déterminer le départ du chrono et un part pour déterminer le stop du chrono.

    Puis deux RemoteEvent pour gérer le démarrage et l’arrêt du chrono :

    Puis script sur le serveur pour gérer les collisions entre le player et les parts de départ et d’arrivée :

    local replicatedStorage = game:GetService("ReplicatedStorage")
    local remoteEvent = replicatedStorage:WaitForChild("Coursetimecheck")
    
    local startEvent = remoteEvent.StartEvent
    local winEvent = remoteEvent.WinEvent
    
    local start = script.Parent.StartPart
    local succes = script.Parent.SuccessPart
    
    succes.SurfaceGui.Enabled = false
    succes.ParticleEmitter.Enabled = false
    
    succes.Anchored = true
    succes.CanCollide = true
    succes.CanTouch = true
    
    start.Anchored = true
    start.CanCollide = false
    start.CanTouch = true
    start.Transparency = 1
    
    succes.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid then return end
    	if succes.SurfaceGui.Enabled then return end
    	
    	remoteEvent.WinEvent:FireClient(game.Players:GetPlayerFromCharacter(character))
    
    	succes.SurfaceGui.Enabled = true
    	succes.ParticleEmitter.Enabled = true
    end)
    
    start.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid then return end
    	
    	local player = game.Players:GetPlayerFromCharacter(character)
    	if not player then return end -- sécurité si ce n'est pas un joueur (NPC par ex.)
    
    	print("StartEvent déclenché pour " .. player.Name)
    
    	startEvent:FireClient(player)
    	
    end)

    Et également un localScript pour l’affichage du chrono pour le joueur :

    -- Récupération des services
    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local RunService = game:GetService("RunService")
    
    -- Récupération du joueur actuel et de la PlayerGui
    local player = Players.LocalPlayer
    local playerGui = player:WaitForChild("PlayerGui")
    
    -- Récupération de l'UI du chrono
    local chrono = playerGui:WaitForChild("ScreenGui"):WaitForChild("Frame"):WaitForChild("ChronoLabel")
    
    -- Récupération des RemoteEvents start et stop du chrono
    local remoteEventsFolder = ReplicatedStorage:WaitForChild("Coursetimecheck")
    local startEvent = remoteEventsFolder:WaitForChild("StartEvent")
    local stopEvent = remoteEventsFolder:WaitForChild("WinEvent")
    
    -- Fonction pour formater le temps en minutes:secondes
    local function formatTime(t)
    	local minutes = math.floor(t / 60)
    	local seconds = math.floor(t % 60)
    	return string.format("%02d:%02d", minutes, seconds)
    end
    
    -- Variables globales pour suivre le temps et l'état du chrono
    local startTime = nil
    chrono.Text = "00:00"
    local running = false
    
    -- Connexion des événements serveur au client
    startEvent.OnClientEvent:Connect(function()
    	startTime = tick()
    	running = true
    end)
    
    stopEvent.OnClientEvent:Connect(function()
    	running = false
    end)
    
    -- Mise à jour continue de l'affichage du chrono
    RunService.Heartbeat:Connect(function()
    	if not running or not startTime then return end
    	chrono.Text = formatTime(tick() - startTime)
    end)
    Catégories
    Jeu vidéo ROBLOX

    Devenir petit en touchant un part

    Ce script est attaché à un Part (bloc) et détecte quand un joueur le touche, via l’événement Touched.

    Il vérifie que c’est bien un personnage avec un Humanoid, et bloque les déclenchements répétés grâce à un système de cooldown (table cooldowns).

    Si le joueur n’a pas encore été rétréci/agrandi, le script sauvegarde sa taille actuelle dans un dossier Scale, puis applique la taille SCALEMAX (0.3) à sa hauteur, largeur, profondeur et tête.

    Si le joueur a déjà été modifié (le dossier Scale existe), le script lui redonne sa taille d’origine et supprime le dossier.

    Autrement dit : c’est un bloc « grandir/rétrécir » qui bascule (toggle) la taille du joueur à chaque contact, avec une seconde d’attente avant de pouvoir réutiliser le bloc.

    QCM : Testez votre compréhension !

    1. Que fait l’événement Touched dans ce script ?
    A. Il vérifie si le joueur a cliqué sur le bloc
    B. Il détecte quand quelque chose touche la Part
    C. Il compte le nombre de joueurs dans le jeu
    D. Il détruit le bloc

    2. À quoi sert la variable COOLDOWN ?
    A. À changer la couleur du bloc
    B. À définir la taille maximale du joueur
    C. À empêcher de réutiliser le bloc trop vite
    D. À supprimer le personnage

    3. Que se passe-t-il si le joueur touche le bloc une deuxième fois (après le cooldown) ?
    A. Rien, ça ne marche qu’une fois
    B. Le joueur reprend sa taille normale
    C. Le joueur devient minuscule
    D. Le jeu plante

    4. À quoi sert le dossier (IntValue) nommé "Scale" ?
    A. À afficher un message au joueur
    B. À mémoriser la taille d’origine du joueur
    C. À compter le temps de cooldown
    D. À stocker le nom du joueur

    5. Pourquoi utilise-t-on une table cooldowns avec le character comme clé ?
    A. Pour donner un nom à chaque joueur
    B. Pour savoir si CE joueur précis est en cooldown
    C. Pour compter les points de chaque joueur
    D. Pour changer la vitesse du joueur

    local part = script.Parent
    
    local SCALEMAX = 0.3
    
    local COOLDOWN = 1 -- secondes avant de pouvoir re-déclencher
    local cooldowns = {} -- [character] = true pendant le cooldown
    
    part.Touched:Connect(function(plr)
    	local character = plr.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid  then return end
    
    	if cooldowns[character] then return end
    	cooldowns[character] = true
    
    	local existingFolder = humanoid:FindFirstChild("Scale")
    
    	if existingFolder then
    		humanoid.BodyHeightScale.Value = existingFolder.Value
    		humanoid.BodyWidthScale.Value = existingFolder.Value		
    		humanoid.BodyDepthScale.Value = existingFolder.Value	
    		humanoid.HeadScale.Value = existingFolder.Value
    		existingFolder:Destroy()
    	else
    		local folder = Instance.new("IntValue")
    		folder.Name = "Scale"
    		folder.Parent = humanoid
    		folder.Value = humanoid.BodyHeightScale.Value
    		humanoid.BodyHeightScale.Value = SCALEMAX
    		humanoid.BodyWidthScale.Value = SCALEMAX		
    		humanoid.BodyDepthScale.Value = SCALEMAX	
    		humanoid.HeadScale.Value = SCALEMAX
    	end
    
    	task.wait(COOLDOWN)
    	cooldowns[character] = nil
    
    end)
    
    Catégories
    Jeu vidéo ROBLOX

    Courir plus vite ou sauter plus haut en touchant un part

    Courir plus vite

    Ce script surveille une part (un bloc) dans le jeu, et attend qu’un joueur la touche.

    Quand un joueur la touche, le script vérifie qu’il s’agit bien d’un personnage (avec un Humanoid, la partie du jeu qui gère la santé, les déplacements, etc.).

    Si c’est bien un joueur, sa vitesse de déplacement (WalkSpeed) passe à 50; il devient beaucoup plus rapide (par défaut, c’est 16).

    QCM — vérifie ta compréhension

    1. Que fait part.Touched:Connect(...) ?
    A) Il détruit la part
    B) Il détecte quand quelque chose touche la part
    C) Il déplace la part
    D) Il change la couleur de la part

    2. Pourquoi le script vérifie if not humanoid then return end ?
    A) Pour vérifier que la part existe
    B) Pour arrêter le script si ce qui a touché n’est pas un personnage (par exemple un objet sans Humanoid)
    C) Pour ralentir le joueur
    D) Pour supprimer le Humanoid

    3. Que représente Humanoid dans un personnage Roblox ?
    A) Le nom du joueur
    B) La couleur de la peau
    C) La partie qui gère la santé, les déplacements, etc.
    D) Un accessoire du personnage

    4. Que se passe-t-il quand humanoid.WalkSpeed = 50 s’exécute ?
    A) Le joueur devient invisible
    B) Le joueur saute plus haut
    C) Le joueur se déplace plus vite
    D) Le joueur perd de la vie

    5. Si un objet SANS Humanoid (comme une simple balle) touche la part, que se passe-t-il ?
    A) Le script plante avec une erreur
    B) Rien, le script s’arrête grâce au return
    C) La balle devient rapide
    D) Le jeu redémarre

    local part = script.Parent
    
    part.Touched:Connect(function(plr)
    	local character = plr.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid  then return end
    	
    	humanoid.WalkSpeed = 50
    		
    end)
    

    Bascule courir plus vite / normalement

    Quand un joueur touche la part, le script regarde s’il a déjà une vitesse « boostée » (mémorisée dans un petit objet nommé « Speed ») : si oui, il lui rend sa vitesse normale, sinon il sauvegarde sa vitesse actuelle et le rend très rapide (50).

    Un système de « cooldown » (temps d’attente) empêche le joueur de retoucher la part plusieurs fois par seconde et de faire buguer le changement de vitesse.

    Ainsi, la part fonctionne comme un interrupteur : un coup pour accélérer, un coup pour revenir à la normale, avec une petite pause obligatoire entre deux touches.

    QCM — vérifie ta compréhension

    1. À quoi sert la variable cooldowns ?
    A) À compter combien de joueurs ont touché la part
    B) À empêcher un joueur de redéclencher l’effet plusieurs fois trop vite
    C) À stocker la couleur de la part
    D) À sauvegarder le nom du joueur

    2. Que fait l’objet IntValue nommé « Speed » ?
    A) Il affiche un message au joueur
    B) Il mémorise la vitesse de marche du joueur avant le boost, pour pouvoir la restaurer plus tard
    C) Il détruit le personnage
    D) Il change la couleur de la part

    3. Que se passe-t-il si le joueur touche la part une seconde fois (sans cooldown actif) ?
    A) Sa vitesse redevient normale, car le dossier « Speed » existe déjà
    B) Rien ne se passe
    C) Sa vitesse augmente encore plus
    D) Le jeu plante

    4. Pourquoi utilise-t-on task.wait(COOLDOWN) à la fin de la fonction ?
    A) Pour ralentir tous les joueurs du jeu
    B) Pour attendre 1 seconde avant de permettre au joueur de redéclencher l’effet
    C) Pour détruire la part après 1 seconde
    D) Pour attendre que le joueur meure

    5. Si un joueur touche la part pendant que son cooldown est actif, que fait le script ?
    A) Il double sa vitesse
    B) Il arrête la fonction immédiatement avec return, sans rien changer
    C) Il redémarre le cooldown
    D) Il supprime le dossier « Speed »

    local part = script.Parent
    
    local SPEEDMAX = 50
    
    local COOLDOWN = 1 -- secondes avant de pouvoir re-déclencher
    local cooldowns = {} -- [character] = true pendant le cooldown
    
    part.Touched:Connect(function(plr)
    	local character = plr.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid  then return end
    	
    	if cooldowns[character] then return end
    	cooldowns[character] = true
    	
    	local existingFolder = humanoid:FindFirstChild("Speed")
    	
    	if existingFolder then
    		humanoid.WalkSpeed = existingFolder.Value
    		existingFolder:Destroy()
    	else
    		local folder = Instance.new("IntValue")
    		folder.Name = "Speed"
    		folder.Parent = humanoid
    		folder.Value = humanoid.WalkSpeed
    		humanoid.WalkSpeed = SPEEDMAX
    	end
    	
    	task.wait(COOLDOWN)
    	cooldowns[character] = nil
    	
    end)
    

    Essaye le même système pour faire sauter plus haut :

    	humanoid.JumpHeight = 20
    local part = script.Parent
    
    local SCALEMAX = 4
    
    local COOLDOWN = 1 -- secondes avant de pouvoir re-déclencher
    local cooldowns = {} -- [character] = true pendant le cooldown
    
    part.Touched:Connect(function(plr)
    	local character = plr.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid  then return end
    
    	if cooldowns[character] then return end
    	cooldowns[character] = true
    
    	local existingFolder = humanoid:FindFirstChild("Scale")
    
    	if existingFolder then
    		humanoid.BodyHeightScale.Value = existingFolder.Value
    		humanoid.BodyWidthScale.Value = existingFolder.Value		
    		humanoid.BodyDepthScale.Value = existingFolder.Value	
    		humanoid.HeadScale.Value = existingFolder.Value
    		existingFolder:Destroy()
    	else
    		local folder = Instance.new("IntValue")
    		folder.Name = "Scale"
    		folder.Parent = humanoid
    		folder.Value = humanoid.BodyHeightScale.Value
    		humanoid.BodyHeightScale.Value = SCALEMAX
    		humanoid.BodyWidthScale.Value = SCALEMAX		
    		humanoid.BodyDepthScale.Value = SCALEMAX	
    		humanoid.HeadScale.Value = SCALEMAX
    	end
    
    	task.wait(COOLDOWN)
    	cooldowns[character] = nil
    
    end)
    

    Traverser le plus vite possible autrement ..

    Catégories
    Jeu vidéo ROBLOX

    Devenir invisible en touchant un part

    Rendre transparent le player

    Ce script Roblox rend transparents (invisibles à 75%) les joueurs ou leurs accessoires (comme un chapeau ou une épée) quand ils touchent une pièce (la part). Il vérifie si ce qui a touché la pièce est un personnage avec un Humanoid (un joueur).
    Ensuite, il parcourt toutes les parties du personnage (corps, accessoires) et les rend transparentes.
    Seules les pièces 3D (BasePart, MeshPart) ou les textures (Decal) sont modifiées.

    QCM : Teste ta compréhension !

    1. Que fait ce script quand un joueur touche la pièce ?
    A) Il supprime le joueur.
    B) Il rend le joueur et ses accessoires transparents.
    C) Il change la couleur du joueur en rouge.
    D) Il fait exploser la pièce.

    2. Pourquoi vérifie-t-on if not humanoid then return end ?
    A) Pour éviter que le script ne s’applique aux objets qui ne sont pas des joueurs.
    B) Pour accélérer le jeu.
    C) Pour rendre la pièce invisible.
    D) Pour ajouter un accessoire au joueur.

    3. Que signifie descendant.Transparency = 0.75 ?
    A) La pièce devient complètement invisible.
    B) La pièce devient à 75% transparente (presque invisible).
    C) La pièce clignote.
    D) La pièce devient plus grande.

    4. Quel type d’objet n’est PAS modifié par ce script ?
    A) Un chapeau (Accessory).
    B) Une épée (MeshPart).
    C) Un mur (Part).
    D) Une texture (Decal) sur un accessoire.

    -- Script pour rendre invisible les joueurs qui touchent la part
    local part = script.Parent
    
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid  then return end
    
    	for _, chose in ipairs(character:GetChildren()) do
    		if chose:IsA("Accessory") then
    			-- Rend transparent les BasePart/Decal de l'accessoire
    			for _, descendant in ipairs(chose:GetDescendants()) do
    				if descendant:IsA("BasePart") or descendant:IsA("Decal") then
    					descendant.Transparency = 0.75
    				end
    			end
    		elseif chose:IsA("MeshPart") then
    			-- Le MeshPart lui-même est la part à rendre transparente
    			chose.Transparency = 0.75
    		end
    	end
    end)

    Bascule invisible/visible

    Ce script Roblox permet de rendre un joueur transparent à 50% quand il touche une pièce, puis de le rendre à nouveau visible s’il la touche une deuxième fois.
    Il utilise un délai de 1 seconde (COOLDOWN) pour éviter de déclencher l’effet trop vite.
    Un dossier caché (Transparency) est créé dans le personnage pour « mémoriser » s’il est déjà transparent.
    Seuls les joueurs (avec un Humanoid) sont concernés, et leurs accessoires ou parties du corps deviennent transparents.

    QCM : Teste ta compréhension !

    1. Que fait ce script quand un joueur touche la pièce pour la première fois ?
    A) Il le supprime.
    B) Il le rend transparent à 50%.
    C) Il le rend complètement invisible.
    D) Il le fait sauter.

    2. Pourquoi utilise-t-on cooldowns[character] = true ?
    A) Pour empêcher le joueur de déclencher l’effet plusieurs fois en 1 seconde.
    B) Pour rendre le joueur invincible.
    C) Pour changer la couleur de la pièce.
    D) Pour ajouter un accessoire au joueur.

    3. À quoi sert le dossier Transparency dans le Humanoid ?
    A) À stocker si le joueur est déjà transparent pour inverser l’effet au prochain contact.
    B) À rendre le joueur plus rapide.
    C) À supprimer le personnage.
    D) À afficher un message.

    4. Que se passe-t-il si un joueur touche la pièce une deuxième fois ?
    A) Il devient à nouveau visible (transparence à 0%).
    B) Il devient complètement invisible.
    C) Il explose.
    D) Rien, le script ne fait plus rien.

    -- Script pour rendre invisible les joueurs qui touchent la part
    local part = script.Parent
    
    local TRANSPARENCE_ACTIVE = 0.5
    local TRANSPARENCE_INACTIVE = 0
    local COOLDOWN = 1 -- secondes avant de pouvoir re-déclencher
    
    local cooldowns = {} -- [character] = true pendant le cooldown
    
    local function playerTransparency(character, transparency)
    	for _, chose in ipairs(character:GetChildren()) do
    		if chose:IsA("Accessory") then
    			-- Rend transparent les BasePart/Decal de l'accessoire
    			for _, descendant in ipairs(chose:GetDescendants()) do
    				if descendant:IsA("BasePart") or descendant:IsA("Decal") then
    					descendant.Transparency = transparency
    				end
    			end
    		elseif chose:IsA("MeshPart") then
    			-- Le MeshPart lui-même est la part à rendre transparente
    			chose.Transparency = transparency
    		end
    	end
    end
    
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid then return end
    	if cooldowns[character] then return end
    
    	cooldowns[character] = true
    
    	local existingFolder = humanoid:FindFirstChild("Transparency")
    	local transparency
    
    	if existingFolder then
    		existingFolder:Destroy()
    		transparency = TRANSPARENCE_INACTIVE
    	else
    		local folder = Instance.new("Folder")
    		folder.Name = "Transparency"
    		folder.Parent = humanoid
    		transparency = TRANSPARENCE_ACTIVE
    	end
    
    	playerTransparency(character, transparency)
    
    	task.wait(COOLDOWN)
    	cooldowns[character] = nil
    end)

    Gestion d’un folder pour gérer plusieurs parts pour rendre invisible

    -- Boucle sur toutes les parts du folder des parts pour rendre invisible
    local folder = workspace:FindFirstChild("Zone Invisibilite", true)
    
    
    for _, part in ipairs(folder:GetChildren()) do
    
    	if not part:IsA("BasePart") then return end
    
    	part.Touched:Connect(function(hit)
    		local character = hit.Parent
    		local humanoid = character and character:FindFirstChild("Humanoid")
    		if not humanoid then return end
    		if cooldowns[character] then return end
    
    		cooldowns[character] = true
    
    		local existingFolder = humanoid:FindFirstChild("Transparency")
    		local transparency
    
    		if existingFolder then
    			existingFolder:Destroy()
    			transparency = TRANSPARENCE_INACTIVE
    		else
    			local folder = Instance.new("Folder")
    			folder.Name = "Transparency"
    			folder.Parent = humanoid
    			transparency = TRANSPARENCE_ACTIVE
    		end
    
    		playerTransparency(character, transparency)
    
    		task.wait(COOLDOWN)
    		cooldowns[character] = nil
    	end)
    
    end

    Traverser un mur quand le player est transparent

    Quand un personnage touche la Part, le script vérifie s’il a un Humanoid possédant un attribut/valeur nommé "Transparency" , si oui, il rend la Part traversable (CanCollide = false).

    Quand ce même personnage arrête de toucher la Part (TouchEnded), le script refait la vérification et remet la Part solide (CanCollide = true).

    Résultat : c’est un bloc qui devient traversable uniquement pour les joueurs possédant la valeur « Transparency » (par exemple des joueurs rendus invisibles/fantômes ailleurs dans le jeu), et redevient solide dès qu’ils sont passés.

    QCM : Teste ta compréhension !

    1. Que vérifie le script avant de rendre la Part traversable ?
    A. Que le joueur a un pseudo spécial
    B. Que le personnage possède une valeur nommée « Transparency »
    C. Que le joueur est en l’air
    D. Que la Part est de couleur rouge

    2. Que fait part.CanCollide = false ?
    A. Le bloc devient invisible
    B. Le bloc disparaît définitivement
    C. Le bloc laisse passer les objets/joueurs à travers
    D. Le bloc explose

    3. Quand se déclenche l’événement TouchEnded ?
    A. Quand le joueur commence à toucher la Part
    B. Quand le joueur arrête de toucher la Part
    C. Quand le joueur meurt
    D. Quand le jeu se termine

    4. Que se passe-t-il si un joueur SANS la valeur « Transparency » touche la Part ?
    A. Il traverse quand même le bloc
    B. Rien ne change, la Part reste solide pour lui
    C. Il devient invisible
    D. La Part se détruit

    5. Pourquoi remet-on CanCollide = true dans TouchEnded ?
    A. Pour empêcher d’autres joueurs (sans la bonne valeur) de traverser après
    B. Pour changer la couleur du bloc
    C. Pour supprimer le joueur
    D. Pour recommencer le jeu

    local part = script.Parent
    
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid then return end
    
    	local existingFolder = humanoid:FindFirstChild("Transparency")
    	if not existingFolder then return end
    	part.CanCollide= false
    
    end)
    
    part.TouchEnded:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")
    	if not humanoid then return end
    	
    	local existingFolder = humanoid:FindFirstChild("Transparency")
    	if not existingFolder then return end	
    	part.CanCollide= true
    
    end)
    Catégories
    Jeu vidéo ROBLOX

    Téléportation d’un point A à un point B :

    Voici l’explication du code, ligne par ligne :

    Les variables de départ

    local teleports = script.Parent
    local teleportA = teleports.TeleportA
    local teleportB = teleports.TeleportB

    On récupère deux objets dans le jeu Roblox : la plateforme A (celle sur laquelle on va marcher) et la plateforme B (celle où on va arriver). Ces deux plateformes sont des enfants du script dans l’arbre du jeu.

    L’événement Touched

    teleportA.Touched:Connect(function(hit)

    Touched est un événement Roblox : il se déclenche automatiquement dès que quelque chose touche la plateforme A. Le paramètre hit contient la pièce (la partie du corps) qui l’a touchée.

    La vérification du joueur

    local character = hit.Parent
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if not humanoid or humanoid.Health <= 0 then return end

    On remonte d’un niveau pour trouver le personnage entier (hit.Parent), puis on cherche s’il contient un Humanoid (ce qui prouve que c’est bien un joueur, pas un mur ou une balle). Si rien de valide n’est trouvé, ou si le joueur est mort (Health <= 0), on arrête tout avec return.

    La téléportation

    local offset = Vector3.new(0, 2, 0)
    character:PivotTo(CFrame.new(teleportB.Position + offset))

    Vector3.new(0, 2, 0) crée un décalage de 2 unités vers le haut pour que le joueur atterrisse au-dessus de la plateforme B et pas à l’intérieur. PivotTo est la fonction qui déplace instantanément tout le personnage à une nouvelle position — c’est ça la téléportation !

    Le code complet de la téléportation

    -- Configuration
    local teleports = script.Parent
    local teleportA = teleports.TeleportA
    local teleportB = teleports.TeleportB
    
    teleportA.Touched:Connect(function(hit)
    	-- Récupération du joueur
    	local character = hit.Parent
    	local humanoid  = character and character:FindFirstChildOfClass("Humanoid")
    	if not humanoid or humanoid.Health <= 0 then return end
    	
    	-- Décalage légert vers le haut pour poser le joueur sur la plateforme
    	local offset = Vector3.new(0, 2, 0)
    	character:PivotTo(CFrame.new(teleportB.Position + offset))
    
    end)
    Catégories
    Jeu vidéo ROBLOX

    Crée un tableau de scores

    Objectif : Créé un tableau de scores

    Créer un script pour afficher un tableau de score au joueur sousServerScriptService :

    Renommer le script leaderstats :

    Saisir le code suivant pour un affichage d’une barre de scores :

    local players = game:GetService("Players")
    
    players.PlayerAdded:Connect(function(player)
         local leaderstats = Instance.new("Folder")
         leaderstats.Name = "leaderstats"
         leaderstats.Parent = player
    end)

    Si tu lances ton jeu une barre s’affiche :

    Si le score ne s’affiche pas vérifie :

    Rajoute à ton script un score à afficher :

    local players = game:GetService("Players")
    
    players.PlayerAdded:Connect(function(player)
    
         local leaderstats = Instance.new("Folder")
         leaderstats.Name = "leaderstats"
         leaderstats.Parent = player
    
         local score = Instance.new("IntValue")
         score.Parent = leaderstats
         score.Name = "Score"
         score.Value = 0
    
    end)

    Le score s’affiche si tu lances ton jeu :

    Exemple d’un script pour augmenter le score si le joueur click sur un ClickDetector :

    local clickDetector = script.Parent.ClickDetector
    
    clickDetector.MouseClick:Connect(function(player)
    
          player:WaitForChild("leaderstats").Score.Value += 10
    
    end)

    Exemple d’un script pour augmenter le score si le joueur rentre en collision avec un part :

    local myPart = script.Parent
    
    
    myPart.Touched:Connect(function(hit)
    
    	-- Vérifie si c'est un joueur qui a touché la part
    	local joueur = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
    	if joueur then
    		-- Trouve le score du joueur dans Leaderstats
    		local leaderstats = joueur:FindFirstChild("leaderstats")
    		if leaderstats then
    			local score = leaderstats:FindFirstChild("Score")
    			if score then
    				-- Incrémente le score
    				score.Value = score.Value + 1
    			end
    		end
    	end
    
    end)

    Exemple d’un script pour augmenter le score si le joueur rentre en collision avec un part :

    local myPart = script.Parent
    
    
    myPart.Touched:Connect(function(hit)
    
    	-- Vérifie si c'est un joueur qui a touché la part
    	local joueur = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
    	if joueur then
    		-- Trouve le score du joueur dans Leaderstats
    		local leaderstats = joueur:FindFirstChild("leaderstats")
    		if leaderstats then
    			local score = leaderstats:FindFirstChild("Score")
    			if score then
    				-- Incrémente le score
    				score.Value = score.Value + 1
    			end
    		end
    	end
    
    end)

    Un système de score avec un ModuleScript

    1. Créer un ModuleScript pour gérer les scores

    -- ModuleScript dans ServerScriptService : "ScoreManager"
    local ScoreManager = {}
    
    -- Initialise le Leaderstats pour un joueur
    function ScoreManager.initPlayer(player)
        local leaderstats = Instance.new("Folder", player)
        leaderstats.Name = "leaderstats"
    
        local points = Instance.new("IntValue", leaderstats)
        points.Name = "Score"
        points.Value = 0
    end
    
    -- Met à jour le score d'un joueur
    function ScoreManager.addPoints(player, points)
        local leaderstats = player:FindFirstChild("leaderstats")
        if leaderstats then
            local score = leaderstats:FindFirstChild("Score")
            if score then
                score.Value = score.Value + points
            end
        end
    end
    
    return ScoreManager

    Appel dans scriptServeur pour rajouter des points :

    -- Script dans ServerScriptService
    local ScoreManager = require(game:GetService("ServerScriptService"):WaitForChild("ScoreManager"))
    
    -- Initialiser le Leaderstats pour chaque joueur
    game.Players.PlayerAdded:Connect(function(player)
    	ScoreManager.initPlayer(player)
    end)
    
    local part = workspace.Part -- La Part qui déclenche l'événement
    
    -- Exemple : Ajouter 10 points à un joueur
    part.Touched:Connect(function(otherPart)
    	-- Vérifie que otherPart fait partie d'un personnage
    	local humanoid = otherPart.Parent:FindFirstChild("Humanoid")
    	if humanoid then
    		-- Récupère le joueur associé au personnage
    		local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
    		if player then            
    			ScoreManager.addPoints(player, 10)
    			part:Destroy() -- Supprime la Part après utilisation
    
    		end
    	end
    end)
    Catégories
    Jeu vidéo ROBLOX

    Apprendre Lua sur Roblox – 10 scénarios simples

    Voici les 10 mini-projets interactifs ! Cliquez sur les défi01 à défi10 pour naviguer entre les projets.

    Chaque fiche contient :

    • la description du jeu, les règles,
    • les compétences Lua acquises,
    • un QCM de 5 questions

    La progression suit une logique pédagogique :

    • défi01 à défi03 : bases Roblox (Parts, inputs, GUI)
    • défi04 à défi06 : communication réseau, physique, effets visuels
    • défi07 à défi09 : animations, interactions avancées, données persistantes
    • défi10 : projet complet qui réutilise tout, avec architecture modulaire

    Défi 01 : La Zone Mortelle

    Description

    Une course parsemée de difficultés et de briques mortelles. Le joueur doit traverser des espaces en utilisant des pouvoirs à sa disposition (sauter plus haut, courir plus vite, rétrécir, devenir transparent pour passer à travers les murs. Au contact d’un part mortel, son personnage meurt instantanément (Humanoid.Health = 0). Des zones sûres (parts verts) permettent de souffler avant d’atteindre une zone verte de victoire.

    Règles du jeu

    Rejoignez l’arène verte de victoire à l’autre bout du parcours en utilisant les pouvoirs à votre disposition. Chaque mort vous remet au départ. Pas de limite de tentatives.

    Voir un exemple sous ROBLOX

    Compétences acquises

    • Touched Event
    • Humanoid.Health
    • BasePart properties
    • Script vs Local
    • for _ , part in ipair(parts:GetChildren())
    • Reconnaître un Humanoid
    • Gérer les collisions

    QCM — Testez vos connaissances

    1. Quel événement Roblox détecte le contact avec une part ?

    • OnTouch
    • Touched
    • Hit
    • Collide

    2. Pour tuer un personnage, on modifie quelle propriété du Humanoid ?

    • MaxHealth
    • WalkSpeed
    • Health
    • Jump

    3. Où place-t-on un Script qui affecte le serveur ?

    • StarterGui
    • ReplicatedStorage
    • ServerScriptService
    • LocalScript

    4. Comment récupérer le Humanoid d’un personnage touché ?

    • hit.Humanoid
    • hit.Parent:FindFirstChild(‘Humanoid’)
    • game.Players.Humanoid
    • workspace.Humanoid

    5. Quelle propriété rend une Part non-solide mais visible ?

    • Transparency = 0
    • CanCollide = false
    • Anchored = true
    • Locked = true

    Défi 02 : Speed Runner

    Touches clavier & compétences joueur

    Description

    Un parcours d’obstacles où le joueur peut débloquer une compétence en appuyant sur une touche du clavier. Appuyez sur [F] pour activer un boost d’un saut et vitesse rapide temporaire. Le boost a un cooldown visible et une barre d’énergie.

    Des checkpoints invisibles qui font respawn le joueur au bon endroit si le joueur tombe ou meurt. Un compteur de tours : combien de fois le joueur a terminé le parcours. Un meilleur temps (record) qui s’affiche et se met à jour automatiquement

    Règles du jeu

    Parcourez le parcours le plus vite possible. Utilisez votre touche de compétence au bon moment. Franchissez la ligne d’arrivée. Votre temps est affiché.

    Voir un exemple sous ROBLOX

    Compétences acquises

    • UserInputService
    • ServiceHumanoid.WalkSpeed
    • Humanoid.Jump
    • Powercooldown avec tick()

    QCM — Testez vos connaissances

    1. Quel service Roblox gère les entrées clavier côté client ?
    • InputServiceUser
    • InputService
    • KeyboardService
    • ContextService

    2. Dans quel type de script utilise-t-on UserInputService ?

    • ScriptModule
    • ScriptLocal
    • ScriptServer
    • Script

    3. Comment détecter l’appui sur la touche E ?

    • Enum.KeyCode.E
    • Key.E
    • Input.E
    • Keyboard.E

    4. Quelle propriété du Humanoid contrôle la vitesse de marche ?

    • Speed
    • RunSpeed
    • WalkSpeed
    • MoveSpeed

    5. tick() retourne quoi en Lua Roblox ?

    • Le tick d’horloge en ms
    • Le temps en secondes depuis le lancement
    • Le framerate actuel
    • Le temps depuis le début de la partie

    Défi 03 : Le Magasin de Pouvoirs

    GUI & ScreenGui

    Description

    Un magasin en jeu affiché via un ScreenGui. Le joueur ouvre l’interface avec [G] et voit une liste de pouvoirs à acheter (vitesse, saut, bouclier). Chaque pouvoir a un prix en pièces d’or ramassées dans le monde. L’achat est confirmé par un bouton.

    Règles du jeu

    Collectez des pièces d’or dans la carte. Appuyez sur [G] pour ouvrir la boutique. Achetez des pouvoirs avec vos pièces. Activez vos pouvoirs via les touches attribuées.

    Compétences acquises

    • ScreenGui & Frame
    • TextButton.MouseButton1Click
    • RemoteEvent (achat)
    • leaderstats basiques
    • Visible toggle

    QCM — Testez vos connaissances

    1. Où place-t-on un ScreenGui pour qu’il s’affiche à tous les joueurs ?
    • Workspace
    • StarterGui
    • ReplicatedStorage
    • ServerStorage

    2. Quel événement déclenche un clic sur un TextButton ?

    • MouseButton1Click
    • Clicked
    • OnClick
    • Activated

    3. Comment rendre une Frame invisible via Script ?

    • Frame.Hide()
    • Frame.Enabled = false
    • Frame.Visible = false
    • Frame.Alpha = 0

    4. Un RemoteEvent sert à quoi ?

    • Communiquer entre LocalScript et Script serveur
    • Créer des GUI
    • Détecter les touches
    • Gérer les collisions

    5. Pour déclencher un RemoteEvent depuis le client vers le serveur, on utilise ?

    • RemoteEvent:FireServer()
    • RemoteEvent:FireClient()
    • RemoteEvent:Send()
    • RemoteEvent:Trigger()

    Défi 04 : La Porte Télékinésique

    RemoteEvents & communication Client/Sserveur

    Description

    Des portes et pièges contrôlés en réseau. Quand un joueur marche sur un bouton (Part), un RemoteEvent notifie le serveur qui ouvre la porte correspondante pour TOUS les joueurs. Des pièges s’activent de même en temps réel.

    Règles du jeu

    Explorez la carte coopérativement. Trouvez les boutons cachés qui ouvrent des portes. Un joueur peut sacrifier sa position pour ouvrir le chemin à ses coéquipiers. Atteignez la sortie ensemble.

    Compétences acquises

    • RemoteEvent:FireServer
    • RemoteEvent:FireClient
    • RemoteEvent.OnServerEvent
    • ReplicatedStorage
    • synchronisation multi-joueurs

    QCM — Testez vos connaissances

    1. Où stocke-t-on les RemoteEvents accessibles client ET serveur ?

    • ServerStorage
    • ServerScript
    • ServiceReplicated
    • StorageStarterGui

    2. OnServerEvent est connecté dans quel type de script ?

    • LocalScript
    • Script (serveur)
    • ModuleScript
    • PluginScript

    3. FireClient() envoie un event à ?

    • Tous les joueurs
    • Un joueur spécifique
    • Le serveur
    • Le workspace

    4. FireAllClients() envoie à ?

    • Un joueur
    • Le serveur uniquement
    • Tous les clients connectés
    • Les NPC seulement

    5. Quel est le premier paramètre reçu par OnServerEvent ?

    • Les données envoyées
    • Le joueur (Player) émetteur
    • Le nom du Remote
    • Eventnil

    Défi 05 : Les Plateformes Mobiles

    Mouvement de Parts via Script

    Description

    Des plateformes qui se déplacent selon des trajectoires (haut/bas, gauche/droite, circulaire). Certaines accélèrent, d’autres s’arrêtent selon des conditions (joueur dessus, timer). Utilisez RunService ou des boucles pour animer les positions.

    Règles du jeu

    Sautez de plateforme en plateforme pour atteindre la tour centrale. Les plateformes bougent en continu. Certaines disparaissent après 3 secondes de contact. Atteignez le sommet.

    Compétences acquises

    • CFrame et Vector3
    • RunService.Heartbeat
    • while true do / wait()
    • math.sin() pour oscillation
    • Anchored vs non-Anchored

    1. Quelle propriété utilise-t-on pour déplacer une Part sans physique ?

    • Position seule
    • CFrame
    • Velocity
    • MoveDirection

    2. RunService.Heartbeat s’exécute à quelle fréquence ?

    • 1 fois/seconde
    • Chaque frame (~60fps)
    • 10 fois/seconde
    • À la demande

    3. math.sin() est utile pour créer quel type de mouvement ?

    • Téléportation
    • Mouvement linéaire
    • Oscillation fluide
    • Rotation fixe

    4. Une part Anchored peut-elle être déplacée par CFrame ?

    • Non, elle est immobile
    • Oui, le script peut changer son CFrame
    • Seulement par les joueurs
    • Seulement via TweenService

    5. Vector3.new(0, 5, 0) représente quoi ?

    • Un déplacement de 5 studs vers le bas
    • Un déplacement de 5 studs vers le haut
    • Une rotation de 5 degré
    • sUne mise à l’échelle de 5

    Défi 06 : L’Atelier des Effets

    ParticleEmitter & effets visuels

    Description

    Un laboratoire où le joueur active différents effets visuels : feu, fumée, étincelles, traînées de lumière. Des zones déclenchent des effets via Touched. Le joueur peut ramasser un ‘orbe de feu’ qui attache un effet de flamme à son personnage.

    Règles du jeu

    Explorez le laboratoire et touchez les zones d’activation. Ramassez des orbes pour équiper des effets sur votre personnage. Certains effets boostent vos stats en plus d’être visuels.

    Compétences acquises

    • ParticleEmitter
    • Fire & Smoke objects
    • Attachment points
    • Enabled toggle
    • PointLight & SpotLight

    1. Où attache-t-on un ParticleEmitter dans un modèle 3D ?

    • Directement dans Workspace
    • Dans un Attachment ou une Part
    • Dans StarterGui
    • Dans ServerStorage

    2. Comment activer/désactiver un ParticleEmitter ?

    • ParticleEmitter.Start()
    • ParticleEmitter.Enabled = true/false
    • ParticleEmitter.Visible = true/false
    • ParticleEmitter.Rate = 0

    3. L’objet Fire de Roblox simule quoi ?

    • Un effet de lumière uniquement
    • Des flammes visuelles directement sur une Part
    • Un dégât de brûlure
    • Une explosion

    4. Un PointLight émet la lumière dans quelle direction ?

    • Devant la Part
    • Dans toutes les directions
    • Vers le haut uniquement
    • Vers le bas uniquement

    5. La propriété Rate d’un ParticleEmitter contrôle quoi ?

    • La taille des particules
    • La couleur
    • Le nombre de particules émises par seconde
    • La durée de vie du ParticleEmitter

    Défi 07 : L’Ascenseur Magique

    TweenService & animations fluides

    Description

    Des ascenseurs, portes coulissantes et objets animés avec TweenService. Les transitions sont fluides grâce aux EasingStyle. Un boss oscille sur place avec un Tween en boucle. Des récompenses s’animent quand ramassées (scale up/down).

    Règles du jeu

    Utilisez les ascenseurs pour monter les étages. Chaque étage déverrouille une porte animée. Ramassez les cristaux (avec animation) pour gagner des points. Atteignez le dernier étage.

    Compétences acquises

    • TweenService:Create()
    • TweenInfoEasing
    • Style & Easing
    • DirectionTween:Play() / Pause() / Cancel()
    • Tween.Completed event

    1. Quel service Roblox gère les transitions animées ?

    • AnimationService
    • TweenService
    • RunService
    • PhysicsService

    2. TweenInfo.new() prend quoi comme premier paramètre ?

    • EasingStyle
    • La durée en secondes
    • L’objet à animer
    • Le nombre de répétitions

    3. EasingStyle.Bounce donne quel effet ?

    • Mouvement linéaire
    • Rebond à la fin de l’animation
    • Accélération progressive
    • Pause au milieu

    4. Comment déclencher quelque chose APRÈS la fin d’un Tween ?

    • Tween.OnComplete()
    • Tween.Completed:Wait()
    • wait(tween.duration)
    • TweenService.OnDone()

    5. Peut-on tweener la couleur (Color3) d’une Part ?

    • Non, seulement la position
    • Oui, Color3 est une propriété tweénable
    • Seulement via ParticleEmitter
    • Seulement avec des scripts serveur

    Défi 08 : Le Marchand & Le Détective

    ProximityPrompt & ClickDetector

    Description

    Des PNJ (statues) équipés de ProximityPrompts affichent un menu de dialogue et de commerce quand on s’approche. Des objets dans le décor ont des ClickDetectors qui révèlent des indices. Un coffre s’ouvre au clic après avoir collecté tous les indices.

    Règles du jeu

    Approchez-vous des PNJ pour interagir. Cliquez sur les éléments suspects pour trouver les 5 indices. Apportez les indices au bon PNJ pour ouvrir le coffre au trésor.

    Compétences acquises

    • ProximityPrompt.TriggeredClick
    • Detector.MouseClick
    • distance d’interaction
    • GUI contextuel
    • état de jeu (indices trouvés)

    1. ProximityPrompt.Triggered est écouté depuis quel script ?

    • Uniquement LocalScript
    • Script serveur uniquement
    • Les deux sont possibles
    • ModuleScript seulement

    2. Quelle propriété définit la distance d’activation d’un ProximityPrompt ?

    • RangeMax
    • ActivationDistance
    • TriggerRadius
    • ActivationDistance

    3. ClickDetector.MouseClick passe quoi comme argument ?

    • La Part cliquée
    • Le Player qui a cliqué
    • Les coordonnées du clic
    • Nil

    4. Comment afficher un texte personnalisé sur un ProximityPrompt ?

    • ProximityPrompt.Label
    • ProximityPrompt.Action
    • TextProximityPrompt.Text
    • ProximityPrompt.Title

    5. Quelle est la différence principale entre ClickDetector et ProximityPrompt ?

    • Aucune différence
    • ClickDetector nécessite un clic, ProximityPrompt une touche en s’approchant
    • ProximityPrompt est plus ancien
    • ClickDetector fonctionne sans script

    Défi 09 : Le Grand Tournoi

    Leaderstats & tableau de score

    Description

    Un jeu de compétition avec un classement en temps réel (leaderstats). Points gagnés en touchant des zones, en éliminant des adversaires (PvP désactivable) ou en terminant des épreuves. Le score se met à jour pour tous via le tableau Roblox natif.

    Règles du jeu

    Accumulez des points en 5 minutes. Éliminez des adversaires (+10pts), touchez des zones (+5pts), finissez des épreuves bonus (+25pts). Le joueur avec le plus de points gagne.

    Compétences acquises

    • leaderstats dans PlayerAdded
    • IntValue & StringValue
    • PlayerRemoving cleanup
    • tri et classement
    • DataStoreService (sauvegarde basique)

    1. Comment créer les leaderstats d’un joueur ?

    • Directement dans Workspace
    • Folder nommé ‘leaderstats’ dans le Player
    • Dans ReplicatedStorage
    • Via un RemoteEvent

    2. Quel événement se déclenche quand un joueur rejoint la partie ?

    • Players.PlayerJoined
    • Players.PlayerAdded
    • Players.New
    • PlayerPlayers.OnJoin

    3. Quelle valeur utilise-t-on pour stocker un nombre entier dans leaderstats ?

    • NumberValue
    • IntValue
    • FloatValu
    • eStringValue

    4. DataStoreService sert à quoi ?

    • Afficher le leaderboard
    • Persister des données entre les sessions
    • Communiquer entre scripts
    • Gérer les équipes

    5. PlayerRemoving est utile pour ?

    • Accueillir le joueur
    • Sauvegarder les données avant que le joueur parte
    • Réinitialiser la map
    • Ajouter des points

    Défi 10 : ROBLOX ADVENTURE COMPLETE

    Jeu complet — tous les concepts

    Description

    Un jeu d’aventure complet qui intègre les 9 compétences précédentes : une carte avec zones mortelles (P1), des compétences débloquables (P2), une boutique GUI (P3), des events réseau (P4), des plateformes mobiles (P5), des effets visuels (P6), des animations TweenService (P7), des PNJ interactifs (P8) et un leaderboard complet (P9). Plusieurs niveaux, un boss final avec patterns d’attaque.

    Règles du jeu

    Traversez 3 zones distinctes (Forêt des Pièges, Tour des Pouvoirs, Donjon du Boss). Collectez des cristaux, achetez des améliorations, interagissez avec les PNJ, esquivez les obstacles animés. Battez le boss final et terminez premier au classement. Progression sauvegardée.

    Compétences acquises

    • Architecture modulaire (ModuleScript)
    • Toutes les compétences P1-P9
    • Gestion d’état global
    • Équipes & rounds
    • Optimisation & bonnes pratiques

    1. Un ModuleScript retourne quoi en général ?

    • Nil
    • Un tableau ou une fonction
    • Un RemoteEvent
    • Une GUI

    2. Pour partager du code entre plusieurs scripts, on utilise ?

    • Copy-paste du code
    • ModuleScript + require()
    • RemoteEvent
    • Un Script dans Workspace

    3. Quelle pratique évite les memory leaks avec les events ?

    • Utiliser task.wait()
    • Déconnecter les connexions avec :Disconnect()
    • Supprimer les RemoteEvents
    • Utiliser des LocalScripts uniquement

    4. task.spawn() est préféré à coroutine.wrap() car ?

    • Il est plus lent
    • Il est intégré au scheduler Roblox et plus sûr
    • Il ne fonctionne qu’en serveur
    • Il bloque le thread principal

    5. Dans une architecture propre, où stocke-t-on les ModuleScripts partagés ?

    • Workspace
    • StarterGui
    • ReplicatedStorage ou ServerScript
    • ServiceStarterPack

    Répondez aux 5 question(s) restante(s)…

    Catégories
    Jeu vidéo ROBLOX

    Plaque rebondissante

    As-tu déjà rêvé de faire bondir les joueurs à plusieurs mètres de hauteur dans ton jeu Roblox ? Elles peuvent servir à franchir un obstacle, atteindre une plateforme cachée ou simplement ajouter une touche amusante à un niveau. Dans ce tutoriel, tu vas découvrir comment transformer un simple part en véritable trampoline interactif. Tu verras également comment régler la puissance du rebond pour obtenir différents effets de jeu.

    Rebond du joueur sur la plaque

    Crée un part et dessous un script :

    Saisie ce code dans le script :

    local TweenService = game:GetService("TweenService")
    
    local BOUNCE_SPEED = 120    -- vitesse verticale imposée (studs/s)
    local COOLDOWN     = 0.3   -- évite les rebonds multiples par contact
    
    local trampoline  = script.Parent
    local lastBounce   = {}     -- cooldown par joueur
    
    local function squish(trampoline, bounceSpeed, squishTime)
    	
    	if bounceSpeed==nil then bounceSpeed = BOUNCE_SPEED end
    	
    	-- Remplace directement la vélocité verticale
    	local vel = trampoline.AssemblyLinearVelocity
    	trampoline.AssemblyLinearVelocity = Vector3.new(vel.X, bounceSpeed, vel.Z)
    	
    end
    
    -- Appliquer des propriétés physiques pour que la part soit glissante
    trampoline.CustomPhysicalProperties = PhysicalProperties.new(
    	0.7, -- Density
    	1,   -- Friction
    	1,   -- Elasticity
    	1,   -- FrictionWeight
    	1    -- ElasticityWeight
    )
    -- Appliquer un matériau glissant comme de la glace
    trampoline.Material = Enum.Material.Carpet
    
    trampoline.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid  = character:FindFirstChildWhichIsA("Humanoid")
    	if not humanoid or humanoid.Health <= 0 then return end
    
    	local rootPart = character:FindFirstChild("HumanoidRootPart")
    	if not rootPart then return end
    
    	-- Cooldown par personnage
    	local now = tick()
    	if lastBounce[character] and (now - lastBounce[character]) < COOLDOWN then return end
    	lastBounce[character] = now
    
    	squish(trampoline)
    end)

    Ce script transforme une simple pièce Roblox en trampoline capable de faire rebondir les joueurs lorsqu’ils la touchent. Les variables BOUNCE_SPEED et COOLDOWN définissent respectivement la puissance du rebond et le temps d’attente avant qu’un même joueur puisse rebondir à nouveau. Les propriétés physiques et le matériau de la pièce sont modifiés pour lui donner l’apparence et le comportement d’une surface adaptée au rebond.

    La fonction squish() applique une nouvelle vitesse verticale à la pièce afin de créer l’effet de propulsion vers le haut.

    L’événement Touched détecte lorsqu’un objet entre en contact avec le trampoline et vérifie qu’il s’agit bien d’un personnage vivant possédant un Humanoid. Un système de cooldown mémorise l’instant du dernier rebond de chaque joueur afin d’éviter plusieurs déclenchements successifs lorsque le personnage reste en contact avec le trampoline.

    Animation de la plaque comme un trampoline

    Par rapport à la version précédente, le script suivant ajoute un effet visuel d’écrasement et de retour à la forme initiale, ce qui donne davantage l’impression qu’il s’agit d’un véritable trampoline.

    Une nouvelle variable originalSize mémorise la taille initiale de la plaque afin de pouvoir la restaurer après l’animation. La constante SQUISH_TIME définit la durée de l’animation de compression et de retour à la normale. La table isSquishing empêche que plusieurs animations soient lancées en même temps sur la même plaque, ce qui éviterait des déformations incohérentes. Le service TweenService est utilisé pour créer une animation fluide plutôt qu’un changement instantané de taille.

    Lorsqu’un joueur rebondit, la plaque s’aplatit : sa hauteur diminue tandis que sa largeur et sa longueur augmentent légèrement. Cela reproduit visuellement le comportement d’un trampoline qui se comprime sous le poids du joueur. Après un court délai, une seconde animation redonne progressivement à la plaque sa taille d’origine, donnant l’impression qu’elle reprend sa forme après avoir propulsé le joueur.

    L’effet visuel est synchronisé avec le rebond du joueur, ce qui rend l’interaction plus réaliste et plus agréable à observer.

    local TweenService = game:GetService("TweenService")
    
    local BOUNCE_SPEED = 120    -- vitesse verticale imposée (studs/s)
    local COOLDOWN     = 0.3   -- évite les rebonds multiples par contact
    local SQUISH_TIME  = 0.08  -- durée de l'étirement en secondes
    
    local trampoline  = script.Parent
    
    local lastBounce   = {}     -- cooldown par joueur
    local isSquishing  = {}		-- marquage de la part en état d'étirement
    
    local function squish(trampoline, bounceSpeed, squishTime)
    	
    	if bounceSpeed==nil then bounceSpeed = BOUNCE_SPEED end
    	if squishTime==nil then squishTime = SQUISH_TIME end
    
    	local originalSize = trampoline.Size
    
    	-- Remplace directement la vélocité verticale
    	local vel = trampoline.AssemblyLinearVelocity
    	trampoline.AssemblyLinearVelocity = Vector3.new(vel.X, bounceSpeed, vel.Z)
    	
    	if isSquishing[trampoline] then return end
    	isSquishing[trampoline] = true
    	local tweenInfo = TweenInfo.new(squishTime, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
    	TweenService:Create(trampoline, tweenInfo, {
    		Size = Vector3.new(originalSize.X * 1.05, originalSize.Y * 0.4, originalSize.Z * 1.05)
    	}):Play()
    	task.delay(SQUISH_TIME, function()
    		TweenService:Create(trampoline, tweenInfo, { Size = originalSize }):Play()
    		task.delay(SQUISH_TIME, function() isSquishing[trampoline] = false end)
    	end)
    end
    
    -- Appliquer des propriétés physiques pour que la part soit glissante
    trampoline.CustomPhysicalProperties = PhysicalProperties.new(
    	0.7, -- Density
    	1,   -- Friction
    	1,   -- Elasticity
    	1,   -- FrictionWeight
    	1    -- ElasticityWeight
    )
    -- Appliquer un matériau glissant comme de la glace
    trampoline.Material = Enum.Material.Carpet
    
    trampoline.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid  = character:FindFirstChildWhichIsA("Humanoid")
    	if not humanoid or humanoid.Health <= 0 then return end
    
    	local rootPart = character:FindFirstChild("HumanoidRootPart")
    	if not rootPart then return end
    
    	-- Cooldown par personnage
    	local now = tick()
    	if lastBounce[character] and (now - lastBounce[character]) < COOLDOWN then return end
    	lastBounce[character] = now
    
    	squish(trampoline)
    end)
    

    Système de plaques rebondissantes

    Modifie la structure en créant un Folder, sous le folder ton script et la part, puis duplique la plaque rebondissante plusieurs fois :

    Modifie ton script pour lire tous les parts rebondissants :

    local TweenService = game:GetService("TweenService")
    
    local BOUNCE_SPEED = 120    -- vitesse verticale imposée (studs/s)
    local COOLDOWN     = 0.3   -- évite les rebonds multiples par contact
    local SQUISH_TIME  = 0.08  -- durée de l'étirement en secondes
    
    local trampolines  = script.Parent
    local lastBounce   = {}     -- cooldown par joueur
    local isSquishing  = {}		-- marquage de la part en état d'étirement
    
    local function squish(trampoline, bounceSpeed, squishTime)
    
    	if bounceSpeed==nil then bounceSpeed = BOUNCE_SPEED end
    	if squishTime==nil then squishTime = SQUISH_TIME end
    	
    	local originalSize = trampoline.Size
    	
    	-- Remplace directement la vélocité verticale
    	local vel = trampoline.AssemblyLinearVelocity
    	trampoline.AssemblyLinearVelocity = Vector3.new(vel.X, bounceSpeed, vel.Z)
    
    	if isSquishing[trampoline] then return end
    	isSquishing[trampoline] = true
    	local tweenInfo = TweenInfo.new(squishTime, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
    	TweenService:Create(trampoline, tweenInfo, {
    		Size = Vector3.new(originalSize.X * 1.05, originalSize.Y * 0.4, originalSize.Z * 1.05)
    	}):Play()
    	task.delay(SQUISH_TIME, function()
    		TweenService:Create(trampoline, tweenInfo, { Size = originalSize }):Play()
    		task.delay(SQUISH_TIME, function() isSquishing[trampoline] = false end)
    	end)
    end
    
    for _, trampoline in ipairs(trampolines:GetChildren()) do
    	if not trampoline:IsA("BasePart") then continue end
    
    	-- Appliquer des propriétés physiques pour que la part soit glissante
    	trampoline.CustomPhysicalProperties = PhysicalProperties.new(
    		0.7, -- Density
    		1,   -- Friction
    		1,   -- Elasticity
    		1,   -- FrictionWeight
    		1    -- ElasticityWeight
    	)
    	-- Appliquer un matériau glissant comme de la glace
    	trampoline.Material = Enum.Material.Carpet
    
    
    
    	trampoline.Touched:Connect(function(hit)
    		local character = hit.Parent
    		local humanoid  = character:FindFirstChildWhichIsA("Humanoid")
    		if not humanoid or humanoid.Health <= 0 then return end
    
    		local rootPart = character:FindFirstChild("HumanoidRootPart")
    		if not rootPart then return end
    
    		-- Cooldown par personnage
    		local now = tick()
    		if lastBounce[character] and (now - lastBounce[character]) < COOLDOWN then return end
    		lastBounce[character] = now
    
    		squish(trampoline)
    	end)
    	
    end
    Catégories
    Jeu vidéo ROBLOX

    Plaque glissante pour le joueur

    Dans beaucoup de jeux Roblox, il existe des zones spéciales qui changent complètement la manière de jouer. Imagine un sol où ton personnage se met à glisser tout seul, comme sur de la glace, sans pouvoir s’arrêter immédiatement. Ou encore une pente qui accélère ton déplacement, te propulsant vers une nouvelle plateforme. Ces effets simples transforment un niveau classique en un vrai parcours d’obstacles amusant et dynamique. Dans ce tutoriel, tu vas apprendre à créer ce type de mécanismes toi-même avec Lua dans Roblox Studio. Tu vas découvrir comment contrôler le comportement d’un joueur lorsqu’il touche une zone spéciale. Tu vas progresser étape par étape pour comprendre comment la physique du jeu peut être modifiée. À la fin, tu seras capable de concevoir tes propres zones de glisse comme dans les vrais jeux d’obby.

    Ce tutoriel est organisé en trois parties :

    • La première te montrera comment créer une plaque glissante simple pour faire “patiner” un joueur.
    • La deuxième expliquera comment gérer une plaque en pente pour influencer la direction du déplacement.
    • Enfin, la troisième partie te permettra de combiner plusieurs plaques glissantes pour créer un parcours complet et dynamique.

    Plaque glissante

    Crée un part puis dessous un script :

    Ce script transforme une Part en surface glissante grâce à des propriétés physiques qui réduisent les frottements et lui donnent l’apparence de la glace. Lorsqu’un joueur touche cette Part, le script vérifie qu’il s’agit bien d’un personnage et récupère son HumanoidRootPart, qui représente le centre de son déplacement. Il calcule ensuite la direction dans laquelle regarde le joueur à l’aide du LookVector. La Part reçoit alors une vitesse SPEED qui la fait glisser dans la direction choisie pendant une durée définie SLIDER_LENGTH. Enfin, après ce délai, la vitesse est remise à zéro pour arrêter la glissade.

    -- Script pour une part qui glisse sur un joueur lorsqu'il la touche
    local part = script.Parent
    
    -- Appliquer des propriétés physiques pour que la part soit glissante
    part.CustomPhysicalProperties = PhysicalProperties.new(
    	0.7, -- Density
    	0,   -- Friction
    	0,   -- Elasticity
    	0,   -- FrictionWeight
    	1    -- ElasticityWeight
    )
    -- Appliquer un matériau glissant comme de la glace
    part.Material = Enum.Material.Ice
    
    -- Vitesse de déplacement de la glissade
    local SPEED = 15
    local SLIDER_LENGTH = 1
    
    -- Fonction appelée lorsque la part est touchée
    part.Touched:Connect(function(hit)
    	-- Vérifier si l'objet touché est un personnage
    	local character = hit:FindFirstAncestorOfClass("Model")
    	if not character then return end
    	-- Récupérer le joueur et sa racine
    	local rootPart = character:FindFirstChild("HumanoidRootPart")
    	if not rootPart then return end
        -- Récupérer la direction de la caméra du joueur
    	local dir = rootPart.CFrame.LookVector
    	-- Appliquer une impulsion sur la part pour faire glisser le joueur dans la direction de la caméra
    	part.AssemblyLinearVelocity = dir * SPEED
    	-- Arrêter la glissade après un délai
    	task.spawn(function()
    		task.wait(SLIDER_LENGTH)
    		part.AssemblyLinearVelocity = Vector3.zero		
    		end)
    
    end)

    Pente glissante

    Modifie le code pour permettre à la plaque glissante de tenir compte de son inclinaison.

    Une nouvelle fonction, getSurfaceInclination, calcule la direction naturelle de la pente à partir de la gravité et de la normale de la surface. La gravité indique toujours le bas, tandis que la normale renseigne sur l’orientation de la plaque. En combinant ces deux informations, le script détermine la direction dans laquelle un objet glisserait naturellement sur la pente.

    Lorsque le joueur touche la plaque, le script calcule cette direction de glissade et vérifie si elle est suffisamment importante. Si la plaque est inclinée, la vitesse est appliquée dans le sens de la pente afin de simuler une descente naturelle. Si la plaque est horizontale, il n’y a pas de direction de pente significative : le joueur glisse alors dans la direction vers laquelle il regarde. Grâce à cet ajout, le même script peut gérer aussi bien une plaque plate qu’une plaque inclinée, ce qui rend le comportement plus réaliste et permet de créer des parcours plus variés.

    -- Script pour une part qui glisse sur un joueur lorsqu'il la touche
    local part = script.Parent
    
    -- Appliquer des propriétés physiques pour que la part soit glissante
    part.CustomPhysicalProperties = PhysicalProperties.new(
    	0.7, -- Density
    	0,   -- Friction
    	0,   -- Elasticity
    	0,   -- FrictionWeight
    	1    -- ElasticityWeight
    )
    -- Appliquer un matériau glissant comme de la glace
    part.Material = Enum.Material.Ice
    
    -- Vitesse de déplacement de la glissade
    local SPEED = 15
    local SLIDER_LENGTH = 1
    
    local function getSurfaceInclination(hit)
    	-- Récupérer la direction de la gravité
    	local gravity = Vector3.new(0, -1, 0)
    	-- Récupérer la normale de la surface de la part
    	-- la normale est un vecteur unitaire perpendiculaire à la surface
    	-- qui indique “dans quel sens la surface est orientée"
    	local normal = part.CFrame.UpVector
    	-- enlève la composante perpendiculaire à la surface
    	local slopeDirection = gravity - normal * gravity:Dot(normal)
    	return slopeDirection.Unit
    end
    
    -- Fonction appelée lorsque la part est touchée
    part.Touched:Connect(function(hit)
    	-- Vérifier si l'objet touché est un personnage
    	local character = hit:FindFirstAncestorOfClass("Model")
    	if not character then return end
    	-- Récupérer le joueur et sa racine
    	local rootPart = character:FindFirstChild("HumanoidRootPart")
    	if not rootPart then return end
        -- Récupérer la direction de la caméra du joueur
    	local dir = rootPart.CFrame.LookVector
    	-- Récuoération du sens de la pente de la part par rapport à la gravité
    	local slopeDirection = getSurfaceInclination(part)
    
    	-- Glissade en fonction si pente de la part ou part horizontale
    	if slopeDirection.Magnitude > 0.1 then
    		-- Appliquer une impulsion sur la part pour faire glisser le joueur dans la direction de la pente
    		part.AssemblyLinearVelocity = slopeDirection * SPEED
    	else
    		-- Appliquer une impulsion sur la part pour faire glisser le joueur dans la direction de la caméra
    		part.AssemblyLinearVelocity = dir * SPEED
    		-- Arrêter la glissade après un délai
    		task.spawn(function()
    			task.wait(SLIDER_LENGTH)
    			part.AssemblyLinearVelocity = Vector3.zero		
    		end)
    	end
    
    end)

    Systèmes de plaques et pentes glissantes

    Dans cette nouvelle version, le script ne gère plus une seule plaque glissante mais un ensemble de plaques regroupées dans un dossier (Folder). Au démarrage, le script récupère tous les objets contenus dans ce dossier puis les parcourt un par un grâce à une boucle.

    local folder = script.Parent
    local parts = folder:GetChildren()
    
    for _, part in pairs(parts) do
    
    end

    Une vérification est effectuée pour s’assurer que chaque objet est bien une BasePart afin d’éviter les erreurs avec d’autres types d’objets.

    if not part:IsA("BasePart") then continue end

    Pour chaque plaque trouvée, les propriétés physiques et le matériau de glace sont appliqués automatiquement. Cela évite de dupliquer le même script sur chaque plaque du parcours. La fonction de calcul de la pente est ensuite associée à chaque plaque afin que son inclinaison soit prise en compte individuellement. Enfin, un événement Touched est créé pour chacune d’elles : lorsqu’un joueur touche une plaque, le script utilise les caractéristiques propres à cette plaque (orientation, pente, vitesse de glisse) pour déterminer son déplacement.

    Grâce à cette modification, il devient très simple de créer un parcours complet composé de nombreuses surfaces glissantes. Il suffit d’ajouter ou de supprimer des plaques dans le dossier pour que le script les prenne automatiquement en charge, sans aucune modification supplémentaire du code.

    -- Script pour une part qui glisse sur un joueur lorsqu'il la touche
    local folder = script.Parent
    local parts = folder:GetChildren()
    
    for _, part in pairs(parts) do
    	
    	if not part:IsA("BasePart") then continue end
    	
    	-- Appliquer des propriétés physiques pour que la part soit glissante
    	part.CustomPhysicalProperties = PhysicalProperties.new(
    		0.7, -- Density
    		0,   -- Friction
    		0,   -- Elasticity
    		0,   -- FrictionWeight
    		1    -- ElasticityWeight
    	)
    	-- Appliquer un matériau glissant comme de la glace
    	part.Material = Enum.Material.Ice
    
    	-- Vitesse de déplacement de la glissade
    	local SPEED = 15
    	local SLIDER_LENGTH = 3
    
    	local function getSurfaceInclination(hit)
    		-- Récupérer la direction de la gravité
    		local gravity = Vector3.new(0, -1, 0)
    		-- Récupérer la normale de la surface de la part
    		-- la normale est un vecteur unitaire perpendiculaire à la surface
    		-- qui indique “dans quel sens la surface est orientée"
    		local normal = part.CFrame.UpVector
    		-- enlève la composante perpendiculaire à la surface
    		local slopeDirection = gravity - normal * gravity:Dot(normal)
    		return slopeDirection.Unit
    	end
    	
    	-- Fonction appelée lorsque la part est touchée
    	part.Touched:Connect(function(hit)
    		-- Vérifier si l'objet touché est un personnage
    		local character = hit:FindFirstAncestorOfClass("Model")
    		if not character then return end
    		-- Récupérer le joueur et sa racine
    		local rootPart = character:FindFirstChild("HumanoidRootPart")
    		if not rootPart then return end
    		-- Récupérer la direction de la caméra du joueur
    		local dir = rootPart.CFrame.LookVector
    		-- Récuoération du sens de la pente de la part par rapport à la gravité
    		local slopeDirection = getSurfaceInclination(part)
    
    		-- Glissade en fonction si pente de la part ou part horizontale
    		if slopeDirection.Magnitude > 0.1 then
    			-- Appliquer une impulsion sur la part pour faire glisser le joueur dans la direction de la pente
    			part.AssemblyLinearVelocity = slopeDirection * SPEED
    		else
    			-- Appliquer une impulsion sur la part pour faire glisser le joueur dans la direction de la caméra
    			part.AssemblyLinearVelocity = dir * SPEED
    			-- Arrêter la glissade après un délai
    			task.spawn(function()
    				task.wait(SLIDER_LENGTH)
    				part.AssemblyLinearVelocity = Vector3.zero		
    			end)
    		end
    
    	end)
    
    end
    Catégories
    Jeu vidéo ROBLOX

    Créer une plaque de faible gravité

    Dans ce tutoriel, tu vas créer une plaque spéciale qui modifie la gravité lorsque le joueur marche dessus.

    Grâce à cette plaque, les personnages pourront :

    • sauter beaucoup plus haut ;
    • retomber plus lentement ;
    • atteindre des plateformes normalement inaccessibles.

    Ce type de mécanisme est souvent utilisé dans les jeux de science-fiction, les parcours d’obstacles (Obby) ou les bases spatiales.

    Comprendre la gravité

    La gravité est la force qui attire les objets vers le sol.

    Sur Terre, lorsque tu sautes :

    1. tu montes ;
    2. tu ralentis ;
    3. tu redescends.

    Dans Roblox, la gravité agit exactement de la même manière.

    Si on la diminue :

    • les sauts deviennent plus grands ;
    • les chutes sont plus lentes ;
    • les déplacements semblent plus légers.

    Solution 1 : Modifier la gravité pour tout le monde

    Dans cette version, lorsqu’un joueur active la plaque, la gravité du jeu entier est modifiée.

    Conséquences

    • tous les joueurs sont affectés ;
    • tous les sauts deviennent plus grands ;
    • tous les objets physiques réagissent également à la nouvelle gravité.

    Cette solution est simple à mettre en place mais peut rendre le jeu imprévisible si plusieurs joueurs jouent en même temps.

    Exemple de situation

    Imaginons :

    • Paul marche sur la plaque ;
    • la gravité est divisée par deux.

    Même les autres joueurs situés à l’autre bout de la carte profiteront immédiatement de cet effet.

    Créer une plaque de non gravité

    Commence par construire une Part qui servira de plaque spéciale.

    Tu peux lui donner :

    • une couleur vive ;
    • un matériau futuriste ;
    • un effet lumineux.

    Les joueurs comprendront ainsi qu’il s’agit d’une zone particulière du parcours.

    Détecter l’entrée du joueur

    Lorsque le personnage marche sur la plaque, le jeu doit détecter le contact.

    Cette détection permet de savoir :

    • quel joueur est entré dans la zone ;
    • quand appliquer l’effet de faible gravité.

    C’est le même principe que pour une zone de téléportation ou un checkpoint.

    Puis un script :

    -- référence au part pour le changement de gravité
    local part = script.Parent
    
    -- détection du joueur qui touche la part
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")	
    	if not humanoid then return end
    	-- changement de gravité à 10 au moment de la collision
    	workspace.Gravity = 10
    end)

    Créer une plaque pour retrouver la gravité

    Commence par construire une Part qui servira de plaque spéciale .

    Puis un script :

    -- référence de la part pour retourner la gravité à 196.2
    local part = script.Parent
    
    -- détection du joueur qui touche la part
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local humanoid = character and character:FindFirstChild("Humanoid")	
    	if not humanoid then return end
    	-- retour de la gravité à 196.2 au moment de la collision
    	workspace.Gravity = 196.2
    end)

    Solution 2 : Modifier la gravité pour un seul joueur

    Dans cette version, seul le joueur qui touche la plaque bénéficie de l’effet.

    Les autres joueurs continuent à jouer normalement.

    Cette méthode est souvent préférable dans un jeu multijoueur car chacun peut vivre sa propre expérience.

    Comment simuler une faible gravité pour un joueur ?

    Comme la gravité du monde est partagée par tous, on ne peut pas simplement changer la gravité globale pour un seul joueur.

    On utilise donc une autre technique :

    • augmenter sa puissance de saut ;
    • ralentir sa descente ;
    • modifier certaines propriétés de déplacement.

    Le résultat ressemble à une gravité plus faible sans affecter les autres joueurs.

    Script à modifier pour la plaque de changement de gravité pour un seul joueur :

    -- référence au part pour le changement de gravité
    local part = script.Parent
    
    -- détection du joueur qui touche la part
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local hrp = character and character:WaitForChild("HumanoidRootPart")
    	
    	if not hrp then return end
    	
    	if hrp:FindFirstChild("GravityAttachment") then return end -- évite les doublons
    	
    	-- 1. Créer une pièce jointe (Attachment) requise pour VectorForce
    	local attachment = Instance.new("Attachment")
    	attachment.Name = "GravityAttachment"
    	attachment.Parent = hrp
    
    	-- 2. Créer la force physique (VectorForce)
    	local vectorForce = Instance.new("VectorForce")
    	vectorForce.Name = "CustomGravityForce"
    	vectorForce.Attachment0 = attachment
    	vectorForce.ApplyAtCenterOfMass = true
    	vectorForce.RelativeTo = Enum.ActuatorRelativeTo.World
    
    	-- 3. Calculer la masse totale du personnage
    	local totalMass = 0
    	for _, part in ipairs(character:GetDescendants()) do
    		if part:IsA("BasePart") then
    			totalMass = totalMass + part:GetMass()
    		end
    	end
    
    	-- 4. Appliquer une force vers le haut pour réduire la gravité ressentie
    	-- Exemple : contrer 60% de la gravité (le joueur se sentira plus léger)
    	local gravityCounterFactor = 0.6 
    	local upwardForce = totalMass * workspace.Gravity * gravityCounterFactor
    
    	vectorForce.Force = Vector3.new(0, upwardForce, 0)
    	vectorForce.Parent = hrp
    end)

    Script à modifier pour retrouver la gravité normal pour un seul joueur :

    -- référence de la part pour retourner la gravité à 196.2
    local part = script.Parent
    
    -- détection du joueur qui touche la part
    part.Touched:Connect(function(hit)
    	local character = hit.Parent
    	local hrp = character and character:FindFirstChild("HumanoidRootPart")
    	if not hrp then return end
    	
    	-- Trouver et supprimer l'Attachment
    	local attachment = hrp:FindFirstChild("GravityAttachment")
    	if attachment then
    		attachment:Destroy()
    	end
    
    	-- Trouver et supprimer le VectorForce
    	local vectorForce = hrp:FindFirstChild("CustomGravityForce")
    	if vectorForce then
    		vectorForce:Destroy()
    	end
    	
    end)