Welcome! Today we’re going to build one of the most essential systems in any obstacle course or adventure game: a checkpoint and respawn system. This will let players save their progress as they move through your game, so when they fall or reset, they’ll respawn at the last checkpoint they reached instead of all the way back at the start.
By the end of this tutorial, you’ll understand how checkpoints work and be able to create your own system from scratch. Let’s get started!
What You’ll Need
Before we begin coding, let’s set up our workspace:
- A basic obstacle course or game with multiple stages
- Several parts that will act as checkpoints (you can use any part, but SpawnLocation parts work great)
- A ServerScriptService script to handle the checkpoint logic
Understanding How Checkpoints Work
Here’s the concept behind our checkpoint system: when a player touches a checkpoint part, we’ll save that checkpoint’s position. Then, when the player respawns (either by falling, dying, or resetting), we’ll move them to that saved position instead of the default spawn point.
The key to making this work is using something called leaderstats. While leaderstats are often used to display scores on the leaderboard, we can also use them to store which stage a player has reached. Roblox will automatically track this information for each player throughout their session.
Step 1: Creating the Checkpoint Parts
First, let’s create some checkpoint parts in your game:
- Insert several parts into your Workspace and position them throughout your game
- Name them “Checkpoint1”, “Checkpoint2”, “Checkpoint3”, etc.
- For organization, put all checkpoints in a folder called “Checkpoints” in the Workspace
- Make sure each checkpoint is set to
CanCollide = falseandTransparency = 0.5so players can walk through them
Give each checkpoint a NumberValue called “Stage” (Insert > NumberValue). Set the Value property to match the checkpoint number (1 for Checkpoint1, 2 for Checkpoint2, etc.). This will help us track which stage is which.
Step 2: Setting Up Player Data
Now let’s write a script that tracks each player’s current stage. Create a Script in ServerScriptService and add this code:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
-- Create leaderstats folder
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
-- Create Stage value
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Value = 1 -- Start at stage 1
stage.Parent = leaderstats
end)
This code runs whenever a player joins the game. We create a leaderstats folder (which Roblox recognizes and displays on the leaderboard) and add a “Stage” value to track which checkpoint the player has reached. Everyone starts at stage 1.
Step 3: Detecting Checkpoint Touches
Next, we need to detect when players touch checkpoints and update their stage. Add this code to the same script:
local checkpointsFolder = game.Workspace:WaitForChild("Checkpoints")
for _, checkpoint in pairs(checkpointsFolder:GetChildren()) do
checkpoint.Touched:Connect(function(hit)
local character = hit.Parent
local player = Players:GetPlayerFromCharacter(character)
if player then
local stage = player.leaderstats:FindFirstChild("Stage")
local checkpointStage = checkpoint:FindFirstChild("Stage")
if stage and checkpointStage then
-- Only update if this checkpoint is the next stage
if checkpointStage.Value == stage.Value + 1 then
stage.Value = checkpointStage.Value
print(player.Name .. " reached stage " .. stage.Value)
end
end
end
end)
end
Let’s break down what’s happening here. We loop through all checkpoints in our Checkpoints folder. For each one, we connect to its Touched event. When something touches the checkpoint, we check if it’s a player, and if that checkpoint is the next stage they need to reach. If so, we update their Stage value.
Notice we only update if the checkpoint is exactly one stage ahead. This prevents players from skipping stages by accidentally touching later checkpoints.
Step 4: Respawning at Checkpoints
Finally, let’s make players respawn at their current checkpoint. Add this code to handle respawning:
Players.PlayerAdded:Connect(function(player)
-- (previous code for leaderstats stays here)
player.CharacterAdded:Connect(function(character)
wait(0.1) -- Small delay to ensure character loads
local stage = player.leaderstats:FindFirstChild("Stage")
if stage then
local checkpointName = "Checkpoint" .. stage.Value
local checkpoint = checkpointsFolder:FindFirstChild(checkpointName)
if checkpoint and character:FindFirstChild("HumanoidRootPart") then
character.HumanoidRootPart.CFrame = checkpoint.CFrame + Vector3.new(0, 5, 0)
end
end
end)
end)
The CharacterAdded event fires whenever a player spawns or respawns. We look up which stage they’re on, find the matching checkpoint, and move their character’s HumanoidRootPart to that position. The + Vector3.new(0, 5, 0) spawns them slightly above the checkpoint so they don’t fall through.
Testing Your System
Press Play and test your game! Walk through each checkpoint and watch your Stage number increase on the leaderboard. Press your character’s reset button (or fall off the map if you have a kill brick), and you should respawn at your last checkpoint!
Recap and Next Steps
Congratulations! You’ve built a working checkpoint system. You learned how to use leaderstats to track player progress, detect touches on checkpoint parts, and teleport players when they respawn.
To take this further, consider adding visual feedback when players reach a checkpoint (like a sound effect or particle effect), or save checkpoint progress with DataStores so players keep their progress between sessions. Happy scripting!