Modify checkpoint script to work with a part

so i have a ball in a folder, and i want that to trigger the check point, i used this tutorial:

and i modified the part where it touches to this:

for i, checkpoint in pairs(Checkpoints) do
	checkpoint.Touched:Connect(function(touch)
		-- Touched is an event that is fired when the object is touched
		local hum = touch.Parent:FindFirstChild("Plr")
		-- If a part in a model touches the part, touch = that part not the model
		if hum and touch.Parent.Name == "Boulder" then
			-- The thing that touched the checkpoint is alive
			local player = touch.Plr.Value
			-- This allows us to find a player with their character (it's very useful)
			if player then
				-- Whatever touched the checkpoint is a player
				local leaderstats = game.Players[hum]:WaitForChild("leaderstats")
				local stage = leaderstats:WaitForChild("Stage")
				-- Find the stage leader stat
				print(player)
				if (tonumber(checkpoint.Name:match("%d+"))-stage.Value) == 1 then
					-- match() finds certain parts in a string
					-- So when we do match("%d"), we're finding the numbers in a string
					-- This is the player's next checkpoint
					-- This makes it so player's can't skip checkpoints
					-- or lose progress if they accidently go backwards
					stage.Value = stage.Value + 1
				end
			end
		end
	end)
end

it dosn’t work however, any idea why?

1 Like

It appears this script makes the player’s stage count go up whem they touch the checkpoint, but it doesnt actuallly set their spawn location to the new checkpoint.

1 Like

hmm, i didnt change anything else, this is the full script btw

local StageData = game:GetService("DataStoreService"):GetDataStore("StageData")


local Checkpoints = workspace:WaitForChild("Checkpoints"):GetChildren()

function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart")
	repeat wait(0.00) until rootPart

	for i, checkpoint in pairs(Checkpoints) do
		print("Checkpoint" .. tostring(stage))
		if ("Checkpoint" .. tostring(stage)) == checkpoint.Name then
			print("Checkpoint found")
			rootPart.CFrame = checkpoint.CFrame * CFrame.new(0,1,0)
	
			break
			-- Stop looping since we found the checkpoint
		end
	end
end

game:GetService("Players").PlayerAdded:Connect(function(player)


	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

for i, checkpoint in pairs(Checkpoints) do
	checkpoint.Touched:Connect(function(touch)
		-- Touched is an event that is fired when the object is touched
		local hum = touch.Parent:FindFirstChild("Plr")
		-- If a part in a model touches the part, touch = that part not the model
		if hum and touch.Parent.Name == "Boulder" then
			-- The thing that touched the checkpoint is alive
			local player = touch.Plr.Value
			-- This allows us to find a player with their character (it's very useful)
			if player then
				-- Whatever touched the checkpoint is a player
				local leaderstats = game.Players[hum]:WaitForChild("leaderstats")
				local stage = leaderstats:WaitForChild("Stage")
				-- Find the stage leader stat
				print(player)
				if (tonumber(checkpoint.Name:match("%d+"))-stage.Value) == 1 then
					-- match() finds certain parts in a string
					-- So when we do match("%d"), we're finding the numbers in a string
					-- This is the player's next checkpoint
					-- This makes it so player's can't skip checkpoints
					-- or lose progress if they accidently go backwards
					stage.Value = stage.Value + 1
				end
			end
		end
	end)
end

game:GetService("Players").PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)
1 Like

Are there any errors or warning of any sort?

1 Like

ignore the blue its another script

2 Likes

full script might help:

local StageData = game:GetService("DataStoreService"):GetDataStore("StageData")


local Checkpoints = workspace:WaitForChild("Checkpoints"):GetChildren()

function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart")
	repeat wait(0.00) until rootPart

	for i, checkpoint in pairs(Checkpoints) do
		print("Checkpoint" .. tostring(stage))
		if ("Checkpoint" .. tostring(stage)) == checkpoint.Name then
			print("Checkpoint found")
			rootPart.CFrame = checkpoint.CFrame * CFrame.new(0,1,0)
	
			break
			-- Stop looping since we found the checkpoint
		end
	end
end

game:GetService("Players").PlayerAdded:Connect(function(player)


	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

for i, checkpoint in pairs(Checkpoints) do
	checkpoint.Touched:Connect(function(touch)
		-- Touched is an event that is fired when the object is touched
		local hum = touch.Parent:FindFirstChild("Plr")
		-- If a part in a model touches the part, touch = that part not the model
		if hum and touch.Parent.Name == "Boulder" then
			-- The thing that touched the checkpoint is alive
			local player = touch.Plr.Value
			-- This allows us to find a player with their character (it's very useful)
			if player then
				-- Whatever touched the checkpoint is a player
				local leaderstats = game.Players[hum]:WaitForChild("leaderstats")
				local stage = leaderstats:WaitForChild("Stage")
				-- Find the stage leader stat
				print(player)
				if (tonumber(checkpoint.Name:match("%d+"))-stage.Value) == 1 then
					-- match() finds certain parts in a string
					-- So when we do match("%d"), we're finding the numbers in a string
					-- This is the player's next checkpoint
					-- This makes it so player's can't skip checkpoints
					-- or lose progress if they accidently go backwards
					stage.Value = stage.Value + 1
				end
			end
		end
	end)
end

game:GetService("Players").PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)
2 Likes

You indexed leaderstats wrong here, it should be hum.Value:WaitForChild(“leaderstats”).

Fixed code:

--//Services
local Players = 	game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")

--//Variables
local StageData = DataStoreService:GetDataStore("StageData")
local Checkpoints = workspace.Checkpoints

--//Functions
local function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart", 5)
	
	if not rootPart then
		return
	end
	
	rootPart.CFrame = Checkpoints:WaitForChild("Checkpoint".. stage).CFrame * CFrame.new(0, 1, 0)
end

Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

Players.PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)

for i, checkpoint in ipairs(Checkpoints:GetChildren()) do
	checkpoint.Touched:Connect(function(touch)
		local plr = touch.Parent:FindFirstChild("Plr")
		
		if not plr or not plr.Value then
			return
		end
		
		local leaderstats = plr.Value:WaitForChild("leaderstats")
		local stage = leaderstats:WaitForChild("Stage")

		if (tonumber(checkpoint.Name:match("%d+")) - stage.Value) == 1 then
			stage.Value += 1
		end
	end)
end
2 Likes

no, i am trying to get the player’s name using the value stored inside , oddly this dosn’t work:

--//Services
local Players = 	game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")

--//Variables
local StageData = DataStoreService:GetDataStore("StageData")
local Checkpoints = workspace.Checkpoints

--//Functions
local function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart", 5)

	if not rootPart then
		return
	end

	rootPart.CFrame = Checkpoints:WaitForChild("Checkpoint".. stage).CFrame * CFrame.new(0, 1, 0)
end

Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

Players.PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)

for i, checkpoint in ipairs(Checkpoints:GetChildren()) do
	checkpoint.Touched:Connect(function(touch)
		local plr = touch.Parent:FindFirstChild("Plr")

		if not plr or not plr.Value then
			return
		end

		local leaderstats = game.Players[plr.Value]:WaitForChild("leaderstats")
		local stage = leaderstats:WaitForChild("Stage")

		if (tonumber(checkpoint.Name:match("%d+")) - stage.Value) == 1 then
			stage.Value += 1
		end
	end)
end

Tell me everything this prints after you move onto the next checkpoint:

--//Services
local Players = 	game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")

--//Variables
local StageData = DataStoreService:GetDataStore("StageData")
local Checkpoints = workspace.Checkpoints

--//Functions
local function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart", 5)

	if not rootPart then
		return
	end

	rootPart.CFrame = Checkpoints:WaitForChild("Checkpoint".. stage).CFrame * CFrame.new(0, 1, 0)
end

Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

Players.PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)

for i, checkpoint in ipairs(Checkpoints:GetChildren()) do
	checkpoint.Touched:Connect(function(touch)
		local plr = touch.Parent:FindFirstChild("Plr")

		if not plr or not plr.Value then
			return
		end

		local leaderstats = Players:WaitForChild(plr.Value):WaitForChild("leaderstats")
		local stage = leaderstats:WaitForChild("Stage")
		
		print(tonumber(checkpoint.Name:match("%d+")), stage.Value)

		if (tonumber(checkpoint.Name:match("%d+")) - stage.Value) == 1 then
			stage.Value += 1
		end
	end)
end

nothing printed, my character wasn’t spawned in the first checkpoint either

That means it couldn’t find the Plr value. Are you sure you have a value named Plr in each boulder?

100%. the boulders are in a folder, does that change anything or no

Hm, that’s weird then. Try this, maybe the checkpoints loaded in after the game started:

--//Services
local Players = 	game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")

--//Variables
local StageData = DataStoreService:GetDataStore("StageData")
local Checkpoints = workspace.Checkpoints

--//Functions
local function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart", 5)

	if not rootPart then
		return
	end

	rootPart.CFrame = Checkpoints:WaitForChild("Checkpoint".. stage).CFrame * CFrame.new(0, 1, 0)
end

local function InitializeCheckpoint(checkpoint)
	checkpoint.Touched:Connect(function(touch)
		local plr = touch.Parent:FindFirstChild("Plr")

		if not plr or not plr.Value then
			return
		end

		local leaderstats = Players:WaitForChild(plr.Value):WaitForChild("leaderstats")
		local stage = leaderstats:WaitForChild("Stage")

		print(tonumber(checkpoint.Name:match("%d+")), stage.Value)

		if (tonumber(checkpoint.Name:match("%d+")) - stage.Value) == 1 then
			stage.Value += 1
		end
	end)
end

Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

Players.PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)

Checkpoints.ChildAdded:Connect(InitializeCheckpoint)

for i, checkpoint in ipairs(Checkpoints:GetChildren()) do
	task.spawn(InitializeCheckpoint, checkpoint)
end

Yeah nothing happened there either, i decided to rework it from the oringinal script like this:

local StageData = game:GetService("DataStoreService"):GetDataStore("StageData")


local Checkpoints = workspace:WaitForChild("Checkpoints"):GetChildren()

function GoToCheckpoint(character, stage)
	local rootPart = character:WaitForChild("HumanoidRootPart")
	repeat wait(0.00) until rootPart

	for i, checkpoint in pairs(Checkpoints) do
		print("Checkpoint" .. tostring(stage))
		if ("Checkpoint" .. tostring(stage)) == checkpoint.Name then
			print("Checkpoint found")
			rootPart.CFrame = checkpoint.CFrame * CFrame.new(0,1,0)

			break
			-- Stop looping since we found the checkpoint
		end
	end
end

game:GetService("Players").PlayerAdded:Connect(function(player)


	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local stage = Instance.new("IntValue", leaderstats)
	stage.Name = "Stage"
	stage.Value = StageData:GetAsync(player.UserId) or 1
	-- Retrieve the player's data, but if there is none, start the player on stage 1

	player.CharacterAdded:Connect(function(character)
		-- The function we're connecting to this event will be called everytime the player's character spawns
		GoToCheckpoint(character, stage.Value)
	end)
end)

for i, checkpoint in pairs(Checkpoints) do
	checkpoint.Touched:Connect(function(touch)
		-- Touched is an event that is fired when the object is touched
		local hum = touch.Parent:FindFirstChild("Plr")
		-- If a part in a model touches the part, touch = that part not the model
		if hum and touch.Parent.Name == "Boulder" then
			-- The thing that touched the checkpoint is alive
		
				-- Whatever touched the checkpoint is a player
				local leaderstats = game.Players[hum.Value]:WaitForChild("leaderstats")
				local stage = leaderstats:WaitForChild("Stage")
				-- Find the stage leader stat
				print(hum.Value)
				if (tonumber(checkpoint.Name:match("%d+"))-stage.Value) == 1 then
					-- match() finds certain parts in a string
					-- So when we do match("%d"), we're finding the numbers in a string
					-- This is the player's next checkpoint
					-- This makes it so player's can't skip checkpoints
					-- or lose progress if they accidently go backwards
					stage.Value = stage.Value + 1
				
			end
		end
	end)
end

game:GetService("Players").PlayerRemoving:Connect(function(player)
	StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
	-- Saves the player's data when they leave the game
end)

it only finds the first checkpoint and prints, but the boulder dosn’t trigger it