Checkpoint system does not spawn players at their appropriate point until they die

Hello! I’m working on an obby game and I’m trying to figure out what the problem is with the MainModule of the checkpoint system. When you spawn into the game, you spawn at the very start of the obby.

If you reset character/die, then the script will work as intended and send you to the correct checkpoint.

Here’s the script:

local module = {}

--Adding and loading data

-- variables
local folder = workspace:WaitForChild("CheckpointsFolder")
local prts = {}


for _,x in pairs(folder:GetChildren())do
	if x:IsA("BasePart") then
		table.insert(prts, x)
	end
end

print("load")


local players = game:GetService("Players")
local dataStore = game:GetService("DataStoreService")
local myData = dataStore:GetDataStore("^%%58765^%$5")


for _,x in pairs(players:GetChildren())do
	local learderstats = Instance.new("Folder", x)
	learderstats.Name = "leaderstats"
	local level = Instance.new("IntValue", learderstats)
	level.Name = "Level"

	local d

	local s,e = pcall(function()
		d = myData:GetAsync(x.UserId)
	end)

	if s then
		level.Value = d
	else
		warn(e)
	end

	local char = x.Character or x.CharacterAdded:Wait()
	print("Character added")
	print("lala")

	for _,c in pairs(prts)do

		if c.Name == tostring(level.Value) then
			print('a')
			wait(.1)
			local leftFoot = char:FindFirstChild("HumanoidRootPart")
			print(leftFoot)
			leftFoot.CFrame = c.CFrame * CFrame.new(0,10,0)
		end
	end


	x.CharacterAdded:Connect(function(char1)
		print("Character added")
		print("lala")

		for _,c in pairs(prts)do

			if c.Name == tostring(level.Value) then
				print('a')
				wait(.1)
				local leftFoot = char1:FindFirstChild("HumanoidRootPart")
				print(leftFoot)
				leftFoot.CFrame = c.CFrame * CFrame.new(0,10,0)
			end
		end
	end)

end

players.PlayerAdded:Connect(function(plr)
	local learderstats = Instance.new("Folder", plr)
	learderstats.Name = "leaderstats"
	local level = Instance.new("IntValue", learderstats)
	level.Name = "Level"

	local d

	local s,e = pcall(function()
		d = myData:GetAsync(plr.UserId)
	end)

	if s then
		level.Value = d
	else
		warn(e)
	end

	plr.CharacterAdded:Connect(function(char)
		print("Character added")
		print("lala")
		for _,c in pairs(prts)do

			if c.Name == tostring(level.Value) then
				print('a')
				wait(.1)
				local leftFoot = char:FindFirstChild("HumanoidRootPart")
				print(leftFoot)
				leftFoot.CFrame = c.CFrame * CFrame.new(0,10,0)
			end
		end
	end)
end)

players.PlayerRemoving:Connect(function(plr)
	local l = plr:WaitForChild("leaderstats")
	local lvl = l:WaitForChild("Level")
	local lvlVal = lvl.Value
	local plrID = plr.UserId

	local s,e = pcall(function()
		myData:SetAsync(plrID, lvlVal)
	end)

	if s then
		warn(plr.Name .. "'s level data was saved to " .. tostring(lvlVal))
	else
		warn(e)
	end
end)


for c = 1,#prts do
	prts[c].Touched:Connect(function(Hit)
		if Hit.Parent:FindFirstChildWhichIsA("Humanoid") then
			local char = Hit.Parent
			local plr = players:GetPlayerFromCharacter(char)
			local lead = plr:WaitForChild("leaderstats")
			local lvl = lead:WaitForChild("Level")
			local lvlVal = lvl.Value
			local partVal = tonumber(prts[c].Name)
			if partVal > lvlVal then
				lvl.Value = partVal
			end
		end

	end)
end

return module

Thanks!

So what exactly is your problem then?

I think he wants it to save your last checkpoint when you leave the game. Then, when you return, you spawn at the last checkpoint, not at the beginning.

Sorry I wasn’t clear.

The datastore works but, when you join the game, it spawns you at the beginning until you reset character. Example:

  1. You join the game
  2. You make go to stage 5
  3. You leave
  4. You rejoin
  5. You spawn at stage 0
  6. You Reset Character/Die
  7. You get respawned at stage 5

Does that make sense?

2 Likes

When a player joins your game, add something like wait(Number like 2 or 3) before teleporting them.

4 Likes

Thank you for your responce!
I’m a bit new to scripting and, I don’t know how I would do that. Can I get some help?

Or, while the player is on the loading screen, is it possible to make them reset character? That would fix it.

Anytime! To respawn a player, you can use LoadCharacter instead of reseting them.

If you want the script to wait for a seconds before teleporting a player, there’s something called wait(). Here is an exampe on how to use it:

wait(5)
print("I'm a cool scripter!")

This script will print “I’m a cool scripter!” after 5 seconds!

1 Like

Wow! I had no clue the solution was that simple.

I had tried adding a wait timer before but I forgot to change the loader script aswell.
Thank you so much for your time! You’re a legend

1 Like

Update:
The script works in Roblox Studio but, it still does not work as expected in-game

Are you getting errors? If yes, could you please send a screenshot?

There are no errors :confused:

The reason the wait() solution doesn’t work is because you can’t really rely on wait() for loading things, as loading things doesn’t have a consistent timer and wait() itself isn’t supposed to be used for loading. Instead, you should use :WaitForChild(char) so it gets the character as soon as it loads.

Let me know how this goes. :slight_smile:

I’m probably missing something very obvious here but, here’s the output

Model.MainModule:1: Expected identifier when parsing expression, got '1'
Requested module received an error while loading.

The second error is for the loader script which is this:

require(6971084595)

The reason the loader script is erroring is because of the MainModule.

Let me know if any of that didn’t make sense :slight_smile:

By the way, the script is currently in use in my game [BETA] Mirror Obby - Roblox incase you wanted to experiment around with it.

I wrote this on mobile so there might be some typos.

 local module = {}

--Adding and loading data

-- variables
local folder = workspace:WaitForChild("CheckpointsFolder")
local prts = {}


for _,x in pairs(folder:GetChildren())do
    if x:IsA("BasePart") then
        table.insert(prts, x)
    end
end

print("load")


local Players = game:GetService("Players")
local dataStore = game:GetService("DataStoreService")
local myData = dataStore:GetDataStore("^%%58765^%$5")

function newPlayer(Player)
    local leaderstats = Instance.new("Folder",Player)
    leaderstats.Name = "leaderstats"
    local level = Instance.new("IntValue",leaderstats)
    level.Name = "Level"
    
    local function newCharacter(Character)
        print("Character Detected")
        local PlayerLevel = tostring(level.Value)
        
        for _, c in ipairs(prts) do
            if c.Name == PlayerLevel then
                wait(.1)
                local HRP = Character:WaitForChild("HumanoidRootPart")
                HRP.CFrame = c.CFrame * CFrame.new(0,10,0)
            end
        end
    end
    
    local d
    local s, e = pcall(function()
        d = myData:GetAsync(Player.UserId)
    end)
    if s then
      level.Value = d  
    else
        warn(e)
    end
    
    local Character = Player.Character or Player.CharacterAdded:Wait()
    
    if Character then
        newCharacter(Character)
    end
    Player.CharacterAdded:Connect(newCharacter)
end

for _, Player in pairs(Players:GetPlayers()) do
    coroutine.wrap(function()
        newPlayer(Player)
    end)()
end
Players.PlayerAdded:Connect(newPlayer)

Players.PlayerRemoving:Connect(function(plr)
    local l = plr:WaitForChild("leaderstats")
    local lvl = l:WaitForChild("Level")
    local lvlVal = lvl.Value
    local plrID = plr.UserId

    local s,e = pcall(function()
        myData:SetAsync(plrID, lvlVal)
    end)

    if s then
        warn(plr.Name .. "'s level data was saved to " .. tostring(lvlVal))
    else
        warn(e)
    end
end)


for c = 1,#prts do
    prts[c].Touched:Connect(function(Hit)
        if Hit.Parent:FindFirstChildWhichIsA("Humanoid") then
            local char = Hit.Parent
            local plr = Players:GetPlayerFromCharacter(char)
            local lead = plr:WaitForChild("leaderstats")
            local lvl = lead:WaitForChild("Level")
            local lvlVal = lvl.Value
            local partVal = tonumber(prts[c].Name)
            if partVal > lvlVal then
                lvl.Value = partVal
            end
        end

    end)
end

return module

What’s this?

I’m curious cause, I’ve seen malicious scripts and, they usually have lines of code that look a lot like that.

I copied the code from yours. So I’m not sure myself.

nothing to worry it’s just a datastore name

if you don’t want to name it like that then you can change its name

(and yeah you’re the one who named the datastore like that)

I completely forgot xD

Sorry about that.