Code issues - Checkpoint Platform Area Respawn Bug

Hello! I’d like to make it so that when my player touches the checkpoint named platformArea, the player’s position is saved, and they respawn at the platformArea (reappear at the position of the platformArea). How can I achieve that?

local respawnPositions = {}

-- Function to save the last position of the player when they touch the platformArea
local function saveLastPlayerPosition(hit)
	-- Check if the object that touched the part is a character (player)
	local character = hit.Parent:FindFirstChildOfClass("Humanoid")
	if character and game.Players:GetPlayerFromCharacter(hit.Parent) then
		-- Get the player
		local player = game.Players:GetPlayerFromCharacter(hit.Parent)

		-- Save the player's last position as the position of the platformArea
		respawnPositions[player] = platformArea.Position
	end
end

-- Function to handle respawning the player
local function respawnPlayer(player)
	-- Check if there's a valid respawn position for the player
	if respawnPositions[player] then
		-- Move player to platformArea position
		player.Character:SetPrimaryPartCFrame(CFrame.new(respawnPositions[player]))
	end
end

-- Connect the function to the Touched event of the checkpoint
platformArea.Touched:Connect(function(hit)
	if debounce then
		return -- If an event is already in progress, exit the function
	end
	debounce = true -- Mark that an event is in progress

	print("Part touched")

	-- Call the function to save the last position of the player
	saveLastPlayerPosition(hit)

	-- Change the colors of checkpoint parts when touched
	changeColors(checkpointParts, colorsToChange)

	-- Check if the object that touched the part is a character (player)
	local character = hit.Parent:FindFirstChildOfClass("Humanoid")
	if character and game.Players:GetPlayerFromCharacter(hit.Parent) then
		print("Player character found")
		-- Call the coroutine functions with the player and the animation/sound parameters
		spawn(function()
			playAnimationFromHumanoid(character, animationId, 3) -- Duration of 3 seconds
		end)
		spawn(function()
			playSound(soundId, 3) -- Duration of 3 seconds
		end)
		spawn(function()
			enableVFXForDuration(arcsVFX, 3) -- Duration of 3 seconds
		end)
	else
		print("Not a player character")
	end

	wait(2) -- Wait for a moment to prevent the event from firing multiple times quickly
	debounce = false -- Reset the event in progress indicator to allow it to fire again
end)

To achieve this, i modified your current script

local platformArea = script.Parent  -- Assuming platformArea is the part that the player touches
local debounce = false
local respawnPositions = {}

-- Function to save the last position of the player when they touch the platformArea
local function saveLastPlayerPosition(hit)
    -- Check if the object that touched the part is a character (player)
    local character = hit.Parent:FindFirstChildOfClass("Humanoid")
    if character and game.Players:GetPlayerFromCharacter(hit.Parent) then
        -- Get the player
        local player = game.Players:GetPlayerFromCharacter(hit.Parent)

        -- Save the player's last position as the position of the platformArea
        respawnPositions[player] = platformArea.Position
    end
end

-- Function to handle respawning the player
local function respawnPlayer(player)
    -- Check if there's a valid respawn position for the player
    if respawnPositions[player] then
        -- Move player to platformArea position
        local humanoid = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
        if humanoid then
            humanoid.Health = 0  -- Kills the player to force respawn
            wait(1)  -- Wait for a short moment before respawning
            player:LoadCharacter()  -- Respawn the player
            player.Character:SetPrimaryPartCFrame(CFrame.new(respawnPositions[player]))  -- Teleport to saved position
        end
    end
end

-- Connect the function to the Touched event of the checkpoint
platformArea.Touched:Connect(function(hit)
    if debounce then
        return  -- If an event is already in progress, exit the function
    end
    debounce = true  -- Mark that an event is in progress

    print("Part touched")

    -- Call the function to save the last position of the player
    saveLastPlayerPosition(hit)

    -- Check if the object that touched the part is a character (player)
    local character = hit.Parent:FindFirstChildOfClass("Humanoid")
    if character and game.Players:GetPlayerFromCharacter(hit.Parent) then
        print("Player character found")
        -- Call the coroutine functions with the player and the animation/sound parameters
        spawn(function()
            -- Call your animation function here if needed
        end)
        spawn(function()
            -- Call your sound function here if needed
        end)
        spawn(function()
            -- Call your VFX function here if needed
        end)
    else
        print("Not a player character")
    end

    wait(2)  -- Wait for a moment to prevent the event from firing multiple times quickly
    debounce = false  -- Reset the event in progress indicator to allow it to fire again
end)

-- Listen for player respawn and teleport them to the checkpoint
game.Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        wait(1)  -- Wait for a short moment to ensure character is fully loaded
        respawnPlayer(player)
    end)
end)

Explanation
Respawning Logic : When a player touches the checkpoint, their position is saved. Upon respawning, the script checks if there’s a saved position for the player and teleports them to that position.

Handling Respawn : We listen for the PlayerAdded event to determine when a new player joins the game. When a player’s character is added, we wait for a short moment to ensure the character is fully loaded, then teleport them to the saved position.

Debouncing : A debounce variable is used to prevent the script from firing multiple times rapidly, which could cause unexpected behavior or lag.

This script should handle respawning players at the platformArea checkpoint upon touching it. Adjust it as you want to fit your needs.

There’s a bug; the player keeps dying repeatedly.

here is the full code:

-- Coroutine function to enable/disable visual effects (VFX) for a specified duration
local function enableVFXForDuration(arcsVFX, duration)
	if arcsVFX then
		arcsVFX.Enabled = true
		wait(duration)
		arcsVFX.Enabled = false
	else
		warn("ArcsVFX not found!")
	end
end

-- Function to change the colors of checkpoint parts
local function changeColors(checkpointParts, partColors)
	for i, part in ipairs(checkpointParts) do
		part.Color = partColors[i]
	end
end

-- Coroutine function to play animation from a humanoid for a specified duration
local function playAnimationFromHumanoid(humanoid, animationId, duration)
	if animationId then
		local animationTrack = Instance.new("Animation")
		animationTrack.AnimationId = animationId
		local animation = humanoid:LoadAnimation(animationTrack)
		if animation then
			animation:Play()
			wait(duration)
			animation:Stop()
		else
			warn("Failed to load animation - sanitized ID:", animationId)
		end
	else
		warn("Animation ID not provided.")
	end
end

-- Coroutine function to play a sound for a specified duration
local function playSound(soundId, duration)
	if soundId then
		local sound = Instance.new("Sound")
		sound.SoundId = soundId
		sound.Parent = game.Workspace
		sound:Play()
		wait(duration)
		sound:Destroy()
	else
		warn("Sound ID not provided.")
	end
end

-- Define specific checkpoint objects here
local platform = script.Parent
local platformArea = platform.platformArea
local arcsVFX = script.Parent:FindFirstChild("B - Arcs v1 [C]").Middle.Arcs
local checkpointParts = {
	platform.Arrow,
	platform.Part1,
	platform.Part2,
	platform.Part3
}
local colorsToChange = {
	Color3.fromRGB(0, 255, 0),
	Color3.fromRGB(0, 255, 0),
	Color3.fromRGB(255, 255, 255),
	Color3.fromRGB(255, 255, 255)
}
local defaultColor = {
	Color3.fromRGB(196, 40, 28),
	Color3.fromRGB(248, 248, 248),
	Color3.fromRGB(196, 40, 28),
	Color3.fromRGB(248, 248, 248)
}

-- Variable to track if the event is already being processed
local debounce = false

local animationId = "rbxassetid://507771019"
local soundId = "rbxassetid://1843468464"

local respawnPositions = {}

-- Function to save the last position of the player when they touch the platformArea
local function saveLastPlayerPosition(hit)
	-- Check if the object that touched the part is a character (player)
	local character = hit.Parent:FindFirstChildOfClass("Humanoid")
	if character and game.Players:GetPlayerFromCharacter(hit.Parent) then
		-- Get the player
		local player = game.Players:GetPlayerFromCharacter(hit.Parent)

		-- Save the player's last position as the position of the platformArea
		respawnPositions[player] = platformArea.Position
	end
end

-- Function to handle respawning the player
local function respawnPlayer(player)
	-- Check if there's a valid respawn position for the player
	if respawnPositions[player] then
		-- Move player to platformArea position
		local humanoid = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
		if humanoid then
			humanoid.Health = 0  -- Kills the player to force respawn
			wait(1)  -- Wait for a short moment before respawning
			player:LoadCharacter()  -- Respawn the player
			player.Character:SetPrimaryPartCFrame(CFrame.new(respawnPositions[player]))  -- Teleport to saved position
		end
	end
end

-- Connect the function to the Touched event of the checkpoint
platformArea.Touched:Connect(function(hit)
	if debounce then
		return -- If an event is already in progress, exit the function
	end
	debounce = true -- Mark that an event is in progress

	print("Part touched")

	-- Call the function to save the last position of the player
	saveLastPlayerPosition(hit)

	-- Change the colors of checkpoint parts when touched
	changeColors(checkpointParts, colorsToChange)

	-- Check if the object that touched the part is a character (player)
	local character = hit.Parent:FindFirstChildOfClass("Humanoid")
	if character and game.Players:GetPlayerFromCharacter(hit.Parent) then
		print("Player character found")
		-- Call the coroutine functions with the player and the animation/sound parameters
		spawn(function()
			playAnimationFromHumanoid(character, animationId, 3) -- Duration of 3 seconds
		end)
		spawn(function()
			playSound(soundId, 3) -- Duration of 3 seconds
		end)
		spawn(function()
			enableVFXForDuration(arcsVFX, 3) -- Duration of 3 seconds
		end)
	else
		print("Not a player character")
	end

	wait(2) -- Wait for a moment to prevent the event from firing multiple times quickly
end)

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		wait(1)  -- Wait for a short moment to ensure character is fully loaded
		respawnPlayer(player)
	end)
end)

-- Connect the function to the TouchEnded event of the checkpoint
platformArea.TouchEnded:Connect(function()
	-- Reset the default colors when the checkpoint touch ends
	--changeColors(checkpointParts, defaultColor)

	-- Disable the VFX if it's currently active
	if arcsVFX then
		arcsVFX.Enabled = false
	end
end)

here. I tried to fix it.

-- Your existing code down here (too lazy to import it myself)

-- Connect the function to the TouchEnded event of the checkpoint
platformArea.TouchEnded:Connect(function()
	-- Reset the default colors when the checkpoint touch ends
	--changeColors(checkpointParts, defaultColor)

	-- Disable the VFX if it's currently active
	if arcsVFX then
		arcsVFX.Enabled = false
	end
	
	-- Reset the debounce variable to allow the event to trigger again
	debounce = false
end)

1 Like

Thank you very much for your help, my issue has been resolved! :smiley:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.