How to make an obby in Roblox Studio
Stages, kill bricks and checkpoints that remember where each player got to — with one complete script and the design rules that keep players jumping.
Updated November 1, 20269 min read
An obby (obstacle course) is the easiest Roblox genre to finish and one of the most played. You need almost no scripting: the work is in level design — stages that get harder at a steady pace and checkpoints so a mistake never costs more than one stage.
The core loop
Every obby comes down to one loop that players repeat. Build this first, in grey blocks:
- Jump through a stage
- Touch the checkpoint
- Die on a kill brick, respawn at the last checkpoint
- Reach the next stage
Systems you need
Stages
Groups of parts between two checkpoints. Keep each stage 10–30 seconds long for a skilled player.
Kill bricks
Parts that reset the player on touch — lava, spikes, neon floors. Tag them so one script handles all of them.
Checkpoints
Flat parts numbered 1, 2, 3… Touching the next one saves the stage; after dying, the player is moved to it.
Stage counter
A Stage value in leaderstats shows progress on the player list and is what you save.
Saving
Store the stage number with DataStoreService so players continue where they left off.
Build order
- 1
Block out 10 stages in grey
Use plain parts first. Test that every jump is possible before you add any color or theme.
- 2
Add checkpoints
Put a flat anchored part at the start of every stage, name them
1,2,3… and put them in a Folder namedCheckpointsin Workspace. Keep one SpawnLocation at the start for new players. - 3
Tag the kill bricks
Select every deadly part, open Properties → Tags and add the tag
Kill. - 4
Paste the script and playtest
Die on purpose on every stage and check you respawn at the right checkpoint.
- 5
Theme it
One clear theme (lava, candy, space) with colors that make safe and deadly parts easy to tell apart.
- 6
Save progress and add skips
Save
Stagewith a data store, then sell a skip-stage developer product.
The key script: Checkpoints, kill bricks and a stage leaderboard
Where it goes: ServerScriptService > Obby (Script).
- Checkpoints are anchored parts named
1,2,3… insideWorkspace > Checkpoints. Checkpoint1sits next to the SpawnLocation. - Deadly parts have the tag
Kill(Properties → Tags).
local Players = game:GetService("Players")
local CollectionService = game:GetService("CollectionService")
local checkpoints = workspace:WaitForChild("Checkpoints")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Value = 1
stage.Parent = leaderstats
-- After every death, move the character to the last checkpoint reached.
player.CharacterAdded:Connect(function(character)
local checkpoint = checkpoints:FindFirstChild(tostring(stage.Value))
if checkpoint then
character:WaitForChild("HumanoidRootPart")
task.wait() -- let Roblox finish spawning the character first
character:PivotTo(checkpoint.CFrame + Vector3.new(0, 4, 0))
end
end)
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
task.spawn(onPlayerAdded, player)
end
-- Touching the next checkpoint saves the stage.
for _, checkpoint in checkpoints:GetChildren() do
local number = tonumber(checkpoint.Name)
checkpoint.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
if not player or not number then return end
local stage = player.leaderstats.Stage
if number == stage.Value + 1 then
stage.Value = number
end
end)
end
-- Every part tagged "Kill" resets whoever touches it.
local function makeDeadly(part)
part.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.Health = 0
end
end)
end
for _, part in CollectionService:GetTagged("Kill") do
makeDeadly(part)
end
CollectionService:GetInstanceAddedSignal("Kill"):Connect(makeDeadly)How it works
- The character respawns at the normal SpawnLocation and is moved to its checkpoint a moment later, so players never start a stage they already finished.
- Only the *next* checkpoint counts, so players can't skip ahead by touching stage 20 from stage 3.
- To save progress, store
Stagewith DataStoreService on leave and restore it on join — see the data store script.
How obbys make Robux
- Skip Stage developer product — the classic obby purchase. Grant it in
ProcessReceipt. - Game passes: speed coil, gravity coil, a trail, VIP chat tag.
- Keep it fair: every stage must be beatable without buying anything.
You receive 70% of what players spend on game passes and developer products; Roblox keeps 30%.
Common mistakes
Difficulty spikes
One impossible stage loses most players. Raise difficulty slowly and test with someone who has never seen the map.
Kill bricks that look like floor
Players should always know what kills them. Use a consistent color or material for danger.
Checkpoints you can skip
Without the “next checkpoint only” check, players touch a far checkpoint and jump ahead.
No saving
A 50-stage obby without saved progress loses everyone who has to leave.
FAQ
Do I need scripting to make an obby in Roblox?
Very little. The script on this page handles checkpoints, kill bricks and the stage counter. The rest is building stages from parts.
How many stages should an obby have?
Enough for 10–30 minutes of play for a first version — often 30 to 50 short stages. You can add more in updates.
How do I make obby checkpoints save?
Save the Stage value with DataStoreService when the player leaves and restore it when they join; the checkpoint script then moves them to that stage. Data stores work only in published places.