How to make an obby in Roblox
An obby (obstacle course) is the best first Roblox game: it's mostly building, the scripts are short, and you can test every jump yourself. This guide builds one from an empty baseplate: stages, checkpoints, kill bricks, moving platforms, a stage counter that saves, and a skip-stage button.
1. Plan your stages
Pick a theme first (a candy kingdom, a lava castle, a space station) and sketch 10 to 20 stages on paper. Each stage is one idea: a row of jumps, a balance beam, a spinning bar, a maze. Make them a little harder each time, and put an easy stage after a hard one so players get a breather.
A Roblox character jumps about 7 studs high and covers a gap of roughly 10 to 12 studs at normal speed. Keep your hardest jumps a bit shorter than that, and test every one yourself.
2. Build the jumps
- Open Roblox Studio and start from the Baseplate template.
- Add parts for platforms and shape them with the Move and Scale tools.
- Anchor every part (tick
Anchoredin Properties). Unanchored platforms fall the moment the game starts. - Use one colour per kind of thing: safe platforms one colour, danger red, checkpoints another. Players learn the rules from the colours.
- Group each stage into a model named "Stage 1", "Stage 2" and so on, so the Explorer stays tidy.
3. Kill bricks
A kill brick sends the player back to their last checkpoint. Make a red part, then insert a Script inside it:
local part = script.Parent
part.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.Health = 0
end
end)
Copy the part to make more; the script comes along. (For lots of kill bricks, one script that loops over a folder of them is tidier, but this is the easiest start.)
4. Checkpoints and a stage counter
Make a folder in Workspace called Checkpoints. Inside it, put one SpawnLocation at the start
of each stage and name them 1, 2, 3... in order. Set each one's
Neutral property on. Then add a Script to ServerScriptService:
local Players = game:GetService("Players")
local checkpoints = workspace:WaitForChild("Checkpoints")
Players.PlayerAdded:Connect(function(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
player.RespawnLocation = checkpoints:FindFirstChild("1")
end)
for _, checkpoint in checkpoints:GetChildren() do
checkpoint.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
local number = tonumber(checkpoint.Name)
if player and number and number == player.leaderstats.Stage.Value + 1 then
player.leaderstats.Stage.Value = number
player.RespawnLocation = checkpoint
end
end)
end
The number == Stage + 1 check means players can only move forward one stage at a time, so nobody skips
ahead by touching a later checkpoint. The stage shows on the player list because the folder is called
leaderstats.
5. Moving platforms
Put this Script inside an anchored part to slide it back and forth forever:
local TweenService = game:GetService("TweenService")
local platform = script.Parent
local info = TweenInfo.new(3, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true)
local goal = { Position = platform.Position + Vector3.new(0, 0, 20) }
TweenService:Create(platform, info, goal):Play()
The -1 repeats it forever and true makes it come back. One catch: a tweened platform can
slide out from under players instead of carrying them. For platforms players ride, use physics instead (an
unanchored part with a PrismaticConstraint or AlignPosition), or keep tweened ones for
things players jump over, like spinning bars.
6. Save the stage between visits
Players hate losing progress. Add saving to the checkpoint script with DataStoreService:
local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("ObbyStage")
-- in PlayerAdded, after creating Stage:
local ok, saved = pcall(function()
return store:GetAsync(player.UserId)
end)
if ok and saved then
stage.Value = saved
player.RespawnLocation = checkpoints:FindFirstChild(tostring(saved))
end
Players.PlayerRemoving:Connect(function(player)
pcall(function()
store:SetAsync(player.UserId, player.leaderstats.Stage.Value)
end)
end)
To test saving in Studio, turn on Enable Studio Access to API Services in the game's settings (Security). It only works once the game is published or saved to Roblox.
7. A skip-stage product
Obbies often sell a "skip stage" for a few Robux, so stuck players can move on. It's a developer product (it can be bought again and again). Create it in Creator Hub, copy its ID (our game passes and developer products guide shows where), then add a Script:
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local SKIP_STAGE_ID = 0 -- paste your developer product ID here
MarketplaceService.ProcessReceipt = function(receipt)
local player = Players:GetPlayerByUserId(receipt.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
if receipt.ProductId == SKIP_STAGE_ID then
local stage = player.leaderstats.Stage
local nextCheckpoint = workspace.Checkpoints:FindFirstChild(tostring(stage.Value + 1))
if nextCheckpoint then
stage.Value += 1
player.RespawnLocation = nextCheckpoint
player:LoadCharacter()
end
end
return Enum.ProductPurchaseDecision.PurchaseGranted
end
A button in your UI calls MarketplaceService:PromptProductPurchase(player, SKIP_STAGE_ID) from a
LocalScript. Hide the button on the last stage, since there's nothing to skip to. Only one script in your game may set
ProcessReceipt: if you sell more products, handle them all in this one function.
8. Polish and publish
- Signs: number every stage so players know how far they've come.
- A finish: a big end platform, a badge or a winners' area makes finishing feel like something.
- Phones: test on a phone; jumps that are easy with a keyboard can be hard with touch controls.
- Publish: File > Publish to Roblox, then make it public. The steps are in how to make a Roblox game.
Generate an obby instead
If you'd rather start from a finished obby and change it, BloxMaps has two ways:
- The Game Maker builds a whole obby game: stages with checkpoints that save, a skip-stage product, speed and gravity passes and a finish reward, plus the UI and shop, in one Roblox Studio file. It also builds deathruns (one player springs the traps) and flood escapes (the water rises behind you). These obby formats are in Beta.
- The map generator builds just the course, with checkpoints and pieces that work when you press Play.
an obby in a candy kingdom with checkpoints, skip stages and a finish line reward
Try this prompt
Building and previewing is free; exporting the finished game costs $14.99 once. Need more stage themes? Browse obby ideas.
Questions
Is an obby a good first Roblox game?
Yes. It's mostly building, the scripts are short, and you can test every stage yourself.
How many stages should an obby have?
There's no rule. Start with 10 to 20 you've tested, publish, and add more in updates.
How do I make a checkpoint?
Put a SpawnLocation at the start of the stage and a short script that sets the player's RespawnLocation when they touch it (the obby guide has it). Saving the stage number with a DataStore brings players back to it next time.
Do I still need Roblox Studio?
Yes, to publish. BloxMaps makes the game file in your browser; you open that file in Roblox Studio (free, for Windows and Mac) and publish it to Roblox from there.
Is BloxMaps free?
Making and previewing is free: 3 previews a day on the Free plan. You pay only to export. You only pay to export the finished Roblox Studio file (.rbxl): $14.99 once per game, or included with the Studio plan. See pricing.