Script vs LocalScript sur Roblox : le modèle client/serveur expliqué pour les débutants
TL;DR
Si tu places un LocalScript là où il ne peut pas tourner, ou que tu essaies d'accéder à game.Players.LocalPlayer depuis un Script serveur, ton code ne fera rien — sans toujours afficher d'erreur claire. Ce guide explique pourquoi, et surtout où placer quoi.
Le modèle client/serveur en deux mots
Quand tu joues à un jeu Roblox, il y a en réalité deux environnements distincts qui tournent en parallèle :
- Le serveur : une machine centralisée gérée par Roblox, invisible pour les joueurs. C'est lui qui fait autorité sur l'état du jeu.
- Le client : le jeu qui tourne sur la machine de chaque joueur, individuellement.
Ces deux environnements sont isolés l'un de l'autre. Un script côté serveur ne peut pas appeler directement un script côté client, et vice-versa. C'est la règle de base, et tout le reste en découle.
Script (serveur) vs LocalScript (client) : la différence fondamentale
| Script | LocalScript | |
|---|---|---|
| S'exécute sur | Le serveur | Le client (machine du joueur) |
| Visible par | Tous les joueurs | Un seul joueur |
Accès à LocalPlayer | ❌ Non (toujours nil) | ✅ Oui |
| Peut modifier le monde pour tout le monde | ✅ Oui | ⚠️ Localement seulement |
| Cas d'usage typique | Données, règles du jeu, sauvegardes | UI, inputs, effets visuels personnels |
Le Script (serveur)
Un Script classique tourne sur le serveur. Il gère tout ce qui doit être partagé entre tous les joueurs : les points de vie, les scores, la logique de jeu, les données sauvegardées avec DataStoreService. Ce que fait un Script est visible (et fait autorité) pour l'ensemble de la partie.
Les Scripts côté serveur sont utilisés pour la logique du jeu, comme gérer l'état de la partie et appliquer les règles. — Roblox Studio Scripts Guide
Le LocalScript (client)
Un LocalScript tourne sur la machine d'un joueur spécifique. Il est idéal pour tout ce qui touche à l'interface utilisateur, les inputs clavier/souris, ou les effets visuels personnalisés. Chaque joueur exécute sa propre instance du LocalScript — ce qui se passe chez l'un n'affecte pas les autres.
Les LocalScripts contrôlent le contenu visible uniquement pour le joueur concerné. — Roblox Wiki
game.Players.LocalPlayer : pourquoi ça ne marche pas dans un Script ?
C'est l'erreur numéro 1 des débutants. On écrit :
-- ❌ Dans un Script (serveur) — ça ne marche PAS
local player = game.Players.LocalPlayer
print(player.Name) -- affiche "nil" ou plante
La raison est simple : LocalPlayer n'existe que sur le client. Le serveur ne sait pas "qui" exécute le script, car il peut servir des dizaines de joueurs à la fois. LocalPlayer est toujours nil dans un Script serveur.
-- ✅ Dans un LocalScript (client) — correct
local player = game.Players.LocalPlayer
print(player.Name) -- affiche le nom du joueur local
Sur le serveur, si tu veux cibler un joueur précis, tu passes par les événements (voir section RemoteEvents plus bas) ou par game.Players.PlayerAdded.
Où placer tes scripts dans l'Explorer ?
C'est une question que tout le monde se pose au début. Voici les emplacements standards :
Pour les Scripts (serveur)
ServerScriptService→ l'endroit recommandé pour tous tes scripts serveur. Les joueurs ne peuvent pas voir ce qu'il y a dedans.ServerStorage→ pour stocker des objets/données côté serveur, inaccessibles au client.
Pour les LocalScripts (client)
Un LocalScript ne s'exécute que s'il est placé dans certains conteneurs liés au joueur :
StarterPlayerScripts→ copié dansPlayerScriptsde chaque joueur à la connexion. Idéal pour des scripts qui tournent pendant toute la session.StarterCharacterScripts→ copié dans le personnage à chaque respawn. Pratique pour des scripts liés au personnage (animations custom, effets sur le character...).StarterGui→ pour les scripts qui gèrent l'interface utilisateur (frames, boutons, etc.).StarterPack→ pour les scripts attachés aux outils (Tools) dans le backpack.ReplicatedFirst→ s'exécute en premier sur le client, avant même que la map soit chargée. Utile pour les écrans de chargement.
Un LocalScript ne peut s'exécuter que s'il se trouve dans un de ces emplacements valides : PlayerGui, Backpack, ReplicatedFirst, PlayerScripts, ou le modèle du personnage. — Roblox Wiki
⚠️ Si tu poses un LocalScript directement dans Workspace ou dans ServerScriptService, il ne tournera pas. Pas d'erreur, juste le silence — ce qui rend le bug très difficile à déboguer.
Et ReplicatedStorage dans tout ça ?
ReplicatedStorage est visible des deux côtés (client et serveur). On l'utilise pour stocker :
- Les
RemoteEventetRemoteFunction(les "ponts" de communication) - Les
ModuleScriptpartagés - Des assets accessibles par les deux côtés
Pour que le serveur et le client puissent tous deux accéder à un RemoteEvent, il doit être placé dans un endroit visible des deux côtés, comme
ReplicatedStorage. — Documentation officielle Roblox
Faire communiquer client et serveur : les RemoteEvents
Puisque les deux environnements sont isolés, comment font-ils pour se parler ? Via des RemoteEvents (et RemoteFunctions).
Le principe :
- Le client envoie une action au serveur avec
:FireServer() - Le serveur écoute avec
.OnServerEvent:Connect() - Le serveur peut envoyer quelque chose au client avec
:FireClient()ou:FireAllClients() - Le client écoute avec
.OnClientEvent:Connect()
Exemple concret : un joueur appuie sur une touche → le client prévient le serveur → le serveur donne des points.
-- ReplicatedStorage > RemoteEvent (nommé "GivePoints")
-- LocalScript (dans StarterPlayerScripts)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local givePoints = ReplicatedStorage:WaitForChild("GivePoints")
-- Quand le joueur appuie sur "E"
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed then return end
if input.KeyCode == Enum.KeyCode.E then
givePoints:FireServer() -- envoie la demande au serveur
end
end)
-- Script (dans ServerScriptService)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local givePoints = ReplicatedStorage:WaitForChild("GivePoints")
givePoints.OnServerEvent:Connect(function(player)
-- Le serveur vérifie et donne les points
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
leaderstats.Points.Value += 10
end
end)
Les scripts côté serveur et les scripts côté client ne peuvent pas s'appeler directement — ils fonctionnent dans des environnements isolés. Les RemoteEvent et RemoteFunction sont les ponts qui permettent aux deux côtés d'échanger des données. — LuaGuides
Récapitulatif : quoi mettre où ?
| Cas d'usage | Type de script | Emplacement recommandé |
|---|---|---|
| Logique de jeu (scores, règles) | Script | ServerScriptService |
| Sauvegarde DataStore | Script | ServerScriptService |
| Interface utilisateur (HUD, menus) | LocalScript | StarterGui |
| Input clavier / souris | LocalScript | StarterPlayerScripts |
| Effets sur le personnage | LocalScript | StarterCharacterScripts |
| Communication client ↔ serveur | RemoteEvent | ReplicatedStorage |
| Code partagé (utilitaires) | ModuleScript | ReplicatedStorage |
| Écran de chargement | LocalScript | ReplicatedFirst |
Erreurs classiques à éviter
-
LocalPlayerdans un Script → toujoursnil. Utilise un RemoteEvent. - LocalScript dans
WorkspaceouServerScriptService→ ne tourne jamais. - Modifier un objet côté client et s'attendre à ce que tout le monde le voie → les modifications client sont locales uniquement.
- Mettre un RemoteEvent dans
ServerStorage→ le client ne peut pas y accéder. - Oublier
WaitForChild()→ si le client charge avant que le serveur crée l'objet, tu obtiensnil.
FAQ rapide
Q : Mon script ne tourne pas, pas d'erreur dans la console — pourquoi ? R : Vérifie l'emplacement du script. Un LocalScript dans Workspace est silencieusement ignoré.
Q : Est-ce que je peux accéder à ServerStorage depuis un LocalScript ? R : Non. ServerStorage est invisible pour le client — c'est voulu, pour protéger tes données serveur.
Q : C'est quoi un ModuleScript alors ? R : Un ModuleScript n'est ni client ni serveur en lui-même — il est requis par d'autres scripts. C'est un moyen d'organiser du code réutilisable. Si tu le places dans ReplicatedStorage, il peut être utilisé des deux côtés.
Q : J'ai entendu parler de RunContext sur les Scripts, c'est quoi ? R : Roblox a ajouté une propriété RunContext sur les instances Script, permettant de choisir entre Server, Client ou Legacy. Ça permet techniquement de faire tourner un Script côté client, mais pour les débutants, la convention classique (LocalScript = client, Script = serveur) reste la plus claire à adopter.
Si tu débutes sur Roblox Studio et que tu cherches des scripts ou des ressources pour tes projets, jette un œil au marketplace GM Market — tu y trouveras des scripts testés et documentés qui respectent ces bonnes pratiques client/serveur.
Bonne chance dans ton projet ! N'hésite pas à poser tes questions en réponse. 🚀