Objectif : Maîtriser les animations fluides avec TweenService, créer des interactions immersives avec ProximityPrompt, et publier ton jeu pour le monde entier !
Les détails qui font la différence
Tu as appris à coder des systèmes puissants. Maintenant, on va les rendre beaux et fluides ! TweenService pour les animations, ProximityPrompt pour les interactions, et enfin : la publication !
TweenService crée des transitions douces entre deux valeurs. Fini les mouvements brusques ! Parfait pour portes, UI, effets visuels...
Structure d'un Tween
local TweenService = game:GetService("TweenService")
local part = script.Parent
-- 1. Configurer les options du tween
local tweenInfo = TweenInfo.new(
2, -- Durée (secondes)
Enum.EasingStyle.Quad, -- Style d'animation
Enum.EasingDirection.Out, -- Direction
0, -- Répétitions (0 = une fois)
false, -- Reverse ?
0 -- Délai avant de démarrer
)
-- 2. Définir les propriétés finales
local goal = {
Position = Vector3.new(0, 10, 0),
Transparency = 0.5
}
-- 3. Créer et jouer le tween
local tween = TweenService:Create(part, tweenInfo, goal)
tween:Play()
L'EasingStyle définit la courbe de l'animation :
Vitesse constante
Accélération douce
Effet rebond
Effet élastique
local TweenService = game:GetService("TweenService")
local door = script.Parent
local isOpen = false
local openPosition = door.Position + Vector3.new(0, 7, 0)
local closedPosition = door.Position
local tweenInfo = TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
local function toggleDoor()
local goal
if isOpen then
goal = {Position = closedPosition}
else
goal = {Position = openPosition}
end
local tween = TweenService:Create(door, tweenInfo, goal)
tween:Play()
isOpen = not isOpen
end
-- Connecte à un ClickDetector ou ProximityPrompt
door.ClickDetector.MouseClick:Connect(toggleDoor)
TweenService marche aussi sur les GuiObject ! Tu peux
animer Position, Size,
BackgroundTransparency
pour des interfaces fluides.
On a vu les bases du ProximityPrompt. Voyons maintenant les options avancées pour des interactions immersives !
Configuration complète
local prompt = Instance.new("ProximityPrompt")
prompt.Parent = script.Parent
-- Texte et apparence
prompt.ActionText = "Ouvrir" -- Texte du bouton
prompt.ObjectText = "Coffre au trésor" -- Nom de l'objet
prompt.KeyboardKeyCode = Enum.KeyCode.E -- Touche clavier
-- Comportement
prompt.HoldDuration = 0.5 -- Temps à maintenir (0 = instant)
prompt.MaxActivationDistance = 10 -- Distance d'activation
prompt.RequiresLineOfSight = true -- Doit voir l'objet
-- Style
prompt.Style = Enum.ProximityPromptStyle.Default -- ou Custom
prompt.UIOffset = Vector2.new(0, -50) -- Décalage de l'UI
-- Événements
prompt.Triggered:Connect(function(player)
print(player.Name .. " a interagi !")
end)
prompt.PromptShown:Connect(function(style)
print("Prompt visible")
end)
prompt.PromptHidden:Connect(function()
print("Prompt caché")
end)
-- Script dans un collectible (pièce, gemme...)
local item = script.Parent
local prompt = item:FindFirstChild("ProximityPrompt")
prompt.ActionText = "Ramasser"
prompt.ObjectText = "Pièce d'or (+10)"
prompt.HoldDuration = 0
prompt.Triggered:Connect(function(player)
-- Ajoute les coins
local coins = player.leaderstats.Coins
coins.Value = coins.Value + 10
-- Effet de ramassage
local sound = Instance.new("Sound")
sound.SoundId = "rbxassetid://12345678" -- ID du son
sound.Parent = item
sound:Play()
-- Animation de disparition
local TweenService = game:GetService("TweenService")
local tween = TweenService:Create(item, TweenInfo.new(0.3), {
Transparency = 1,
Size = Vector3.new(0, 0, 0)
})
tween:Play()
tween.Completed:Wait()
item:Destroy()
end)
Ton jeu est prêt ! Voici comment le partager avec le monde entier.
File ? Publish to Roblox (ou Ctrl+Shift+P). Donne un nom et une description à ton jeu.
Home ? Game Settings. Configure les permissions, l'icône, les thumbnails, et les options de monétisation.
Dans Game Settings ? Permissions, passe le jeu de "Private" à "Public".
L'apparence de ta page de jeu attire les joueurs ! Voici les tailles recommandées :
512 x 512 px
1920 x 1080 px
30 sec max
Types de monétisation
Tu as terminé la formation LearnBlox ! Tu sais maintenant créer des jeux Roblox avec des scripts Luau, des interfaces, des sauvegardes, et plus encore. Continue à apprendre et à créer !
5 questions pour valider tes acquis
Ajoute du "Juice" à ton jeu avec des animations fluides (TweenService) et publie-le pour que le monde entier puisse y jouer !
Modules 1 à 9 complétés (TweenService)
Modifie ton script HUD (Module 8) pour utiliser
TweenService
au lieu de changer la taille instantanément.
Fais flotter tes objets (Oxygène, etc.) dans les airs !
File > Publish to Roblox
🎉 Ton jeu est maintenant en ligne sur Roblox !
Ajoute une musique d'ambiance et des sons quand tu ramasses un
objet ! Utilise SoundService.
Tu es maintenant un développeur Roblox confirmé. Bravo !
Le moment est venu d'assembler tous les systèmes ! Crée la boucle de survie avec cycle jour/nuit, événements aléatoires, et écran de victoire à 100 jours.
Un "jour" dans le jeu dure 60 secondes. Crée un
script GameLoop dans
ServerScriptService :
-- GameLoop.lua - Le cœur du jeu !
local
Players =
game:GetService("Players") local
ReplicatedStorage =
game:GetService("ReplicatedStorage") local
Lighting =
game:GetService("Lighting") local
TweenService =
game:GetService("TweenService")
-- Configuration
local DUREE_JOUR =
60
-- Secondes par jour
local JOUR_VICTOIRE =
100
-- Jours pour gagner
local ENERGIE_PAR_JOUR =
15
-- Énergie consommée par jour
-- RemoteEvents
local nouveauJourEvent =
Instance.new("RemoteEvent") nouveauJourEvent.Name =
"NouveauJour"
nouveauJourEvent.Parent =
ReplicatedStorage
local victoireEvent =
Instance.new("RemoteEvent") victoireEvent.Name =
"Victoire" victoireEvent.Parent =
ReplicatedStorage
local gameOverEvent =
Instance.new("RemoteEvent") gameOverEvent.Name =
"GameOver" gameOverEvent.Parent =
ReplicatedStorage
Utilise TweenService pour faire tourner le soleil et créer une ambiance dynamique :
-- FONCTION : Animer le passage du temps
local function
animerCycleJour()
-- Matin (6h) → Midi (12h) → Soir (18h) → Nuit (0h)
local tempsDepart =
Lighting.ClockTime
local tweenInfo =
TweenInfo.new( DUREE_JOUR,
-- Durée totale
Enum.EasingStyle.Linear,
-- Linéaire
Enum.EasingDirection.InOut )
-- Faire avancer l'horloge de 24h
local tween =
TweenService:Create(Lighting, tweenInfo, { ClockTime = tempsDepart +
24 }) tween:Play() tween.Completed:Wait()
-- Remettre à 0 pour éviter des valeurs énormes
Lighting.ClockTime = tempsDepart
end
Crée la boucle principale qui gère chaque jour, consomme l'énergie et vérifie les conditions de victoire/défaite :
-- FONCTION : Traiter un nouveau jour pour un joueur
local function
traiterNouveauJour(player)
local energie = player:GetAttribute("Energie")
or 0
local jours = player:GetAttribute("JoursSurvecus")
or 0
-- Consommer de l'énergie
energie = energie - ENERGIE_PAR_JOUR
-- Vérifier si énergie épuisée (GAME OVER)
if energie <=
0
then gameOverEvent:FireClient(player, { joursVecus = jours, cause =
"Énergie épuisée"
})
return false
end
-- Incrémenter les jours
jours = jours + 1
-- Vérifier VICTOIRE
if jours >= JOUR_VICTOIRE
then victoireEvent:FireClient(player, { joursVecus = jours, cristaux = player:GetAttribute("Cristaux")
or 0
})
return true
end
-- Mettre à jour les attributs
player:SetAttribute("Energie", energie) player:SetAttribute("JoursSurvecus", jours)
-- Notifier le client
nouveauJourEvent:FireClient(player,
jours)
return true
end
-- BOUCLE PRINCIPALE
while true do
-- Animer le jour (60 secondes)
animerCycleJour()
-- Traiter chaque joueur
for _, player
in
pairs(Players:GetPlayers())
do
traiterNouveauJour(player)
end
print("🌅 Nouveau jour !") end
Ajoute des événements aléatoires pour pimenter le gameplay :
-- Table des événements possibles
local EVENEMENTS = { { nom =
"Pluie de météorites", description
=
"⚠️ La station subit des impacts !", effet = function(player)
local perte =
math.random(5, 15)
local energie = player:GetAttribute("Energie")
or
0 player:SetAttribute("Energie",
math.max(0, energie - perte)) end, chance
= 15
-- 15% de chance }, { nom =
"Bonus solaire", description =
"☀️ Les panneaux captent plus d'énergie !", effet = function(player)
local bonus =
math.random(10, 25)
local energie = player:GetAttribute("Energie")
or 0
local max = player:GetAttribute("EnergieMax")
or
100 player:SetAttribute("Energie",
math.min(max, energie + bonus))
end, chance =
20 }, { nom =
"Découverte de cristaux",
description =
"💎 Un filon de cristaux apparaît !", effet = function(player)
local bonus =
math.random(3, 8)
local cristaux = player:GetAttribute("Cristaux")
or
0 player:SetAttribute("Cristaux", cristaux + bonus)
end, chance =
10
} }
-- FONCTION : Tenter un événement aléatoire
local function
tenterEvenement(player)
for _, event
in
pairs(EVENEMENTS)
do
if
math.random(100) <= event.chance
then event.effet(player)
-- Notifier le client
ReplicatedStorage.EvenementAleatoire:FireClient(player, event)
return
end
end
end
tenterEvenement(player) dans la boucle
traiterNouveauJour pour ajouter du suspense !
Crée un LocalScript dans
StarterPlayerScripts
pour afficher l'écran de fin :
-- EcranFin.lua (LocalScript)
local
ReplicatedStorage =
game:GetService("ReplicatedStorage") local
TweenService =
game:GetService("TweenService") local
Players =
game:GetService("Players")
local player =
Players.LocalPlayer
local gui = player.WaitForChild("PlayerGui")
-- FONCTION : Créer l'écran de fin
local function
afficherEcranFin(victoire, data)
local screen =
Instance.new("ScreenGui") screen.Name = "EcranFin"
screen.Parent = gui
local fond =
Instance.new("Frame") fond.Size = UDim2.new(1, 0,
1, 0)
fond.BackgroundColor3 = victoire
and
Color3.fromRGB(16, 185,
129)
-- Vert victoire
or
Color3.fromRGB(239, 68,
68)
-- Rouge défaite
fond.BackgroundTransparency = 1
fond.Parent = screen
-- Animation d'apparition
local tween =
TweenService:Create(fond,
TweenInfo.new(0.5, Enum.EasingStyle.Quad),
{BackgroundTransparency = 0.3} )
tween:Play()
-- Texte principal
local titre =
Instance.new("TextLabel") titre.Text = victoire and
"🏆 VICTOIRE !"
or
"💀 GAME OVER" titre.Font =
Enum.Font.GothamBold
titre.TextSize =
72 titre.TextColor3 =
Color3.new(1, 1,
1) titre.Position =
UDim2.new(0.5, 0,
0.3,
0) titre.AnchorPoint =
Vector2.new(0.5, 0.5)
titre.BackgroundTransparency = 1
titre.Parent = fond
-- Stats
local stats =
Instance.new("TextLabel") stats.Text =
"📅 Jours survécus : " ..
data.joursVecus stats.Font =
Enum.Font.Gotham stats.TextSize =
36 stats.Position =
UDim2.new(0.5, 0,
0.5,
0) stats.AnchorPoint =
Vector2.new(0.5, 0.5)
stats.BackgroundTransparency = 1
stats.Parent = fond
end
-- Écouter les événements
ReplicatedStorage:WaitForChild("Victoire").OnClientEvent:Connect(function(data)
afficherEcranFin(true, data) end)
ReplicatedStorage:WaitForChild("GameOver").OnClientEvent:Connect(function(data)
afficherEcranFin(false, data) end)
Tu maîtrises maintenant Lua, les systèmes de jeu, l'architecture client/serveur, et les bonnes pratiques de développement Roblox. Tu es prêt à créer n'importe quel jeu !