Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

Zones de Boost

Ici, tu vas apprendre à coder des boosts pour rendre ton personnage plus petit, transparent, plus rapide ou capable de sauter plus haut.
Tu vas découvrir comment modifier ton personnage avec des scripts simples en Lua, le langage de Roblox.

Créer une base avec 4 pièces (parts) dans Roblox. Chaque pièce active ou désactive un boost (ex. : transparence, taille réduite, saut plus haut, course plus rapide) quand le joueur la traverse.

Ce que tu vas apprendre :

  1. Lire la structure hiérarchique sous workspace :
    • Utiliser une boucle for pour parcourir toutes les pièces dans le jeu.
    • Reconnaître chaque part grâce à son nom (ex. : MoreJump, MoreSpeed, etc.).
  2. Gérer l’événement de collision (Touched) :
    • Détecter quand un joueur touche une part avec part.Touched:Connect().
    • Vérifier si l’objet qui touche est bien un joueur (en cherchant un Humanoid).
  3. Appliquer ou retirer le boost :
    • Utiliser des conditions (if/else) pour savoir quel boost activer en fonction du nom de la part.
      • local existingFolder = humanoid:FindFirstChild(« Speed »)
        if existingFolder then
    • Modifier les propriétés du joueur (ex. : Humanoid.WalkSpeed pour la vitesse, Humanoid.JumpPower pour le saut).
  4. Gérer un cooldown :
    • Ajouter un délai (task.delay(COOLDOWN_DURATION)) pour éviter que le joueur active le boost trop souvent.
    • Utiliser une table (activeCooldowns) pour suivre les joueurs en cooldown.

Résultat :
Un système où chaque part active/désactive un boost différent, avec une gestion propre des collisions et des délais

Ce script exemple permet de créer des zones spéciales dans Roblox qui, lorsqu’un joueur les touche, augmentent temporairement sa hauteur de saut (par exemple, pour sauter plus haut). Après avoir touché la zone, le joueur doit attendre un certain temps (COOLDOWN_DURATION) avant de pouvoir réutiliser l’effet.

Objets à créer dans le Workspace de Roblox

Pour que le script fonctionne, il faut créer ces éléments dans Roblox Studio :

  1. Un dossier nommé ZonesBoost dans le Workspace :
    • C’est ici que seront placées toutes les zones de boost.
    • Comment faire : Dans l’onglet Explorer, cliquez droit sur WorkspaceInsert ObjectFolder → Renommez-le en ZonesBoost.
  2. Des pièces (Parts) nommées MoreJump dans le dossier ZonesBoost :
    • Ce sont les zones que le joueur pourra toucher pour activer le boost.
    • Comment faire :
      • Insérez une Part (cliquez droit sur ZonesBoostInsert ObjectPart).
      • Renommez-la en MoreJump.
      • Ajustez sa taille et sa position pour qu’elle soit visible et accessible dans le jeu.
      • Répétez pour ajouter plusieurs zones si besoin.

Exemple de script pour sauter plus haut

local ZONES_FOLDER = workspace:WaitForChild("ZonesBoost")
local JUMP_MAX = 80
local COOLDOWN_DURATION = 1  -- en secondes
local activeCooldowns = {}  -- [character] = true si en cooldown

-- Parcourir uniquement les enfants directs du dossier (pas les descendants)
for _, part in ipairs(ZONES_FOLDER:GetDescendants()) do
	if not (part:IsA("BasePart") and part.Name == "MoreJump") then continue end

	part.Touched:Connect(function(hit)
		-- Vérifier que l'objet qui a touché est bien un personnage
		local character = hit.Parent
		if not character then return end

		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not humanoid then return end

		-- Vérifier le cooldown
		if activeCooldowns[character] then return end
		activeCooldowns[character] = true

		-- Sauvegarder ou restaurer la hauteur de saut
		local jumpValue = humanoid:FindFirstChild("Jump")
		if jumpValue then
			humanoid.JumpHeight = jumpValue.Value
			jumpValue:Destroy()
		else
			jumpValue = Instance.new("IntValue")
			jumpValue.Name = "Jump"
			jumpValue.Value = humanoid.JumpHeight
			jumpValue.Parent = humanoid
			humanoid.JumpHeight = JUMP_MAX
		end

		-- Réinitialiser le cooldown après le délai
		task.delay(COOLDOWN_DURATION, function()
			activeCooldowns[character] = nil
		end)
	end)
end

Déclaration des variables globales

local ZONES_FOLDER = workspace.ZonesBoost
local JUMP_MAX = 80
local COOLDOWN_DURATION = 1 -- secondes
local activeCooldowns = {} -- [character] = true pendant le cooldown
  • ZONES_FOLDER : Référence au dossier ZonesBoost dans le Workspace. C’est ici que le script va chercher les zones de boost.
  • JUMP_MAX : La hauteur de saut maximale (80) appliquée quand le joueur touche une zone.
  • COOLDOWN_DURATION : Temps d’attente (1 seconde) avant que le joueur puisse réutiliser le boost.
  • activeCooldowns : Une table (comme un dictionnaire) qui stocke si un joueur est en cooldown ou non.
    • Exemple : activeCooldowns[character] = true signifie que le joueur ne peut pas encore réutiliser le boost.

Récupérer les objets du Workspace

for _, part in ipairs(folder:GetDescendants()) do
  • ZONES_FOLDER:GetDescendants() : Récupère tous les objets (y compris les sous-objets) dans le dossier ZonesBoost.
  • ipairs : Parcourt la liste des objets un par un.
  • for _, part in ... :
    • _ est une variable non utilisée (on s’intéresse seulement à part).
    • part représente chaque objet dans le dossier.

Filtrer les objets valides

if not (part:IsA("BasePart") and part.Name=="MoreJump") then continue end
  • part:IsA("BasePart") : Vérifie si l’objet est une Part (un bloc 3D dans Roblox).
  • part.Name=="MoreJump" : Vérifie si la Part s’appelle MoreJump.
  • continue : Si la condition n’est pas remplie, on passe à l’objet suivant (on ignore les autres objets).

Détecter la collision avec Touched

part.Touched:Connect(function(plr)
  • Touched : Événement déclenché quand un objet entre en collision avec la Part.
  • plr : Représente l’objet qui a touché la Part (ici, ce sera le personnage du joueur).

Récupérer le joueur et son Humanoid

local character = plr.Parent
local humanoid = character and character:FindFirstChild("Humanoid")
if not humanoid then return end
  • plr.Parent : Le parent de plr est le modèle du personnage (le joueur).
  • character:FindFirstChild("Humanoid") : Cherche l’Humanoid dans le personnage.
    • L’Humanoid est un composant Roblox qui gère les propriétés du personnage (comme la hauteur de saut).
  • if not humanoid then return end : Si le personnage n’a pas d’Humanoid, on arrête la fonction (cas rare, mais possible).

Gérer le COOLDOWN

if activeCooldowns[character] then return end
activeCooldowns[character] = true
  • activeCooldowns[character] : Vérifie si le personnage est déjà en cooldown.
    • Si oui (true), on arrête la fonction avec return.
    • Si non, on active le cooldown pour ce personnage : activeCooldowns[character] = true.

Sauvegarder et restaurer la hauteur de saut

local jumpValue = humanoid:FindFirstChild("Jump")

if jumpValue then
humanoid.JumpHeight = jumpValue.Value
existingFolder:Destroy()
else
jumpValue = Instance.new("IntValue")
jumpValue.Name = "Jump"
jumpValue.Parent = humanoid
jumpValue.Value = humanoid.JumpHeight
humanoid.JumpHeight = JUMPMAX
end
  • jumpValue : Cherche si l’Humanoid a déjà un enfant nommé Jump (un IntValue qui stocke la hauteur de saut d’origine).
    • Si Jump existe :
      • On restaure la hauteur de saut d’origine (jumpVallue.Value).
      • On supprime le IntValue car il n’est plus utile.
    • Si Jump n’existe pas :
      • On crée un IntValue nommé Jump.
      • On y stocke la hauteur de saut actuelle (humanoid.JumpHeight).
      • On applique la nouvelle hauteur de saut (JUMPMAX = 80).

Attendre la fin du COOLDOWN

task.delay(COOLDOWN_DURATION)
activeCooldowns[character] = nil
  • task.delay(COOLDOWN_DURATION) : Attend 1 seconde (la valeur de COOLDOWN).
  • activeCooldowns[character] = nil : Supprime le cooldown pour ce personnage, qui peut maintenant réutiliser le boost.

Pourquoi le COOLDOWN ?

  • Eviter les nombreux événements de collision : Sans cooldown, le joueur spamme le boost en touchant rapidement la zone plusieurs fois.
  • Éviter les bugs : Sans cooldown, le script pourrait s’exécuter trop souvent et causer des problèmes.

Résumé des concepts clés

ConceptExplication
WorkspaceL’espace 3D où se trouvent tous les objets du jeu.
BasePartUne pièce de base dans Roblox (ex. : un cube, une sphère).
TouchedÉvénement déclenché quand un objet entre en collision avec un autre.
HumanoidComposant qui contrôle les propriétés d’un personnage (vie, saut, etc.).
IntValueUn objet Roblox qui stocke un nombre entier (ici, la hauteur de saut d’origine).
activeCooldownsTable qui suit quels joueurs sont en cooldown.
task.delay()Fonction qui pause le script pendant un certain temps.

Exemple d’un script pour gérer plusieurs Boosts

-- ==================== SERVICES ====================
local Players = game:GetService("Players")

-- ==================== CONFIGURATION ====================
local ZONES_FOLDER = workspace:WaitForChild("ZonesBoost")
local COOLDOWN_DURATION = 1 -- secondes avant de pouvoir re-déclencher une zone

-- Suivi des cooldowns actifs par personnage (évite le spam de déclenchement)
local activeCooldowns = {} -- [character] = true pendant le cooldown

-- ==================== EFFETS APPLIQUÉS AU PERSONNAGE ====================

-- Rend transparent les accessoires et MeshPart du personnage
local function setPlayerTransparency(character, transparency)
	if not character then return end

	for _, child in ipairs(character:GetChildren()) do
		if child:IsA("Accessory") then
			-- Rend transparent les BasePart/Decal de l'accessoire
			for _, descendant in ipairs(child:GetDescendants()) do
				if descendant:IsA("BasePart") or descendant:IsA("Decal") then
					descendant.Transparency = transparency
				end
			end
		elseif child:IsA("MeshPart") then
			-- Le MeshPart lui-même est la part à rendre transparente
			child.Transparency = transparency
		end
	end
end

-- Modifie la taille (échelle) du personnage
local function setPlayerScale(character, scale)
	if not character then return end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then return end
	print("scale: ", scale)
	humanoid.BodyHeightScale.Value = scale
	humanoid.BodyWidthScale.Value = scale
	humanoid.BodyDepthScale.Value = scale
	humanoid.HeadScale.Value = scale
end

-- Modifie la vitesse de marche du personnage
local function setPlayerSpeed(character, speed)
	if not character then return end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then return end

	humanoid.WalkSpeed = speed
end

-- Modifie la hauteur de saut du personnage
local function setPlayerJump(character, jumpHeight)
	if not character then return end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then return end

	humanoid.JumpHeight = jumpHeight
end

-- ==================== VALEURS PAR DÉFAUT (pour restaurer l'état d'origine) ====================

local function getDefaultTransparency(character)
	if not character then return nil end
	return 0
end

local function getDefaultScale(character)
	if not character then return nil end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then return nil end
	return humanoid.BodyHeightScale.Value
end

local function getDefaultSpeed(character)
	if not character then return nil end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then return nil end
	return humanoid.WalkSpeed
end

local function getDefaultJump(character)
	if not character then return nil end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then return nil end
	return humanoid.JumpHeight
end

-- ==================== CONFIGURATION DES BOOSTS ====================
-- Chaque boost définit : sa valeur max, comment récupérer la valeur par défaut,
-- le nom de la valeur stockée sur le personnage, et l'action à appliquer
local BOOSTS = {
	MoreSpeed = {
		max = 50,
		default = getDefaultSpeed,
		valueName = "Speed",
		action = setPlayerSpeed,
	},
	MoreJump = {
		max = 80,
		default = getDefaultJump,
		valueName = "Jump",
		action = setPlayerJump,
	},
	LessScale = {
		max = 0.3,
		default = getDefaultScale,
		valueName = "Scale",
		action = setPlayerScale,
	},
	Invisibility = {
		max = 0.9,
		default = getDefaultTransparency,
		valueName = "Transparency",
		action = setPlayerTransparency,
	},
}

-- ==================== LOGIQUE DE ZONE ====================
-- Applique ou retire un boost selon l'état actuel du personnage (toggle)
local function handleBoostTouch(character, boost)
	local existingValue = character:FindFirstChild(boost.valueName)

	if existingValue then
		-- Le boost est déjà actif : on restaure la valeur d'origine et on nettoie
		boost.action(character, existingValue.Value)
		existingValue:Destroy()
	else
		-- Le boost n'est pas actif : on sauvegarde la valeur par défaut, puis on applique le boost max
		local defaultValue = boost.default(character)
		if not defaultValue then return end -- sécurité : impossible de sauvegarder, on annule

		local savedValue = Instance.new("IntValue")
		savedValue.Name = boost.valueName
		savedValue.Value = defaultValue
		savedValue.Parent = character

		boost.action(character, boost.max)
	end
end

for _, part in ipairs(ZONES_FOLDER:GetDescendants()) do
	if not part:IsA("BasePart") then continue end

	local boost = BOOSTS[part.Name]
	if not boost then continue end
	
	print(boost)

	part.Touched:Connect(function(hit)
		local character = hit.Parent
		if not character then return end

		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not humanoid then return end

		-- Vérifie que c'est bien un personnage joueur (pas un NPC ou une part aléatoire)
		local player = Players:GetPlayerFromCharacter(character)
		if not player then return end

		-- Vérifie le cooldown pour éviter le spam de déclenchement
		if activeCooldowns[character] then return end
		activeCooldowns[character] = true

		handleBoostTouch(character, boost)

		-- Réinitialise le cooldown après le délai
		task.delay(COOLDOWN_DURATION, function()
			activeCooldowns[character] = nil
		end)
	end)
end

-- ==================== NETTOYAGE ====================
Players.PlayerRemoving:Connect(function(player)
	-- Nettoyage complet pour éviter les fuites mémoire quand un joueur quitte le jeu
	local character = player.Character
	if not character then return end

	activeCooldowns[character] = nil
	
	-- Supprimer tous les IntValue liés aux boosts
	for _, boost in pairs(BOOSTS) do
		local value = character:FindFirstChild(boost.valueName)
		if value then
			value:Destroy()
		end
	end
end)

Ce script permet de créer 4 types de zones de boost dans un seul script :

  • MoreSpeed : Augmente la vitesse de marche (WalkSpeed).
  • MoreJump : Augmente la hauteur de saut (JumpHeight).
  • MoreScale : Réduit la taille du personnage (échelle).
  • Transparency : Rend le personnage transparent.

Chaque zone est une BasePart dans le dossier ZonesBoost. Quand un joueur touche une zone, le boost correspondant est activé ou désactivé (toggle). Un cooldown empêche le spam.

Structure de la table BOOSTS

La table BOOSTS est le cœur du script. Elle définit les propriétés et comportements de chaque boost sous forme de sous-tables.

Définition de BOOSTS

local BOOSTS = {
MoreSpeed = {
max = 50, -- Valeur maximale du boost (ex: WalkSpeed = 50)
default = getDefaultSpeed, -- Fonction pour récupérer la valeur par défaut
valueName = "Speed", -- Nom de la valeur stockée sur le personnage (ex: IntValue "Speed")
action = setPlayerSpeed, -- Fonction à appeler pour appliquer le boost
},
MoreJump = {
max = 80,
default = getDefaultJump,
valueName = "Jump",
action = setPlayerJump,
},
MoreScale = {
max = 1.5,
default = getDefaultScale,
valueName = "Scale",
action = setPlayerScale,
},
Transparency = {
max = 0.9,
default = getDefaultTransparency,
valueName = "Transparency",
action = setPlayerTransparency,
},
}

Explication des champs

ChampTypeRôleExemple pour MoreSpeed
maxnumberValeur maximale du boost (ex: WalkSpeed = 50).50
defaultfunctionFonction qui récupère la valeur par défaut du personnage (ex: WalkSpeed initiale).getDefaultSpeed (retourne humanoid.WalkSpeed)
valueNamestringNom de l’IntValue stocké sur le personnage pour sauvegarder la valeur d’origine."Speed"
actionfunctionFonction qui applique le boost (ex: modifie WalkSpeed).setPlayerSpeed(character, 50)

Pourquoi cette structure ?

  • Modularité : Chaque boost est indépendant et peut être modifié sans toucher aux autres.
  • Réutilisabilité : Les fonctions (default, action) sont partagées entre tous les boosts du même type.
  • Extensibilité : Pour ajouter un nouveau boost, il suffit d’ajouter une entrée dans BOOSTS.

3. Fonctionnement des boosts (Toggle)

Le script utilise un mécanisme de toggle :

  • 1ère collision : Active le boost (ex: WalkSpeed = 50).
  • 2ème collision : Désactive le boost et restaure la valeur d’origine.

Fonction handleBoostTouch

local function handleBoostTouch(character, boost)
local existingValue = character:FindFirstChild(boost.valueName)

if existingValue then
-- Boost déjà actif : on restaure la valeur d'origine
boost.action(character, existingValue.Value)
existingValue:Destroy()
else
-- Boost inactif : on sauvegarde la valeur par défaut, puis on applique le boost
local defaultValue = boost.default(character)
if not defaultValue then return end

local savedValue = Instance.new("IntValue")
savedValue.Name = boost.valueName
savedValue.Value = defaultValue
savedValue.Parent = character

boost.action(character, boost.max)
end
end

Explication du toggle

  1. Vérification de existingValue :
    • Le script cherche un IntValue dans le character avec le nom boost.valueName (ex: "Speed").
    • Si existingValue existe → Le boost est déjà actif :
      • On restaure la valeur d’origine (existingValue.Value) en appelant boost.action.
      • On supprime l’IntValue pour indiquer que le boost est désactivé.
    • Si existingValue n’existe pas → Le boost est inactif :
      • On récupère la valeur par défaut avec boost.default(character) (ex: getDefaultSpeed).
      • On crée un IntValue pour stocker cette valeur dans le character.
      • On applique le boost avec boost.action(character, boost.max).

Exemple concret avec MoreSpeed

  1. 1ère collision:
    • existingValue = nil → Boost inactif.
    • defaultValue = getDefaultSpeed(character) → Récupère WalkSpeed initiale (ex: 16).
    • Crée un IntValue nommé "Speed" avec Value = 16.
    • Applique setPlayerSpeed(character, 50)WalkSpeed = 50.
  2. 2ème collision:
    • existingValue = IntValue "Speed" (Value = 16) → Boost actif.
    • Applique setPlayerSpeed(character, 16) → Restaure WalkSpeed = 16.
    • Supprime l’IntValue "Speed".

Nettoyage mémoire (Éviter les fuites)

Pourquoi nettoyer ?

  • Fuites mémoire : Si un joueur quitte le jeu, ses IntValue (ex: "Speed", "Jump") restent dans le character.
  • Cooldowns actifs : La table activeCooldowns conserve des références aux character qui n’existent plus.
  • Performances : Accumuler des objets inutiles ralentit le jeu.

Nettoyage dans PlayerRemoving

Players.PlayerRemoving:Connect(function(player)
local character = player.Character
if not character then return end

activeCooldowns[character] = nil -- Supprime le cooldown du joueur
end)

Explications

  • PlayerRemoving : Événement déclenché quand un joueur quitte le jeu.
  • activeCooldowns[character] = nil :
    • Supprime l’entrée du character dans activeCooldowns pour éviter de garder des références inutiles.

5. Fonctions de boost et valeurs par défaut

Fonctions d’action (setPlayer...)

Ces fonctions appliquent un effet au personnage :

  • setPlayerSpeed(character, speed) : Modifie humanoid.WalkSpeed.
  • setPlayerJump(character, jumpHeight) : Modifie humanoid.JumpHeight.
  • setPlayerScale(character, scale) : Modifie l’échelle du personnage (BodyHeightScale, etc.).
  • setPlayerTransparency(character, transparency) : Rend les accessoires et MeshPart transparents.

Fonctions de valeur par défaut (getDefault...)

Ces fonctions récupèrent la valeur d’origine du personnage :

  • getDefaultSpeed(character) : Retourne humanoid.WalkSpeed.
  • getDefaultJump(character) : Retourne humanoid.JumpHeight.
  • getDefaultScale(character) : Retourne humanoid.BodyHeightScale.Value.
  • getDefaultTransparency(character) : Retourne 0 (par défaut, les objets ne sont pas transparents).

6. Logique de détection des zones

Boucle sur les zones

for _, part in ipairs(ZONES_FOLDER:GetDescendants()) do
if not part:IsA("BasePart") then continue end

local boost = BOOSTS[part.Name] -- Récupère la configuration du boost
if not boost then continue end -- Ignore si la part n'est pas une zone de boost

part.Touched:Connect(function(hit)
-- Vérifications (character, humanoid, player, cooldown)
-- ...
handleBoostTouch(character, boost)
end)
end

Explications

  1. Parcours des BasePart dans ZonesBoost :
    • Seules les BasePart avec un nom correspondant à une clé de BOOSTS (ex: "MoreSpeed") sont prises en compte.
  2. Événement Touched :
    • Quand un joueur touche une zone, handleBoostTouch est appelé avec le character et le boost correspondant.
  3. Vérifications :
    • hit.Parent doit être un character valide.
    • Le character doit avoir un Humanoid.
    • Le character doit appartenir à un Player (pas un NPC).
    • Le character ne doit pas être en cooldown (activeCooldowns).

7. Gestion du cooldown

Mécanisme

if activeCooldowns[character] then return end
activeCooldowns[character] = true

-- Après application du boost :
task.delay(COOLDOWN_DURATION, function()
activeCooldowns[character] = nil
end)

Explications

  • activeCooldowns : Table qui stocke les character en cooldown ([character] = true).
  • task.delay :
    • Planifie la réinitialisation du cooldown après COOLDOWN_DURATION secondes.
    • Évite de bloquer le thread principal (contrairement à task.wait).

Résumé des points clés

ÉlémentsRôle
BOOSTSTable qui définit les 4 boosts (vitesse, saut, taille, transparence).
valueNameNom de l’IntValue stocké dans le character pour sauvegarder la valeur d’origine.
defaultFonction qui récupère la valeur d’origine (ex: WalkSpeed initiale).
actionFonction qui applique le boost (ex: setPlayerSpeed).
handleBoostTouchGère le toggle (activation/désactivation) du boost.
activeCooldownsTable qui empêche le spam en bloquant les déclenchements pendant COOLDOWN_DURATION.
PlayerRemovingNettoie les cooldowns quand un joueur quitte le jeu.
IntValueStocke la valeur d’origine du boost dans le character pour la restaurer plus tard.

Améliorations possibles

  1. Gestion des erreurs :
    • Ajouter des warn pour déboguer (ex: si defaultValue est nil).
  2. Effets visuels/sonores :
    • Ajouter des particules ou des sons quand un boost est activé/désactivé.
  3. Cooldown par boost :
    • Actuellement, le cooldown est global (un seul boost à la fois).
    • Pour permettre plusieurs boosts simultanés, utiliser une table de cooldowns par type de boost :
    • local cooldowns = {} -- [character] = { MoreSpeed = true, MoreJump = false, ... } -- Dans handleBoostTouch : if cooldowns[character] and cooldowns[character][boostName] then return end cooldowns[character][boostName] = true task.delay(COOLDOWN_DURATION, function() cooldowns[character][boostName] = nil end)

Compréhension du script des boosts

Consignes : Choisis une seule réponse par question.

Question 1 : À quoi sert la table BOOSTS dans le script ?

  • A. À stocker les joueurs qui ont activé un boost.
  • B. À définir les propriétés (valeur maximale, action, etc.) pour chaque type de boost (vitesse, saut, taille, transparence).
  • C. À enregistrer les positions des zones de boost dans le jeu.
  • D. À gérer les cooldowns des joueurs.

Question 2 : Que fait la fonction handleBoostTouch quand un joueur touche une zone de boost pour la première fois ?

  • A. Elle supprime le boost et restaure la valeur par défaut.
  • B. Elle vérifie si le joueur a déjà utilisé un boost.
  • C. Elle applique le boost, sauvegarde la valeur d’origine dans un IntValue, et active le cooldown.
  • D. Elle change la couleur de la zone de boost.

Question 3 : Pourquoi utilise-t-on activeCooldowns dans le script ?

  • A. Pour stocker les valeurs maximales des boosts.
  • B. Pour compter le nombre de joueurs ayant utilisé un boost.
  • C. Pour désactiver définitivement un boost.
  • D. Pour éviter qu’un joueur ne déclenche plusieurs fois le même boost trop rapidement.

Question 4 : Que se passe-t-il si un joueur touche une zone de boost alors qu’il a déjà activé ce boost ?

  • A. Le boost est désactivé, et la valeur d’origine est restaurée.
  • B. Rien, le boost reste actif indéfiniment.
  • C. Le boost est réappliqué avec une valeur plus forte.
  • D. Le joueur est téléporté à un autre endroit.

Question 5 : Pourquoi faut-il nettoyer les IntValue et activeCooldowns quand un joueur quitte le jeu ?

  • A. Pour accélérer le jeu.
  • B. Pour éviter les fuites mémoire et les références à des objets qui n’existent plus.
  • C. Pour réinitialiser les boosts pour tous les joueurs.
  • D. Pour changer l’apparence des zones de boost.

Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

Comment pousser un bloc

Pousser un bloc sans code complexe

Ce script rend un bloc poussable par le joueur en utilisant directement le moteur physique de Roblox, sans avoir besoin de code complexe pour détecter les contacts. part.Anchored = false est la ligne essentielle : elle « détache » la Part du monde et lui permet de bouger sous l’effet de forces physiques (comme la poussée du joueur). part.CanCollide = true garantit que le joueur ne traverse pas le bloc mais rentre réellement dedans, ce qui déclenche la poussée physique naturelle.

PhysicalProperties.new(...) personnalise le comportement physique du bloc : ici, une densité basse (0.2) rend l’objet léger et facile à pousser, une friction basse (0.2) le fait glisser facilement, et une élasticité (0.5) lui donne un léger effet de rebond.

part.CustomPhysicalProperties = physicalProperties applique ces réglages personnalisés à la Part, plutôt que d’utiliser les valeurs par défaut de Roblox (qui donneraient un objet plus lourd et moins glissant).

local part = script.Parent

local physicalProperties = PhysicalProperties.new(
	0.2,  -- Density (densité, plus c'est bas plus c'est léger à pousser)
	0.2,  -- Friction
	0.5,  -- Elasticity
	1,    -- FrictionWeight
	1     -- ElasticityWeight
)

part.Anchored = false
part.CanCollide = true
part.CustomPhysicalProperties = physicalProperties

Pousser un bloc avec une impulsion

Ce script combine deux mécanismes pour rendre un bloc poussable :

  1. Configuration physique de base : le bloc devient mobile (Anchored = false) et reçoit des propriétés physiques personnalisées (densité, friction, élasticité) qui définissent son comportement naturel (léger/lourd, glissant/collant, rebondissant ou non).
  2. Poussée scriptée additionnelle : en plus de la physique naturelle, le script détecte quand un joueur touche le bloc et lui applique une impulsion (un « coup de pousse ») dans la direction où le joueur regarde/avance, grâce à ApplyImpulse.

Détail du fonctionnement

  • humanoidRootPart.CFrame.LookVector récupère un vecteur représentant la direction vers laquelle le joueur est orienté — c’est cette direction qui détermine le bloc va être poussé.
  • part:ApplyImpulse(direction * PUSH_FORCE * part:GetMass()) calcule la force de poussée en tenant compte de la masse du bloc (GetMass()) : plus le bloc est lourd, plus il faut une impulsion importante pour le déplacer de la même façon (comme dans la vraie vie).
  • part.Touched:Connect(onTouched) signifie que cette poussée se déclenche à chaque fois que quelque chose touche le bloc — donc potentiellement plusieurs fois par seconde si le joueur reste collé dessus.

Pourquoi combiner les deux mécanismes ?

La physique seule (Anchored = false + CanCollide = true) suffit déjà à rendre le bloc poussable naturellement. Mais ajouter une impulsion scriptée permet de renforcer ou contrôler cet effet — par exemple pour que la poussée soit plus franche et immédiate, même si le joueur touche le bloc à faible vitesse.

QCM pour mieux comprendre

1. Que se passe-t-il si on met part.Anchored = true dans ce script ?
A. Le bloc devient plus facile à pousser
B. Le bloc ne pourra plus bouger du tout, malgré l’impulsion appliquée
C. Le bloc disparaît
D. Rien ne change

2. Que représente humanoidRootPart.CFrame.LookVector ?
A. La vitesse du joueur
B. La direction vers laquelle le joueur regarde/avance
C. La position exacte du joueur
D. Le nom du joueur

3. Pourquoi multiplie-t-on la force par part:GetMass() ?
A. Pour que la poussée soit toujours la même, peu importe le poids du bloc
B. Pour adapter la force de poussée au poids réel du bloc (plus lourd = plus de force nécessaire)
C. Pour calculer la vitesse du joueur
D. Pour rendre le bloc invisible

4. Que fait part:ApplyImpulse(...) ?
A. Il déplace instantanément le bloc à une position précise
B. Il applique une force ponctuelle qui pousse le bloc dans une direction donnée
C. Il détruit le bloc
D. Il change la couleur du bloc

5. Quand la fonction onTouched se déclenche-t-elle ?
A. Une seule fois au démarrage du jeu
B. À chaque fois qu’un objet (joueur ou autre) touche le bloc
C. Uniquement quand le joueur saute sur le bloc
D. Toutes les 5 secondes automatiquement

6. Si on augmente la valeur de PUSH_FORCE, que se passe-t-il ?
A. Le bloc devient plus lourd visuellement
B. Le bloc sera poussé plus fort/plus loin à chaque contact
C. Le joueur devient plus rapide
D. Rien, cette variable n’est pas utilisée dans le script

7. Pourquoi le script vérifie-t-il if not humanoid or not humanoidRootPart then return end ?
A. Pour vérifier que c’est bien un joueur (ou personnage) qui touche le bloc, et pas un autre objet
B. Pour supprimer le joueur s’il n’a pas de vie
C. Pour ralentir le jeu volontairement
D. Ce n’est pas nécessaire, cette ligne ne sert à rien

local part = script.Parent

local physicalProperties = PhysicalProperties.new(
	0.5,  -- Density (densité, plus c'est bas plus c'est léger à pousser)
	0.5,  -- Friction
	0.5,  -- Elasticity
	1,    -- FrictionWeight
	1     -- ElasticityWeight
)

part.Anchored = false
part.CanCollide = true
part.CustomPhysicalProperties = physicalProperties

local PUSH_FORCE = 2 -- Intensité de la poussée

local function onTouched(hit)
	local character = hit.Parent
	local humanoid = character and character:FindFirstChild("Humanoid")
	local humanoidRootPart = character and character:FindFirstChild("HumanoidRootPart")
	if not humanoid or not humanoidRootPart then return end

	-- Calcule la direction dans laquelle le joueur se déplace
	local direction = humanoidRootPart.CFrame.LookVector

	-- Applique une impulsion dans cette direction
	part:ApplyImpulse(direction * PUSH_FORCE * part:GetMass())
end

part.Touched:Connect(onTouched)

Pousser plusieurs BLOCs

local partFolder = script.Parent

local physicalProperties = PhysicalProperties.new(
	0.5,  -- Density (densité, plus c'est bas plus c'est léger à pousser)
	0.5,  -- Friction
	0.5,  -- Elasticity
	1,    -- FrictionWeight
	1     -- ElasticityWeight
)


local PUSH_FORCE = 20 -- Intensité de la poussée

local function onTouched(hit, part)
	local character = hit.Parent
	local humanoid = character and character:FindFirstChild("Humanoid")
	local humanoidRootPart = character and character:FindFirstChild("HumanoidRootPart")
	if not humanoid or not humanoidRootPart then return end

	-- Calcule la direction dans laquelle le joueur se déplace
	local direction = humanoidRootPart.CFrame.LookVector

	-- Applique une impulsion dans cette direction
	part:ApplyImpulse(direction * PUSH_FORCE * part:GetMass())
end

for _, part in partFolder:GetChildren() do
	if part:IsA("BasePart") then
		
		part.Anchored = false
		part.CanCollide = true
		part.CustomPhysicalProperties = physicalProperties		
		part.Touched:Connect(onTouched, part)
	end
end

Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

Points de respawns, comptage des tours, meilleur temps

À quoi sert ce script ?

Ce script permet de créer un parcours de course :

  • Des checkpoints invisibles qui font respawn le joueur au bon endroit s’il 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

Comment l’utiliser dans votre jeu

Étape 1 : Créer les parts de checkpoint

  1. Créez un dossier (Folder) nommé PartSpawnNiv dans le Workspace.
  2. Créez un dossier GAME dans le Workspace qui contiendra ce dossier PartSpawnNiv.
  3. Dans PartSpawnNiv, créez une Part pour chaque checkpoint de votre parcours (une au départ, une à chaque étape importante, une à l’arrivée).
  4. Nommez-les avec des numéros dans l’ordre : "1", "2", "3", etc. ; c’est très important, le script trie les checkpoints selon ces numéros !
Workspace
 └── GAME
      └── PartSpawnNiv
           ├── 1  (départ)
           ├── 2
           ├── 3
           └── 4  (arrivée)

Le script rend ces parts automatiquement invisibles et traversables : pas besoin de le faire vous-même !

Étape 2 : Créer l’interface (GUI)

Dans StarterGui, créez un ScreenGui contenant :

  • Un Frame nommé Counter avec un TextLabel nommé CounterLabel (nombre de tours)
  • Un Frame nommé Best avec un TextLabel nommé BestLabel (meilleur temps)

Étape 3 : Placer le script

Placez ce script en tant que Script (serveur, pas LocalScript) directement dans ServerScriptService.

Comment fonctionne le script (en 6 points)

  1. Au démarrage, le script range tous les checkpoints du dossier PartSpawnNiv dans l’ordre de leurs numéros, puis les rend invisibles et traversables.
  2. Quand un joueur touche un checkpoint, le script vérifie qui il est, puis retient dans un tableau playersProgression : la part actuelle, le nombre de tours, l’heure de départ, et le meilleur temps.
  3. Si le joueur touche le checkpoint n°1 juste après avoir touché le DERNIER checkpoint, le script comprend qu’il a terminé un tour complet : il incrémente le compteur et compare le temps réalisé au record.
  4. Si le joueur meurt, l’événement CharacterAdded se déclenche : le script téléporte automatiquement le joueur au-dessus du dernier checkpoint touché (et pas au tout début du parcours !).
  5. Le tableau playersProgression retient les informations de chaque joueur séparément, grâce à son UserId (un peu comme une fiche personnelle par joueur).
  6. Quand un joueur quitte le jeu, ses informations sont automatiquement supprimées du tableau pour ne pas garder des données inutiles en mémoire.

Pourquoi utiliser un tableau, et que contient playersProgression ?

Pourquoi a-t-on besoin d’un tableau ici ?

Imagine que plusieurs joueurs jouent en même temps sur ton parcours. Le script doit se souvenir, pour chaque joueur individuellement :

  • à quel checkpoint il en est
  • depuis quand il a commencé son tour actuel
  • combien de tours il a déjà faits
  • son meilleur temps

Si le script utilisait une seule variable simple (par exemple local spawnActuel = ...), cette variable serait partagée par tous les joueurs — dès qu’un 2ème joueur touche un checkpoint, ça écraserait la progression du 1er joueur ! Ce serait comme si tout le monde partageait le même carnet de notes : la dernière personne qui écrit efface ce que l’autre avait noté.

Un tableau permet de créer une « fiche » séparée pour chaque joueur, un peu comme un casier avec un tiroir par élève dans une salle de classe.

Qu’est-ce qu’un tableau d’informations (une table Lua) ?

En Lua, une table peut fonctionner comme un dictionnaire : au lieu d’accéder à une information par un numéro de position (comme dans une liste), on y accède par une clé (un identifiant unique), et chaque clé pointe vers une valeur.

playersProgression = {
	[12345] = { ... },  -- clé = UserId du joueur 1
	[67890] = { ... },  -- clé = UserId du joueur 2
}

C’est comme un répertoire téléphonique : la clé, c’est le nom de la personne ; la valeur, c’est son numéro. Ici, la clé est le UserId (identifiant unique de chaque joueur sur Roblox), et la valeur est une autre table qui contient toutes les infos de progression de ce joueur précis.

Pourquoi utiliser le UserId comme clé ?

Parce que chaque joueur a un UserId unique et permanent sur Roblox — contrairement à son pseudo qui pourrait théoriquement changer, ou à sa position dans une liste qui peut varier si un joueur quitte. Utiliser le UserId garantit qu’on retrouve toujours la bonne fiche pour le bon joueur, même avec plusieurs joueurs connectés simultanément.

Le contenu détaillé de playersProgression[UserId]

Pour un joueur donné, la table stockée ressemble à ceci :

playersProgression[12345] = {
	spawn = <référence à la Part checkpoint>,
	course = 2,            -- nombre de tours réalisés
	start = 1735689042.5,  -- temps de démarrage du tour
	best = 45.32,          -- temps du meilleur parcours
}
CléSignification
spawnLe dernier checkpoint touché par ce joueur — utilisé pour savoir où faire respawn s’il meurt
courseLe nombre de tours complets déjà réalisés par ce joueur
startL’heure exacte (tick()) à laquelle le joueur a commencé son tour actuel — sert à calculer son temps une fois arrivé
bestLe meilleur temps (le record personnel) réalisé par ce joueur sur un tour complet

QCM pour vérifier la compréhension

1. Pourquoi faut-il nommer les checkpoints « 1 », « 2 », « 3 »… et pas « Depart », « Milieu », « Fin » ?
A. Pour que ce soit plus joli dans l’Explorer
B. Parce que le script trie les checkpoints selon ces numéros pour connaître leur ordre
C. Ça n’a aucune importance, on peut les nommer comme on veut
D. Parce que Roblox l’exige pour toutes les Parts

2. Que se passe-t-il quand un joueur meurt en plein milieu du parcours ?
A. Il recommence tout le parcours depuis le début
B. Il respawn au dernier checkpoint qu’il a touché
C. Le jeu se ferme
D. Son compteur de tours est remis à zéro

3. Comment le script sait-il qu’un joueur a terminé un tour complet ?
A. Quand il touche n’importe quel checkpoint
B. Quand il touche le checkpoint n°1 juste après avoir touché le tout dernier checkpoint
C. Quand il appuie sur une touche spéciale
D. Automatiquement après 60 secondes

4. Pourquoi les checkpoints sont-ils rendus invisibles et traversables (CanCollide = false) ?
A. Pour que le joueur ne les voie pas et ne soit pas bloqué en les traversant
B. Pour que le jeu soit plus rapide
C. Pour économiser de la mémoire
D. Ce n’est pas obligatoire, c’est juste un choix esthétique

5. À quoi sert le UserId du joueur dans le tableau playersProgression ?
A. À afficher le nom du joueur à l’écran
B. À retenir séparément la progression de CHAQUE joueur individuellement
C. À bannir les joueurs trichent
D. À compter le nombre total de joueurs connectés

6. Que se passe-t-il si deux checkpoints ont accidentellement le même numéro (ex: deux parts nommées « 3 ») ?
A. Rien, le script gère ça automatiquement
B. Le parcours pourrait ne pas fonctionner correctement, car l’ordre ne serait plus fiable
C. Le jeu affiche une erreur et s’arrête
D. Roblox choisit au hasard laquelle utiliser

7. Pourquoi utilise-t-on un Script (serveur) et pas un LocalScript pour ce système ?
A. Parce que le compteur de tours et le meilleur temps doivent être valables pour tout le monde, gérés par un seul endroit fiable (le serveur)
B. Parce que les LocalScripts ne fonctionnent pas avec les Parts
C. Ça n’a pas d’importance, les deux marcheraient pareil
D. Parce que c’est plus rapide à écrire

-- ═══════════════════════════════════════
-- SERVICES ET RÉFÉRENCES
-- ═══════════════════════════════════════
local Players = game:GetService("Players")
local Game = workspace.GAME

local SpawnFolder = Game:WaitForChild("PartSpawnNiv", true)

local baseplate = workspace:FindFirstChild("Baseplate")
if baseplate then
	baseplate:Destroy()
end

-- Tableau des joueurs en cours de partie avec l'étape mémorisée
local playersProgression = {}

-- Tableau de toutes les étapes du jeu, triées par nom pour garantir l'ordre
local spawnsList = SpawnFolder:GetChildren()
table.sort(spawnsList, function(a, b)
	return tonumber(a.Name) < tonumber(b.Name)
end)
local lastSpawnIndex = #spawnsList

local function formatTime(t)
	local minutes = math.floor(t / 60)
	local seconds = math.floor(t % 60)
	local centiemes = math.floor((t * 100) % 100)
	return string.format("%02d:%02d.%02d", minutes, seconds, centiemes)
end

-- ═══════════════════════════════════════
-- RESPAWN AU DERNIER CHECKPOINT
-- ═══════════════════════════════════════
local function respawnAuCheckpoint(player)
	local progression = playersProgression[player.UserId]
	if not progression or not progression.spawn then return end

	local character = player.Character
	if not character then return end

	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then return end

	local spawn = progression.spawn
	local targetPosition = spawn.Position + Vector3.new(0, (spawn.Size.Y / 2) + 2, 0)
	humanoidRootPart.CFrame = CFrame.new(targetPosition)
end

-- ═══════════════════════════════════════
-- GESTION DU CHARGEMENT DES JOUEURS
-- ═══════════════════════════════════════
local function initPlayer(player)
	player.CharacterAdded:Connect(function(character)
		character:WaitForChild("HumanoidRootPart")
		respawnAuCheckpoint(player)
	end)
end

Players.PlayerAdded:Connect(initPlayer)
Players.PlayerRemoving:Connect(function(player)
	playersProgression[player.UserId] = nil
end)

-- ═══════════════════════════════════════
-- CHARGEMENT DES ÉTAPES ET DÉTECTION DES CHECKPOINTS
-- ═══════════════════════════════════════
for index, spawn in ipairs(spawnsList) do
	if spawn:IsA("BasePart") then
		spawn.Transparency = 1
		spawn.CanCollide = false
		spawn.Anchored = true

		spawn.Touched:Connect(function(hit)
			local player = Players:GetPlayerFromCharacter(hit.Parent)
			if not player then return end

			local progression = playersProgression[player.UserId]

			-- Ignore si le joueur est déjà sur ce checkpoint
			if progression and progression.spawn == spawn then return end

			if not progression then
				playersProgression[player.UserId] = {
					spawn = spawn,
					course = 0,
					start = tick(),
					best = 0,
					counterLabel = player.PlayerGui.ScreenGui.Counter.CounterLabel,
					bestLabel = player.PlayerGui.ScreenGui.Best.BestLabel,
				}
				return
			end

			-- Tour complet détecté : dernier checkpoint -> premier checkpoint
			if index == 1 and progression.spawn == spawnsList[lastSpawnIndex] then
				progression.course += 1
				progression.counterLabel.Text = string.format("%02d", progression.course)

				local finishTime = tick() - progression.start
				if progression.best == 0 or finishTime < progression.best then
					progression.best = finishTime
				end
				progression.bestLabel.Text = formatTime(progression.best)
			end

			progression.spawn = spawn
			progression.start = tick()
		end)
	end
end
Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

Boost temporaire

À quoi sert ce script ?

Ce script permet au joueur d’appuyer sur une touche (F) pour obtenir un boost temporaire de vitesse et de saut pendant quelques secondes, avec une énergie limitée qui se réduit à chaque utilisation, affichée sous forme de barre.

Pourquoi ce script doit être un LocalScript et pas un script serveur

1. Détection des touches du clavier

UserInputService.InputBegan (qui détecte l’appui sur F) ne fonctionne que côté client. Le serveur ne « voit » pas directement quelle touche un joueur appuie sur son clavier — seul l’ordinateur du joueur (le client) peut détecter ça. Si ce script était sur le serveur, la détection de la touche ne fonctionnerait tout simplement pas.

2. Réactivité et fluidité

Un LocalScript s’exécute directement sur l’ordinateur du joueur, sans attendre d’aller-retour réseau avec le serveur. Le chrono et le boost réagissent donc instantanément, sans latence perceptible.

3. Affichage de l’interface (GUI)

Modifier un TextLabel ou la taille d’une barre (energy.Size) dans la PlayerGui doit se faire depuis un LocalScript : c’est l’interface personnelle de ce joueur, elle ne concerne que son écran à lui.

⚠️ Attention cependant : comme ce script est entièrement côté client, un joueur malveillant pourrait potentiellement le modifier pour tricher (boost infini, énergie illimitée…). Dans un vrai jeu, il faudrait que le serveur vérifie et valide réellement les changements de vitesse/saut, plutôt que de faire une confiance totale au client. Ce script convient pour l’affichage et le confort, mais une version « anti-triche » demanderait une communication avec un script serveur.

Pourquoi utiliser des CONSTANTES

EN MAJUSCULES (TIMELAPS, SPEEDMAX, JUMPMAX…)

  1. Convention de lisibilité : en programmation, écrire un nom de variable entièrement en majuscules est une convention largement utilisée pour signaler « ceci est une constante de configuration, une valeur qui ne doit jamais changer pendant l’exécution du script ». Ça permet, en un coup d’œil, de distinguer les réglages (en haut du script) des variables qui évoluent pendant le jeu (energyLevel, startime…).
  2. Facilité de modification : toutes les valeurs importantes sont regroupées au même endroit, en haut du script. Si tu veux changer la durée du boost ou la touche utilisée, tu modifies une seule ligne, sans devoir chercher dans tout le code où cette valeur est utilisée.
  3. Évite les « nombres magiques » : sans constante, on verrait des 50, 70, 6 disséminés dans le code sans savoir à quoi ils correspondent. Avec SPEEDMAX = 50, le nom explique immédiatement le rôle du nombre.

Pourquoi RunService.Heartbeat plutôt qu’une boucle while ... do wait() end

Le problème d’une boucle while avec wait()

-- ❌ Mauvaise pratique
while true do
	wait()
	-- code du chrono
end
  1. Bloque le thread : une boucle infinie s’exécute en continu et occupe le script en permanence, même quand il n’y a rien à faire.
  2. Timing imprécis : wait() ne garantit pas un délai exact — il peut varier légèrement selon la charge du jeu, ce qui rend le chrono moins précis.
  3. Difficile à arrêter proprement : il faut gérer soi-même une condition de sortie, et un oubli peut bloquer le script indéfiniment.

Pourquoi Heartbeat est meilleur

  1. Synchronisé avec le moteur du jeu : RunService.Heartbeat se déclenche automatiquement à chaque frame, juste après les calculs de physique — c’est le rythme naturel du jeu (environ 60 fois par seconde), donc le chrono reste fluide et précis.
  2. Pas de blocage : contrairement à une boucle while, Heartbeat:Connect(...) ne bloque jamais le reste du script — le code continue de s’exécuter normalement en parallèle.
  3. Gestion automatique : pas besoin de gérer soi-même l’arrêt de la boucle ; la fonction ne fait simplement rien (return immédiat) tant que startime est nil, sans gaspiller de ressources inutiles.
  4. Standard de l’industrie : c’est la méthode recommandée par Roblox pour tout ce qui doit se mettre à jour en continu (chronos, animations personnalisées, barres de vie…).

QCM pour vérifier la compréhension

1. Pourquoi ce script doit-il être un LocalScript et non un script serveur ?
A. Parce que les LocalScripts sont plus rapides à écrire
B. Parce que la détection des touches du clavier (InputBegan) ne fonctionne que côté client
C. Parce que Roblox interdit les scripts serveur sur les touches
D. Ça n’a aucune importance, les deux fonctionneraient pareil

2. Que signifie écrire une variable EN MAJUSCULES comme SPEEDMAX ?
A. Que la variable est plus rapide à lire par l’ordinateur
B. Que c’est une convention indiquant qu’il s’agit d’une constante de configuration
C. Que la variable est obligatoirement un nombre
D. Que la variable est visible par tous les scripts du jeu

3. Quel est le principal problème d’une boucle while true do wait() end pour gérer un chrono ?
A. Elle ne fonctionne pas du tout sur Roblox
B. Elle est difficile à écrire
C. Son timing est moins précis et elle bloque le thread en continu
D. Elle ne peut pas afficher de texte

4. Que fait RunService.Heartbeat ?
A. Il vérifie le rythme cardiaque du joueur
B. Il exécute une fonction automatiquement à chaque frame du jeu
C. Il redémarre le script à chaque respawn
D. Il détecte les touches du clavier

5. Pourquoi regrouper tous les réglages (TIMELAPS, SPEEDMAX, JUMPMAX…) en haut du script ?
A. Pour que le script soit plus court
B. Pour faciliter la modification des paramètres à un seul endroit, sans chercher dans tout le code
C. Parce que Roblox l’exige
D. Pour que le jeu se charge plus vite

6. Quel est le risque de sécurité mentionné concernant ce LocalScript ?
A. Il pourrait faire planter le jeu
B. Un joueur malveillant pourrait le modifier pour tricher (énergie infinie, boost permanent)
C. Il consomme trop de mémoire
D. Il ne fonctionne que sur mobile

7. Que se passe-t-il concrètement si on remplace Heartbeat par une boucle while wait() do dans ce script ?
A. Rien ne change, c’est strictement identique
B. Le chrono pourrait être légèrement moins précis et le code moins optimisé, bien que fonctionnellement proche
C. Le boost ne fonctionnerait plus du tout
D. Le jeu planterait immédiatement

Crée cette structure d’UI pour la barre d’énergie et le compteur du boost :

Le ScreenGui possède une propriété ResetOnSpawn, qui vaut true par défaut. Quand elle est activée :

  • À chaque respawn, Roblox détruit le ScreenGui actuel dans la PlayerGui et le recrée à neuf depuis sa version originale dans StarterGui.
  • Toutes les modifications faites par script sont donc perdues, et la barre d’énergie revient à sa taille définie dans les Properties de Studio.

Solution

Dans l’Explorer, sélectionne ton ScreenGui et décoche/mets à false la propriété ResetOnSpawn :

Crée un LocalScript sous StarterPlayerScripts

Sous StarterPlayerScripts

Le script s’exécute dès la connexion du joueur, souvent avant même que le personnage n’existe dans le jeu (player.Character vaut alors nil, car le perso n’a pas encore spawn).

Sous StarterCharacterScripts

Le script est recréé et réexécuté à chaque respawn du personnage.

Dans notre cas, nous avons besoin de garder les informations sur le joueur après un respawn, crée donc un LocalScript sous StarterPlayerScripts :

-- Récupération des services
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

-- Paramètrage du service
local TIMELAPS = 6
local SPEEDMAX = 50
local JUMPMAX = 70
local TOUCHBOOST = Enum.KeyCode.F
local ENERGY_COST = 0.1

-- Récupération du player et des écrans
local player = Players.LocalPlayer

-- La PlayerGui et son contenu ne sont PAS détruits au respawn : on les récupère une seule fois
local playerGui = player:WaitForChild("PlayerGui")
local screenGui = playerGui:WaitForChild("ScreenGui")

-- Penser à modifier la propriété suivante dans ROBLOX STUDIO screenGui.ResetOnSpawn = false
local chrono = playerGui:WaitForChild("ScreenGui"):WaitForChild("Frame"):WaitForChild("ChronoBoost")
local energy = playerGui:WaitForChild("ScreenGui"):WaitForChild("Frame"):WaitForChild("Energy")
local info = energy:WaitForChild("Frame"):WaitForChild("InfoLabel")

-- Initialisation des variables au lancement du script
local humanoid, jumpHeight, walkSpeed
local energyLevel = 1
local startime = nil

-- Initialisation de l'affichage de la barre de puissance
info.Text = "Press " .. TOUCHBOOST.Name .. " to boost for 3 seconds (Energy " .. math.floor(ENERGY_COST * 100) .. "%)"
chrono.Visible = false

-- Formatage du temps restant en seconde et dixième de seconde
local function formatTime(t)
	local seconds = math.floor(t % 60)
	local tenths = math.floor((t * 10) % 10)
	return string.format("%02d.%d", seconds, tenths)
end

-- Chargement du player
local function onCharacterAdded(character)
	humanoid = character:WaitForChild("Humanoid")
	jumpHeight = humanoid.JumpHeight
	walkSpeed = humanoid.WalkSpeed
	startime = nil
end

player.CharacterAdded:Connect(onCharacterAdded)
if player.Character then
	onCharacterAdded(player.Character)
end

-- Récupération de la touche du clavier pour actionner le boost
local function onKeyPress(input, gameProcessed)
	if gameProcessed or startime or not humanoid then return end
	if input.KeyCode ~= TOUCHBOOST then return end
	if energyLevel < ENERGY_COST then return end

	humanoid.JumpHeight = JUMPMAX
	humanoid.WalkSpeed = SPEEDMAX
	--energyLevel = math.clamp(energyLevel - ENERGY_COST, 0, 1)
	startime = tick()
	--energy.Size = UDim2.new(energyLevel, 0,  energy.Size.Y.Scale, 0)
end

UserInputService.InputBegan:Connect(onKeyPress)
-- Affichage du temps restant du boost
RunService.Heartbeat:Connect(function()
	if not startime or not humanoid then return end

	local elapsed = TIMELAPS - (tick() - startime)
	if elapsed > 0 then
		chrono.Visible = true
		chrono.Text = formatTime(elapsed)
	else
		startime = nil
		humanoid.JumpHeight = jumpHeight
		humanoid.WalkSpeed = walkSpeed
		chrono.Visible = false
		energyLevel = math.clamp(energyLevel - ENERGY_COST, 0, 1)
		energy.Size = UDim2.new(energyLevel, 0,  energy.Size.Y.Scale, 0)
	end
end)
Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

Zone de boosts

Crée quatre parts avec un pouvoir pour chaque part :

  • devenir transparent
  • changer de taille
  • courir plus vite
  • sauter plus haut

Explication des 4 boosts

Invisibilité

Quand un joueur touche une des parts du dossier, le script vérifie s’il a déjà un dossier "Transparency" sur son Humanoid.
S’il ne l’a pas, il le crée et rend transparents tous les vêtements/accessoires et le corps du joueur (Transparency = 0.9).
S’il l’a déjà, le script le supprime et redonne au joueur son apparence normale (Transparency = 0).Un système de cooldown empêche de réactiver le pouvoir immédiatement après l’avoir utilisé.
C’est donc un interrupteur (toggle) : chaque contact avec la part active ou désactive l’invisibilité.

-- Script pour rendre invisible les joueurs qui touchent la part
local TRANSPARENCE_ACTIVE = 0.9
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

-- Boucle sur toutes les parts du folder des parts pour rendre invisible
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
	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)

Taille

  1. Quand le joueur touche la part, le script regarde si un dossier "Scale" existe déjà sur son Humanoid.
  2. S’il n’existe pas, il sauvegarde la taille actuelle du joueur, puis l’agrandit ou le rétrécit à SCALEMAX (0.3, donc joueur miniature).
  3. S’il existe déjà, le script redonne au joueur sa taille d’origine et supprime le dossier.
  4. Les 4 dimensions (hauteur, largeur, profondeur, tête) sont modifiées en même temps pour un effet cohérent.
  5. Comme pour l’invisibilité, c’est un toggle protégé par un cooldown.
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)

Vitesse

  1. Quand le joueur touche la part, le script vérifie si un dossier "Speed" existe sur son Humanoid.
  2. S’il n’existe pas, il sauvegarde la vitesse actuelle du joueur (WalkSpeed) et la remplace par SPEEDMAX (50, donc très rapide).
  3. S’il existe déjà, le script restaure la vitesse normale du joueur et supprime le dossier.
  4. Cela permet au joueur de courir beaucoup plus vite qu’en temps normal.
  5. Le cooldown évite d’activer/désactiver le pouvoir trop rapidement en boucle.
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)

Saut

  1. Quand le joueur touche la part, le script vérifie si un dossier "Jump" existe sur son Humanoid.
  2. S’il n’existe pas, il sauvegarde une valeur puis augmente sa hauteur de saut (JumpHeight) jusqu’à JUMPMAX (80, donc saut très haut).
  3. S’il existe déjà, le script restaure la hauteur de saut d’origine et supprime le dossier.
  4. Cela permet au joueur de sauter beaucoup plus haut que d’habitude.
  5. Le cooldown protège contre une réactivation trop rapide du pouvoir.
local part = script.Parent

local JUMPMAX = 80
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("Jump")
	
	if existingFolder then
		humanoid.JumpHeight = existingFolder.Value
		existingFolder:Destroy()
	else
		local folder = Instance.new("IntValue")
		folder.Name = "Jump"
		folder.Parent = humanoid
		folder.Value = humanoid.JumpHeight
		humanoid.JumpHeight = JUMPMAX
	end
	
	task.wait(COOLDOWN)
	cooldowns[character] = nil
	
end)

Point commun aux 4 scripts : ils utilisent tous le même mécanisme (dossier-mémoire + toggle + cooldown).

QCM pour mieux comprendre

1. Que se passe-t-il si un joueur touche deux fois la part « invisibilité » (avec le cooldown écoulé entre les deux) ?
A. Rien la deuxième fois
B. Il devient invisible puis redevient visible
C. Il meurt
D. Il devient invincible

2. À quoi sert le dossier créé (ex: "Speed", "Scale", "Jump") dans chaque script ?
A. À décorer le personnage
B. À mémoriser la valeur d’origine avant modification
C. À compter le nombre de joueurs
D. À afficher un message

3. Pourquoi y a-t-il un COOLDOWN dans chaque script ?
A. Pour ralentir le jeu
B. Pour empêcher de réactiver le pouvoir trop vite d’affilée
C. Pour supprimer le joueur
D. Pour changer la couleur de la part

4. Quelle propriété du Humanoid est modifiée par le pouvoir « saut » ?
A. WalkSpeed
B. Health
C. JumpHeight
D. Transparency

5. Que modifient ENSEMBLE BodyHeightScale, BodyWidthScale, BodyDepthScale et HeadScale ?
A. La vitesse du joueur
B. La taille du joueur
C. La transparence du joueur
D. La couleur du joueur

6. Pourquoi le pouvoir « invisibilité » doit-il aussi modifier les Accessory (accessoires) du joueur ?
A. Pour que le chapeau/les cheveux etc. deviennent transparents aussi, sinon on verrait encore une partie du joueur
B. Pour supprimer les accessoires
C. Pour donner des points au joueur
D. Pour changer la forme des accessoires

Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

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 ROBLOX-NIVEAU02

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 ROBLOX-NIVEAU02

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 ROBLOX-NIVEAU02

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 ROBLOX-NIVEAU02

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)