Tutorials•Updated October 6, 2026•14 min read

Roblox Studio Scripting Tutorial: Learn Luau from Scratch

Learn Roblox scripting with Luau basics, exact Script placement, five small examples, setup instructions, and a multiplayer test checklist.

Learn Roblox Scripting (Luau) from Zero

Scripting is what brings Roblox games to life. Every mechanic — from a kill brick to a complex combat system — is powered by Luau scripts. This tutorial takes you from zero coding knowledge to writing practical game scripts.

Roblox Studio scripting tutorial — learn Luau coding

Set up your first server Script

Open a Baseplate in Studio and enable Explorer, Properties, and Output. Insert a Script into ServerScriptService for the first two examples. Leave its RunContext at the default Legacy value. Start a play test and check Output; editing code without starting a test does not run it.

For the touch examples, create an anchored Part in Workspace and insert a separate Script beneath that Part. Keep CanTouch enabled. A Script under a Part has that Part as script.Parent. Pasting the same touch code into ServerScriptService changes what Parent means and will fail.

These examples use server Scripts. LocalScripts handle client behavior in supported locations, while ModuleScripts return reusable code that another script requires. See Roblox’s script types and locations for the current placement rules.

Basics: Variables and Print

local playerName = "Alex"
local score = 100
local isAlive = true

print("Player:", playerName)
print("Score:", score)

For a deeper check of conditions, try the true/false and boolean exercises.

Functions

local function greetPlayer(name)
  print("Welcome, " .. name .. "!")
end

greetPlayer("Alex")  -- prints: Welcome, Alex!

Events — The Heart of Roblox Scripting

Roblox is event-driven. Things happen when players touch parts, click buttons, or join the game.

-- When a player touches a part
script.Parent.Touched:Connect(function(hit)
  print(hit.Name .. " touched me!")
end)

5 Practical Scripts

Script 1: Kill Brick

script.Parent.Touched:Connect(function(hit)
  local humanoid = hit.Parent:FindFirstChild("Humanoid")
  if humanoid then
    humanoid.Health = 0
  end
end)

Script 2: Speed Boost Pad

Put this Script inside an anchored pad. One character gets one five-second boost at a time; another player can use the pad independently. It records the previous speed and only restores it if the speed still equals this boost. This is a small prototype: games with sprinting or multiple buffs need one movement system that owns the final speed.

local pad = script.Parent
local active = {}
local boostSpeed = 50

pad.Touched:Connect(function(hit)
  local character = hit:FindFirstAncestorOfClass("Model")
  local humanoid = character and character:FindFirstChildOfClass("Humanoid")
  if not humanoid or humanoid.Health <= 0 or active[humanoid] then
    return
  end

  active[humanoid] = true
  local previousSpeed = humanoid.WalkSpeed
  humanoid.WalkSpeed = boostSpeed

  task.delay(5, function()
    if humanoid.Parent and humanoid.WalkSpeed == boostSpeed then
      humanoid.WalkSpeed = previousSpeed
    end
    active[humanoid] = nil
  end)
end)

Walk across the pad repeatedly during the five seconds. The first activation controls the timer; repeated body-part contacts do not schedule additional resets.

Luau code examples in Roblox Studio — kill brick, speed boost

Script 3: Disappearing Platform

Use a new anchored Part with CanCollide enabled and Transparency set to zero. This platform disappears for everyone, so one shared debounce is appropriate. Roblox touch events can fire for multiple body parts; the flag prevents overlapping hide/show sequences.

local part = script.Parent
local busy = false

part.Touched:Connect(function(hit)
  local character = hit:FindFirstAncestorOfClass("Model")
  local humanoid = character and character:FindFirstChildOfClass("Humanoid")
  if not humanoid or humanoid.Health <= 0 or busy then
    return
  end
  busy = true
  task.wait(1)
  part.Transparency = 1
  part.CanCollide = false
  task.wait(3)
  part.Transparency = 0
  part.CanCollide = true
  busy = false
end)

Test with two players: both should see the same disappearing platform. For a deeper explanation, read Roblox’s debounce patterns.

Script 4: Coin Collector

First create a Script called Leaderstats in ServerScriptService. It creates a visible session-only coin count for each player. This example does not save progress between visits.

local Players = game:GetService("Players")

local function addStats(player)
  if player:FindFirstChild("leaderstats") then return end
  local stats = Instance.new("Folder")
  stats.Name = "leaderstats"
  local coins = Instance.new("IntValue")
  coins.Name = "Coins"
  coins.Value = 0
  coins.Parent = stats
  stats.Parent = player
end

Players.PlayerAdded:Connect(addStats)
for _, player in Players:GetPlayers() do
  addStats(player)
end

Then insert this separate Script inside an anchored coin Part. A coin is claimed once, globally; it is not a separate collectible for each player. Set the coin’s CanCollide property to false so it does not block the character.

local Players = game:GetService("Players")
local coin = script.Parent
local claimed = false

coin.Touched:Connect(function(hit)
  if claimed then return end
  local character = hit:FindFirstAncestorOfClass("Model")
  local player = character and Players:GetPlayerFromCharacter(character)
  local humanoid = character and character:FindFirstChildOfClass("Humanoid")
  if not player or not humanoid or humanoid.Health <= 0 then return end
  local stats = player:FindFirstChild("leaderstats")
  local coins = stats and stats:FindFirstChild("Coins")
  if not coins or not coins:IsA("IntValue") then return end

  claimed = true
  coins.Value += 1
  coin:Destroy()
end)

Confirm the score changes by exactly one when the coin disappears. Duplicate the coin to make a small collection course. Data persistence, purchases, and rewards supplied by clients require additional validation.

Script 5: A Shared Door with a Coin Requirement

Create an anchored door with CanCollide enabled and put this Script inside it. For a quick test, set the Leaderstats example’s starting Coins value to 10 before entering play mode. This gate checks a balance but does not spend coins. When a qualifying player opens it, everyone can pass during the three-second window. It is a shared-world prototype, not a secure per-player paid gate.

local Players = game:GetService("Players")
local door = script.Parent
local requiredCoins = 10
local busy = false

 door.Touched:Connect(function(hit)
  if busy then return end
  local character = hit:FindFirstAncestorOfClass("Model")
  local player = character and Players:GetPlayerFromCharacter(character)
  local stats = player and player:FindFirstChild("leaderstats")
  local coins = stats and stats:FindFirstChild("Coins")
  if not coins or not coins:IsA("IntValue") or coins.Value < requiredCoins then
    return
  end

  busy = true
  door.Transparency = 0.5
  door.CanCollide = false
  task.wait(3)
  door.Transparency = 0
  door.CanCollide = true
  busy = false
end)

Working in a larger project? Learn how to search code across all scripts before changing a mechanic.

Test before combining the examples

  • No output: check Script location, RunContext, and whether a play test is running.
  • Touched is missing: the Script is probably not directly under a BasePart. Check Explorer.
  • A touch does nothing: check CanTouch, the character’s health, and any cooldown flag.
  • Coins are missing: check the Leaderstats setup, exact capitalization, and Output errors.
  • Only one player is affected: identify whether that is the intended per-character state or an accidental shared flag.

Test each mechanic alone, then run a multi-client Studio test. Check repeated contacts, two simultaneous players, respawning during a boost, and a player leaving. Save a backup before combining scripts; our Studio saving guide covers local and cloud copies.

Ready to add character motion? Follow our first Roblox animation exercise before connecting a clip to gameplay.

For a small progression project, build a session-only XP rank display and test its promotion thresholds.

A practical learning sequence

Start with variables and Output, then functions, events, object references, and tables. Change one constant in a working example, predict the result, and test it. Next, make one mechanic from a blank Script without copying. Move to client/server communication and persistence only after you can explain where your code runs and who owns each piece of state. Learning time depends on practice and project complexity.

Use Roblox’s event documentation and client/server security guide when expanding a prototype.

Skip the Coding — Use AI

If scripting isn't your thing, Obby can help draft Luau code from a description. Specify the Script location, expected behavior, and test cases; inspect the output and verify it in Studio before publishing.

Try Obby free →

Frequently Asked Questions

What language does Roblox use for scripting?▾

Roblox uses Luau, a typed language derived from Lua. It's specifically designed for Roblox and is beginner-friendly.

How long does it take to learn Roblox scripting?▾

There is no fixed timeline. Start with one small mechanic, learn how to inspect Output and script placement, and practice modifying it before moving to multiplayer systems or persistent data.

Ready to build your Roblox game?

Create, edit, preview, and export your game for free. No credit card required.

Try Obby — 100% Free →