If you're building an obby, you definitely need a solid roblox checkpoint teleport script to keep players from losing their minds when they fall off a floating platform for the tenth time. There's nothing that kills the vibe of a game faster than making someone restart from the very beginning because a script didn't trigger correctly. Most of us have been there—you spend an hour grinding through difficult jumps only to realize the "save" point you just touched didn't actually do anything.
Setting up a checkpoint system might seem like a headache if you're new to Luau, but it's actually one of the more rewarding things to learn early on. It teaches you about touched events, variables, and how the game handles the player's character model. Once you get the hang of it, you can apply the same logic to all sorts of things, like teleporters, area transitions, or even stage-based rewards.
Why checkpoints are the backbone of your obby
Let's be real: unless you're purposely making one of those "rage games" that people play for the frustration factor, checkpoints are mandatory. A good roblox checkpoint teleport script ensures that the player's progress is respected. In technical terms, we're essentially telling the game, "Hey, this player reached this specific Coordinate Frame (CFrame), so the next time they reset, put them back there."
In the early days of Roblox, people used to use the default SpawnLocation objects and change the player's Team to manage checkpoints. While that still works for some basic games, it's a bit clunky. Modern games usually handle this with a script that tracks a "Stage" value for each player. This way, you don't have to deal with fifty different team colors just because your obby has fifty levels.
Setting up the parts in Studio
Before we even look at the code, you need something for the player to touch. I usually just use a flat Part, make it slightly transparent, and maybe give it a nice neon glow so players know it's a safe zone.
- Create a Part and name it "1".
- Put it in a Folder in the Workspace called "Checkpoints".
- Duplicate it and name the next one "2", and so on.
- Make sure they are all Anchored and CanCollide is off if you want players to walk through them, or on if you want them to stand on top.
Using a folder makes your life so much easier later. Instead of having scripts scattered all over the place, you can have one central script that looks through that folder and figures out what to do. It's a lot cleaner and way easier to debug when things inevitably go sideways.
The logic behind the script
The most common way to handle a roblox checkpoint teleport script is to use a NumberValue or IntValue inside the player. When a player touches a checkpoint part, the script checks if the number of that checkpoint is higher than the player's current "Stage" value. If it is, the script updates the value.
The second half of the puzzle is the teleportation. When the player's character loads in (after dying or joining), the script looks at that Stage value, finds the corresponding part in your Checkpoints folder, and moves the player's HumanoidRootPart to that position.
A simple script to get you started
You'll want to put this in ServerScriptService. This isn't the only way to do it, but it's a very reliable method for beginners and intermediate builders alike.
```lua game.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.CharacterAdded:Connect(function(character) local root = character:WaitForChild("HumanoidRootPart") wait(0.1) -- Give the engine a split second to breathe local checkpoint = workspace.Checkpoints:FindFirstChild(tostring(stage.Value)) if checkpoint then root.CFrame = checkpoint.CFrame + Vector3.new(0, 3, 0) end end) end)
-- The part that handles touching the checkpoints for _, checkpoint in pairs(workspace.Checkpoints:GetChildren()) do checkpoint.Touched:Connect(function(hit) local character = hit.Parent local player = game.Players:GetPlayerFromCharacter(character)
if player then local stageValue = player.leaderstats.Stage local checkpointNumber = tonumber(checkpoint.Name) if checkpointNumber > stageValue.Value then stageValue.Value = checkpointNumber end end end) end ```
This script does two things: it sets up the "leaderstats" so you can see your level on the scoreboard, and it listens for when a character spawns. The wait(0.1) might look a bit hacky, but sometimes Roblox spawns the character at the default spawn point so fast that the script struggles to move them instantly. That tiny delay ensures the teleport actually happens.
Dealing with the "CharacterAdded" trap
One thing that trips up a lot of people when writing a roblox checkpoint teleport script is the CharacterAdded event. You see, when a player dies, their old character is destroyed and a brand new one is created. If your script only runs when the player first joins, they'll only be teleported once.
By nesting the teleport logic inside player.CharacterAdded, you're telling the game to move them every single time they respawn. It's also important to use WaitForChild("HumanoidRootPart"). If the script tries to move the player before their body has actually finished loading, the script will error out and your player will be stuck at the beginning of the map, probably getting pretty frustrated.
Why your teleports might be breaking
If you've set everything up and it's still not working, don't panic. Scripting is 10 percent writing code and 90 percent figuring out why that code is broken. Here are a few common culprits:
- Part Names: Check your folder. Are the parts actually named "1", "2", "3"? If you named them "Checkpoint1", the
tostring(stage.Value)logic won't find them. - Anchoring: If your checkpoint parts aren't anchored, they might fall through the floor or get kicked around by players. If the part moves, the teleport location moves with it.
- Vector3 Offset: In the code above, I added
Vector3.new(0, 3, 0)to the CFrame. This spawns the player slightly above the part. Without this, they might get stuck inside the floor or glitch through the checkpoint.
Taking it a step further: Saving progress
The script I showed you works great for a single session. But what happens when a player leaves and comes back the next day? Usually, they'll be back at Stage 1. If your obby is long, you'll want to look into DataStoreService.
Integrating a DataStore with your roblox checkpoint teleport script is basically just saving that "Stage" value to the Roblox cloud. When the player joins, instead of setting the Stage to 1 by default, you ask the DataStore, "Hey, what was this guy's last level?" and set the value to that instead. It makes the game feel much more professional and keeps people coming back to finish the levels they haven't beaten yet.
Making it look "pro"
Once the functional part is done, you can start having some fun. Why just have a boring teleport? You could add a sound effect when the player touches a checkpoint. Maybe throw in some confetti particles using ParticleEmitter.
You could even change the color of the checkpoint part once the player has reached it. To do that, you'd just add a line inside the .Touched function that changes the checkpoint.Color or checkpoint.Material. Small visual cues like that go a long way in making your game feel polished and satisfying to play.
Wrapping it up
Building a roblox checkpoint teleport script is basically a rite of passage for Roblox developers. It's the first real "system" most people build. It combines physical parts in the 3D world with logic in the script, and it directly affects the player's experience.
Don't be afraid to experiment with the code. Try changing how the teleport works, or try adding "Kill Bricks" that work alongside the checkpoints. The more you mess with it, the more you'll understand how the character physics and server-client relationship work in Roblox. Keep at it, and before you know it, you'll be building much more complex systems than just moving a player from point A to point B!