BLOXBUILDS
Discord
Back
OBBY

Checkpoint System

Paste into ServerScriptService as a Script. Name checkpoint parts Checkpoint and set a number attribute called Stage. Touching a higher stage saves it and sends the player back there on respawn.

-- Paste into ServerScriptService as a Script.
-- Name checkpoint parts "Checkpoint" and set a number attribute called Stage.

local Players = game:GetService("Players")

local function getStage(player: Player): IntValue
	local leaderstats = player:FindFirstChild("leaderstats")
	if not leaderstats then
		leaderstats = Instance.new("Folder")
		leaderstats.Name = "leaderstats"
		leaderstats.Parent = player
	end

	local stage = leaderstats:FindFirstChild("Stage")
	if not stage then
		stage = Instance.new("IntValue")
		stage.Name = "Stage"
		stage.Value = 0
		stage.Parent = leaderstats
	end

	return stage :: IntValue
end

local function findCheckpoint(stageNumber: number): BasePart?
	for _, inst in ipairs(workspace:GetDescendants()) do
		if inst:IsA("BasePart") and inst.Name == "Checkpoint" and inst:GetAttribute("Stage") == stageNumber then
			return inst
		end
	end
	return nil
end

local function teleportToStage(player: Player, character: Model)
	local stageNumber = getStage(player).Value
	local checkpoint = findCheckpoint(stageNumber)
	if not checkpoint then
		return
	end

	local root = character:WaitForChild("HumanoidRootPart")
	task.defer(function()
		root.CFrame = checkpoint.CFrame + Vector3.new(0, 4, 0)
	end)
end

local function hookPlayer(player: Player)
	player.CharacterAdded:Connect(function(character)
		teleportToStage(player, character)
	end)
end

for _, inst in ipairs(workspace:GetDescendants()) do
	if inst:IsA("BasePart") and inst.Name == "Checkpoint" then
		inst.Touched:Connect(function(hit)
			local player = Players:GetPlayerFromCharacter(hit.Parent)
			if not player then
				return
			end

			local stageNumber = inst:GetAttribute("Stage")
			if typeof(stageNumber) ~= "number" then
				return
			end

			local stage = getStage(player)
			if stageNumber <= stage.Value then
				return
			end

			stage.Value = stageNumber
			local character = player.Character
			if character then
				teleportToStage(player, character)
			end
		end)
	end
end

Players.PlayerAdded:Connect(hookPlayer)
for _, player in ipairs(Players:GetPlayers()) do
	hookPlayer(player)
end