An obby is an obstacle course game where players jump through platforms, avoid dangers, and reach a finish line. It's perfect for learning Roblox Studio because it teaches you building, scripting, spawning, and collision detection all in one project.
This guide walks you through creating a complete obby from zero. You'll build platforms, add checkpoints that teleport players back if they fall, script a winning system, and test your game.
Set Up Your Workspace
Start by opening Roblox Studio and creating a new blank project. When Studio opens, you'll see the 3D viewport in the center, the Explorer panel on the right, and the Properties panel below it.
First, delete the default Spawn location. In the Explorer, find Workspace, then expand it. Click on SpawnLocation and press Delete. You don't need it for an obby.
Now add a baseplate for players to spawn on. In the Home tab, click Part. A gray cube will appear in the viewport. In the Properties panel:
- Set Size to (60, 1, 20) to make it long and flat.
- Set Position to (0, 0, 0).
- Change Material to Concrete or Grass to make it look nicer.
- Give it a Name of "Baseplate".
This is where players will spawn and start your obby.
Design Your Obstacle Course
Now create a series of platforms that get progressively harder. Start simple: players jump from one platform to the next, building up to trickier jumps and obstacles.
To make a platform, insert a Part, then scale and position it. Here's a quick workflow:
- Click Part in the Home tab.
- In Properties, change Size to something like (8, 1, 8) for a small jumping platform.
- Set Position to move it where you want (X, Y, Z).
- Change Material or Color to make platforms visually distinct.
- Give it a meaningful Name like "Platform1", "Platform2", etc.
Build at least 10–15 platforms in a path. Vary the distances between them so some jumps are easy and others challenging. Increase the height as players progress to add difficulty.
Add some obstacles too. Create narrow platforms, gaps players must long-jump, or spinning parts that push them off. Use cylinders, wedges, or rotated parts to mix up the challenge.
Add Checkpoints
Checkpoints let players respawn at a safe spot if they fall off. This prevents rage quits. Create a checkpoint part and a script that teleports players to it when they touch a kill part (like lava at the bottom).
First, create a checkpoint part at your starting platform. Insert a Part, make it small and invisible so it doesn't clutter the scene. In Properties:
- Set CanCollide to false.
- Set Transparency to 1 (invisible).
- Give it a Name like "Checkpoint1".
- Note its Position (you'll use this in scripts).
Create more checkpoints near major milestones in your course. Place them near platforms at roughly 25%, 50%, and 75% through your obby.
Now create a kill part at the bottom of your course. This is where players respawn if they fall. Insert a Part:
- Make it very long and flat, covering the area below your entire course.
- Set CanCollide to false.
- Set Transparency to 0.5 and BrickColor to red so it's visible but clear it kills.
- Name it "KillBrick".
Insert a new Script inside the KillBrick. In Explorer, right-click KillBrick, click Insert Object, then Script. Delete the default code and paste this:
local killBrick = script.Parent
local checkpointPosition = Vector3.new(0, 5, 0) -- Change this to your first checkpoint's position
killBrick.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
humanoid:TakeDamage(humanoid.Health)
end
end)Wait—that kills the player. We want to respawn them at a checkpoint instead. Let's use a different approach with a ServerScript in ServerScriptService that tracks each player's current checkpoint.
Delete the script you just made. Instead, go to ServerScriptService in Explorer (if it doesn't exist, right-click Workspace and insert it). Right-click ServerScriptService and insert a new Script. Name it "CheckpointManager". Paste this:
local players = game:GetService("Players")
local killBrick = workspace:WaitForChild("KillBrick")
-- Store each player's last checkpoint
local playerCheckpoints = {}
-- When a new player joins, track them
players.PlayerAdded:Connect(function(player)
playerCheckpoints[player] = Vector3.new(0, 5, 0) -- Start position (first checkpoint)
player.CharacterAdded:Connect(function(character)
playerCheckpoints[player] = Vector3.new(0, 5, 0)
end)
end)
-- Clean up when player leaves
players.PlayerRemoving:Connect(function(player)
playerCheckpoints[player] = nil
end)
-- Detect when a checkpoint is touched
local checkpoints = workspace:FindDescendants() -- Get all parts
for _, part in pairs(checkpoints) do
if part.Name:match("Checkpoint") then
part.Touched:Connect(function(hit)
local character = hit.Parent
local humanoid = character:FindFirstChild("Humanoid")
local player = players:FindFirstChild(character.Name) or players:GetPlayerFromCharacter(character)
if player and playerCheckpoints[player] then
playerCheckpoints[player] = part.Position + Vector3.new(0, 3, 0)
end
end)
end
end
-- Kill brick respawns player at last checkpoint
killBrick.Touched:Connect(function(hit)
local character = hit.Parent
local humanoid = character:FindFirstChild("Humanoid")
local player = players:GetPlayerFromCharacter(character)
if humanoid and player and playerCheckpoints[player] then
character:MoveTo(playerCheckpoints[player])
end
end)This script tracks each player's current checkpoint and teleports them there if they touch the kill brick.
Create a Finish Line
Players need a goal. Create a finish platform at the end of your course with a script that detects when they reach it.
Insert a Part and customize it:
- Make it visible and distinct (bright green is traditional).
- Position it at the end of your course, slightly elevated.
- Name it "Finish".
- Set CanCollide to false (so players stand on the platform below it, not on the finish part itself).
Insert a Script inside the Finish part. Replace the default code with:
local finishPart = script.Parent
local players = game:GetService("Players")
local playersFinished = {} -- Track who has finished this session
finishPart.Touched:Connect(function(hit)
local character = hit.Parent
local humanoid = character:FindFirstChild("Humanoid")
local player = players:GetPlayerFromCharacter(character)
if humanoid and player then
if not playersFinished[player] then
playersFinished[player] = true
print(player.Name .. " finished the obby!")
-- Optional: Teleport them back to start after 3 seconds
task.wait(3)
character:MoveTo(Vector3.new(0, 5, 0)) -- Your spawn position
playersFinished[player] = false
end
end
end)This script detects when a player reaches the finish, prints a victory message, and optionally respawns them to try again.
Spawn Players Correctly
By default, Roblox spawns players randomly on "Spawnable" parts. Since you deleted the default SpawnLocation, you need to tell Roblox where to spawn new players.
Select your Baseplate. In Properties, scroll down and find Anchored — make sure it's checked. Then look for CanCollide — make sure it's checked too.
Now, insert a SpawnLocation for spawning. In Home tab, click Part, then in Properties set Name to "SpawnLocation". Size it to (6, 1, 6) and position it on top of your Baseplate (around Y = 5). Make sure CanCollide is checked.
When you test your game, players will spawn on this SpawnLocation.
Make Sure Parts Don't Move
Before testing, anchor all your platforms so they don't fall through the world. This is easy to forget and breaks your entire obby.
In the Explorer, select all your platform parts (hold Shift and click each one). Then in Properties, check Anchored. Now they're locked in place.
Test Your Obby
Click the Play button at the top of Studio. Your game will run in test mode. Your character will spawn on the SpawnLocation.
Jump through your obstacle course. Test that:
- Each platform is reachable from the previous one.
- Checkpoints work (jump off and confirm you respawn at the last checkpoint you touched).
- The finish line detects you.
- No parts are falling or moving unexpectedly.
Stop the test by clicking Stop. Make adjustments: tighten difficult jumps, widen easy ones, adjust heights. Playtest again. Repeat until it's fun.
Polish and Publish
Once your obby plays well, add some polish. Change part materials and colors, add lighting, insert decorative parts (trees, buildings, themed objects). Use the Lighting service to adjust atmosphere.
When you're happy, publish your game:
- Click File > Publish to Roblox As.
- Fill in a title, description, and thumbnail.
- Choose whether it's public or private.
- Click Create.
Your obby is now live. Share the link with friends and watch them struggle through your course!
Next Steps
Once you master the basics, try adding:
- Rotating platforms — Use BodyVelocity or AssemblyAngularVelocity to spin parts.
- Moving platforms — Script parts to move back and forth using TweenService.
- Leaderboards — Track fastest completion times with DataStoreService.
- Custom themes — Swap your gray parts for a desert, space, or underwater aesthetic.
- Sound effects — Add jump sounds, victory music, and ambient sounds.