Checkpoint not teleporting player?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve?
    I want to make a simple checkpoint system.

  2. What is the issue?
    The script is NOT teleporting the player on spawn.

  3. What solutions have you tried so far?
    I tried adding prints as you can see in the script and they print, despite the character not teleporting. I’ve tried changing “Character:MoveTo” to: “:SetPrimaryPartCFrame” and “Character.HumanoidRootPart.CFrame = StoredCheckpoint.Value”.

local Checkpoints = workspace:WaitForChild("CheckPoints"):GetChildren()
local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(Player)
	local StoredCheckpoint = Instance.new("Vector3Value", Player)
	StoredCheckpoint.Name = "CheckPoint"
	
	Player.CharacterAdded:Connect(function(Character)
		if StoredCheckpoint.Value ~= nil then
			print("checkpoint exists")
			Character:MoveTo(StoredCheckpoint.Value)
			print("teleported")
		end
	end)
	
end)

local function BindCheckPoint(checkpoint)
	checkpoint.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") ~= nil then
			local Player = Players:GetPlayerFromCharacter(hit.Parent)
			if Player.CheckPoint.Value ~= checkpoint.Position+Vector3.new(0,3,0) then
				Player.CheckPoint.Value = checkpoint.Position+Vector3.new(0,3,0)
				checkpoint.Particle:Emit(50)
				checkpoint.Sound:Play()
			end
		end
	end)
end

for i, v in pairs(Checkpoints) do
	BindCheckPoint(v)
end

The issue is that when the player spawns, their character may not have fully loaded, and therefore the MoveTo() function may not work correctly. To fix this, you can wait for the character’s HumanoidRootPart to be loaded and then teleport the player to the stored checkpoint. Here’s the modified script:

local Checkpoints = workspace:WaitForChild("CheckPoints"):GetChildren()
local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(Player)
    local StoredCheckpoint = Instance.new("Vector3Value", Player)
    StoredCheckpoint.Name = "CheckPoint"
    
    Player.CharacterAdded:Connect(function(Character)
        local humanoidRootPart = Character:WaitForChild("HumanoidRootPart")
        
        if StoredCheckpoint.Value ~= Vector3.new(0, 0, 0) then
            print("checkpoint exists")
            humanoidRootPart.CFrame = CFrame.new(StoredCheckpoint.Value)
            print("teleported")
        end
    end)
    
end)

local function BindCheckPoint(checkpoint)
    checkpoint.Touched:Connect(function(hit)
        if hit.Parent:FindFirstChild("Humanoid") ~= nil then
            local Player = Players:GetPlayerFromCharacter(hit.Parent)
            if Player.CheckPoint.Value ~= checkpoint.Position + Vector3.new(0, 3, 0) then
                Player.CheckPoint.Value = checkpoint.Position + Vector3.new(0, 3, 0)
                checkpoint.Particle:Emit(50)
                checkpoint.Sound:Play()
            end
        end
    end)
end

for i, v in pairs(Checkpoints) do
    BindCheckPoint(v)
end

In this modified script, the line local humanoidRootPart = Character:WaitForChild("HumanoidRootPart") waits for the HumanoidRootPart to be loaded before teleporting the player. Also, I changed the line Character:MoveTo(StoredCheckpoint.Value) to humanoidRootPart.CFrame = CFrame.new(StoredCheckpoint.Value) to teleport the player using their HumanoidRootPart CFrame. This should resolve the issue with the character not teleporting on spawn.

It’s still not teleporting the player after they spawn. Although it was a good tip to wait for the root part before teleporting. I actually have no clue why this isn’t working.

Is it printing that the checkpoint exists and that they got teleported?

Not sure if this would help, but your CheckPoint object is never parented to the player. You might want to add this line:

StoredCheckpoint.Parent = Player

This will fix your problem:

    Player.CharacterAdded:Connect(function(Character)
        repeat task.wait() until Character.Parent

        local humanoidRootPart = Character:WaitForChild("HumanoidRootPart")
        
        if StoredCheckpoint.Value ~= Vector3.new(0, 0, 0) then
            print("checkpoint exists")
            humanoidRootPart.CFrame = CFrame.new(StoredCheckpoint.Value)
            print("teleported")
        end
    end)

This line above creates the value and also parents it to the Player.

It is parented to their player.

local StoredCheckpoint = Instance.new("Vector3Value", Player)

It’s what the , Player is for.

I’m confused as to why we’re bothering to verify whether the value is nil or not equal to another value. Instead, we could establish a default spawn position equal to that value, which would obviate the need for an if statement to check it.

Although you haven’t replied yet, please inform me if the print statement below is being executed. If not, it suggests that there might be an issue with the if statement that compares the values.

Yes, it was, although I’ve resolved the issue now. All I did was make it wait for the root part and then wait before teleporting. Thanks for the response.

Sorry to bump this 3 months later but I’m currently having trouble with a similar issue and I was wondering if you can show what you did exactly to make it work?

I’m pretty sure that I made used :WaitForChild() to get the root part. Then I remember adding “task.wait(0.1)” before setting the part’s position.