Your First Roblox Script
This walkthrough takes you from an empty Roblox Studio project to a published place with a real, working feature. We'll build a part that gives the player coins when they touch it — simple, but it covers every concept you'll use in every script after this one: instances, events, server scripts, and updating player state.
Step 1: Open Studio and create a baseplate
Launch Roblox Studio and pick the Baseplate template. You'll see a flat grey ground (the baseplate), a sky, and a spawn point. The Explorer pane on the right shows the data model tree — Workspace,Players, ReplicatedStorage, and friends.
If the Explorer or Properties panes aren't visible, find them under the View tab of the ribbon. You'll use both constantly.
Step 2: Place a coin part
In the Home tab, click Part to spawn a brick in front of the camera. Rename it Coin in the Explorer.
In the Properties pane, set:
BrickColor→ Bright yellowMaterial→ NeonSize→2, 2, 2Anchored→ true (so it doesn't fall)CanCollide→ false (the player can walk through it)
The coin is now a glowing yellow cube sitting in the world. You can drag it around with the Move tool to place it near the spawn.
Step 3: Add a Script to the coin
In the Explorer, hover over the Coin part and click the "+" that appears. Pick Script. A new script opens in the script editor with a one-line placeholder. Delete it and paste:
local coin = script.Parent
local Players = game:GetService("Players")
local debounce = {}
coin.Touched:Connect(function(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then return end
local player = Players:GetPlayerFromCharacter(character)
if not player then return end
-- Debounce: only credit once per second per player
if debounce[player] and tick() - debounce[player] < 1 then return end
debounce[player] = tick()
print(player.Name .. " picked up the coin!")
end)Press Play in the ribbon. Your avatar spawns; walk into the coin and watch the Output pane (View → Output if it's hidden). You should see "YourName picked up the coin!".
That's your first script working. Now let's make it do something visible.
Step 4: Give the player a coin counter
Roblox players have a child folder called leaderstats that, by convention, appears in the top-right leaderboard. We'll create one and add a Coins counter.
In ServerScriptService, add a new Script (right- click the service → Insert Object → Script) called SetupLeaderstats with:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
local stats = Instance.new("Folder")
stats.Name = "leaderstats"
stats.Parent = player
local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Value = 0
coins.Parent = stats
end)Now modify the coin script in Workspace to actually award the coin:
local coin = script.Parent
local Players = game:GetService("Players")
local debounce = {}
coin.Touched:Connect(function(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then return end
local player = Players:GetPlayerFromCharacter(character)
if not player then return end
if debounce[player] and tick() - debounce[player] < 1 then return end
debounce[player] = tick()
local stats = player:FindFirstChild("leaderstats")
local coinsValue = stats and stats:FindFirstChild("Coins")
if coinsValue then
coinsValue.Value += 1
end
end)Press Play again. Touch the coin — your Coins counter in the top-right increments to 1. Walk away, walk back, get another.
Step 5: Make the coin react
A coin that doesn't change after being picked up feels dead. Let's make it briefly hide and respawn.
local coin = script.Parent
local Players = game:GetService("Players")
local debounce = false
coin.Touched:Connect(function(otherPart)
if debounce then return end
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if not player then return end
local stats = player:FindFirstChild("leaderstats")
local coinsValue = stats and stats:FindFirstChild("Coins")
if not coinsValue then return end
debounce = true
coinsValue.Value += 1
coin.Transparency = 1
coin.CanTouch = false
task.wait(3)
coin.Transparency = 0
coin.CanTouch = true
debounce = false
end)A few things changed. The debounce flipped from a per-player table to a single boolean, because the whole coin is now unavailable while it's respawning. We use task.wait(3) instead of wait(3) — the new one is more predictable on the modern scheduler.
Press Play. Touch the coin, watch it vanish, wait three seconds, watch it return. That's a full feature loop.
Step 6: Save to a datastore (optional)
The coin count above only lives for one session — when the player leaves, it's gone. To persist it, add a DataStore. In ServerScriptService add another script:
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local coinStore = DataStoreService:GetDataStore("CoinsV1")
Players.PlayerAdded:Connect(function(player)
-- Wait for leaderstats setup above
local stats = player:WaitForChild("leaderstats")
local coins = stats:WaitForChild("Coins")
local ok, saved = pcall(function() return coinStore:GetAsync(player.UserId) end)
if ok and typeof(saved) == "number" then
coins.Value = saved
end
end)
Players.PlayerRemoving:Connect(function(player)
local stats = player:FindFirstChild("leaderstats")
local coins = stats and stats:FindFirstChild("Coins")
if coins then
pcall(function() coinStore:SetAsync(player.UserId, coins.Value) end)
end
end)Step 7: Publish
File → Publish to Roblox. Pick a name and an icon, set the genre, mark it public when you're ready. Your game now has a roblox.com page and anyone with the link can play it.
You can keep editing in Studio and re-publishing as you go — changes go live within seconds of clicking publish. There's no separate "deploy" step.
Common beginner mistakes
- Forgetting Anchored. Unanchored parts fall. You probably want most static parts to be anchored.
- No debounce.
.Touchedcan fire many times per second from multiple body parts. Always guard against re-entry. - LocalScript instead of Script. A LocalScript in Workspace doesn't run for any player. Use a regular Script for things you want to happen on the server.
- Skipping nil checks.
FindFirstChildcan return nil. Always check before dereferencing.
What to try next
Concrete next steps once the coin works end-to-end:
- Place ten coins by duplicating the part. The script lives on each part, so they all just work.
- Add a sound. Drop a
Soundinstance into the coin and call:Play()on it when picked up. - Build a shop. Make a script that reads the player's coins and lets them buy something — a hat, a colour, a power.
- Read the script types breakdown to understand server/client more deeply.
From here, every Roblox feature you build is just more of the same: place instances, connect events, update state. The patterns scale all the way to the largest games.
Ather is the lead developer behind Atherhub. He's been writing Luau and Roblox tooling for the better part of a decade, with a focus on the messy interface between game-script internals and the platforms that host them. Have feedback on this article? Drop it in the Discord.