Finitions & Publication

Objectif : Maîtriser les animations fluides avec TweenService, créer des interactions immersives avec ProximityPrompt, et publier ton jeu pour le monde entier !

Le Polish Final

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 !

0. Le mindset "jeu publiable"

À ce stade, l'objectif n'est plus seulement "que ça fonctionne" mais que l'expérience soit propre, fluide et compréhensible pour un vrai joueur. Le polish, c'est la différence entre un prototype et un jeu qu'on recommande.

Avant la publication, vérifie toujours : clarté de l'objectif, feedback visuel/sonore, performances stables, absence de blocages critiques, et parcours joueur lisible dès la première minute.

Checklist pré-publication

1) Onboarding rapide (le joueur comprend quoi faire).
2) UX cohérente (prompts, boutons, messages).
3) Tests solo + multijoueur sans erreur bloquante.
4) Boucle de jeu claire et gratifiante.

0.5 Quand polish rime avec rétention

Les animations, prompts et retours sonores ne sont pas du "bonus" : ils guident le joueur, réduisent la frustration et augmentent les chances qu'il revienne jouer.

Utilise le polish pour clarifier l'action, pas pour distraire. Chaque effet doit avoir une fonction : signaler, confirmer, orienter ou récompenser.

  • Erreur fréquente : trop d'effets simultanés
  • Erreur fréquente : animation jolie mais sans utilité gameplay
  • Erreur fréquente : publication sans tests multijoueur
  • Erreur fréquente : absence de plan de corrections post-lancement

0.8 Parcours pédagogique section par section

Section 1 - TweenService

Définition : Système d'animation fluide de propriétés.

Pourquoi : Améliorer la lisibilité des actions et le ressenti.

Quand l'utiliser : Portes, transitions UI, feedbacks visuels, objets dynamiques.

Anti-pattern : Animer tout en permanence sans priorité UX.

Exercice guidé : Anime une porte avec ouverture, fermeture et état cohérent.

Résumé : L'animation doit servir la compréhension du joueur.

Section 2 - ProximityPrompt

Définition : Interaction contextuelle par proximité.

Pourquoi : Rendre les interactions claires sans UI intrusive.

Quand l'utiliser : Coffres, PNJ, leviers, stations de craft.

Anti-pattern : Prompts partout avec distances excessives.

Exercice guidé : Configure un prompt avec validation serveur et feedback visuel.

Résumé : Un prompt bien calibré fluidifie l'exploration et l'action.

Section 3 - Publication

Définition : Passage du prototype local à une expérience publique.

Pourquoi : Garantir qualité, sécurité et stabilité avant diffusion.

Quand l'utiliser : Après cycle complet de tests fonctionnels et UX.

Anti-pattern : Publier sans checklist ni plan de suivi.

Exercice guidé : Réalise une checklist de sortie puis corrige 3 points critiques.

Résumé : Une bonne publication est un processus, pas un clic.

1. TweenService : Animations Fluides

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()

1.2 Les Styles d'Animation

L'EasingStyle définit la courbe de l'animation :

Linear

Vitesse constante

Quad

Accélération douce

Bounce

Effet rebond

Elastic

Effet élastique

1.3 Exemple : Porte Coulissante

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)

Tweens sur UI

TweenService marche aussi sur les GuiObject ! Tu peux animer Position, Size, BackgroundTransparency pour des interfaces fluides.

2. ProximityPrompt Avancé

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)

2.2 Exemple : Système de Ramassage

-- 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)

3. Publier ton Jeu

Ton jeu est prêt ! Voici comment le partager avec le monde entier.

Avant de publier, vérifie :
  • ✅ Ton jeu fonctionne sans erreurs
  • ✅ Les sauvegardes sont testées
  • ✅ L'expérience est fun et équilibrée
  • ✅ Pas de contenu inapproprié

3.1 Étapes de Publication

1
Sauvegarder sur Roblox

File ? Publish to Roblox (ou Ctrl+Shift+P). Donne un nom et une description à ton jeu.

2
Configurer Game Settings

Home ? Game Settings. Configure les permissions, l'icône, les thumbnails, et les options de monétisation.

3
Rendre Public

Dans Game Settings ? Permissions, passe le jeu de "Private" à "Public".

3.2 Les Icônes et Thumbnails

L'apparence de ta page de jeu attire les joueurs ! Voici les tailles recommandées :

Icône

512 x 512 px

Thumbnail

1920 x 1080 px

Vidéo

30 sec max

3.3 Monétisation (Optionnel)

Types de monétisation

  • Game Passes ? Achats uniques (VIP, double XP...)
  • Developer Products ? Achats répétables (packs de coins)
  • Premium Payouts ? Rémunération basée sur le temps de jeu des abonnés Premium

🎉 Félicitations !

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 !

💻 Sandbox Luau
Simulateur v2.0
1 2 3 4 5 6 7 8 9 10
💡 Explore les options de TweenInfo...

Quiz : Finitions & Publication

5 questions pour valider tes acquis

1. Quel service permet de créer des animations fluides ?

  • AnimationService
  • TweenService
  • MotionService
  • TransitionService

2. Quel EasingStyle crée un effet de rebond ?

  • Quad
  • Elastic
  • Bounce
  • Linear

3. Quelle propriété de ProximityPrompt définit le temps de maintien ?

  • PressTime
  • HoldDuration
  • ActivationTime
  • WaitDuration

4. Quelle taille est recommandée pour l'icône du jeu ?

  • 256 x 256 px
  • 512 x 512 px
  • 1024 x 1024 px
  • 128 x 128 px

5. Quel type de monétisation permet des achats répétables ?

  • Game Passes
  • Developer Products
  • Premium Payouts
  • Robux Direct
Challenge Code

Sauvegarde les Données

Complète ce script pour sauvegarder les pièces d'un joueur avec DataStore.

15-50 Points
DataStore.lua
-- Accède au service de sauvegarde
local DataStoreService = game:("DataStoreService")
local playerData = DataStoreService:("PlayerSaves")
-- Charge les données (peut échouer !)
local success, data = (function()
  return playerData:(playerId) -- Lit les données
end)
if success then print("Données chargées !") end
🚀
Étape Finale !

Animations & Publication

Ajoute du "Juice" à ton jeu avec des animations fluides (TweenService) et publie-le pour que le monde entier puisse y jouer !

1
2
3
4
5
6
7
8
9
10
Prérequis

Modules 1 à 9 complétés (TweenService)

Polish Final

1
Animation du HUD (Tween)

Modifie ton script HUD (Module 8) pour utiliser TweenService au lieu de changer la taille instantanément.

🏆 Défi Final - Code 100% autonome !
Objectif : Animer la barre d'oxygène avec TweenService
Tu as appris TweenService dans ce module. Applique-le au HUD du module 8 !
🔒
Solution Finale
Tu es arrivé au bout ! Prouve que tu maîtrises tout ce que tu as appris.
2
Animation des Collectibles

Fais flotter tes objets (Oxygène, etc.) dans les airs !

🏆 Défi Final - Tu gères !
Objectif : Faire flotter un objet de haut en bas avec un Tween qui boucle
Paramètre RepeatCount = -1 pour boucle infinie, Reverses = true pour aller-retour
🔒
Solution Finale
Dernier effort ! Tu connais TweenInfo et ses paramètres.
3
🚀 PUBLIE TON JEU !

File > Publish to Roblox

  1. Choisis un nom : "Survie Spatiale" (ou ton propre nom !)
  2. Ajoute une description : "Survis 100 jours dans une station spatiale endommagée !"
  3. Genre : Survival
  4. Clique sur "Create" puis "Publish"

🎉 Ton jeu est maintenant en ligne sur Roblox !

Bonus : Sons & Musique

Ajoute une musique d'ambiance et des sons quand tu ramasses un objet ! Utilise SoundService.

🎮 RÉCAP : TON JEU "SURVIE SPATIALE"

🎯 Objectif
Survivre 100 jours dans ta station spatiale
⚙️ Mécaniques
Gérer oxygène, énergie, matériaux
💾 Sauvegarde
Progression conservée (DataStore)
✨ Ambiance
Animations fluides et interface pro
🏆

FORMATION TERMINÉE !

Tu es maintenant un développeur Roblox confirmé. Bravo !

🏆
🚀 SURVIE SPATIALE - FINALE

Boucle de Jeu Complète

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.

1
2
3
4
5
6
7
8
9
10
C'est le grand final ! Ce module assemble TOUT ce que tu as appris. Prends ton temps et teste régulièrement.
1
⏰ Créer le Cycle Jour/Nuit

Un "jour" dans le jeu dure 60 secondes. Crée un script GameLoop dans ServerScriptService :

📁 ServerScriptService
📜 GestionSauvegarde
📜 GestionnaireRessources
📜 GameLoop
-- 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
2
🌅 Animer le Cycle Lumineux

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
3
🔁 La Boucle de Survie

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
4
🎲 Événements Aléatoires

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
Appelle tenterEvenement(player) dans la boucle traiterNouveauJour pour ajouter du suspense !
5
🎉 Écran de Victoire (Client)

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)
🚀
Publier sur Roblox !
  1. Va dans File → Publish to Roblox
  2. Nomme ton jeu : "Survie Spatiale - 100 Jours"
  3. Description : "Peux-tu survivre 100 jours dans une station spatiale endommagée ? Gère tes ressources, collecte des cristaux et fais face aux événements aléatoires !"
  4. Genre : Survival
  5. Clique sur Create puis Publish
🎉 FÉLICITATIONS !
Tu as créé un jeu de survie complet avec toutes les mécaniques d'un vrai jeu Roblox professionnel !
📋
Récap : Tout ce que tu as créé
Module 1-3 Structure de la station spatiale
Module 4 Réacteur & Système d'énergie (fonctions)
Module 5 Zone de collecte de cristaux (physique)
Module 6 Portes sécurisées (événements)
Module 7 HUD de la station (client/serveur)
Module 8 Animations fluides (TweenService)
Module 9 Sauvegarde progression (DataStore)
Module 10 Game Loop & Victoire à 100 jours
🏆

DÉVELOPPEUR ROBLOX CERTIFIÉ !

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 !