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:

  1. Jump through a stage
  2. Touch the checkpoint
  3. Die on a kill brick, respawn at the last checkpoint
  4. 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. 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. 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 named Checkpoints in Workspace. Keep one SpawnLocation at the start for new players.

  3. 3

    Tag the kill bricks

    Select every deadly part, open Properties → Tags and add the tag Kill.

  4. 4

    Paste the script and playtest

    Die on purpose on every stage and check you respawn at the right checkpoint.

  5. 5

    Theme it

    One clear theme (lava, candy, space) with colors that make safe and deadly parts easy to tell apart.

  6. 6

    Save progress and add skips

    Save Stage with 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… inside Workspace > Checkpoints. Checkpoint 1 sits next to the SpawnLocation.
  • Deadly parts have the tag Kill (Properties → Tags).
ServerScriptService > Obby (Script)
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 Stage with 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.

Keep reading