How to wait until or repeat searching for a Character to respawn?

So, I have found this really irritating bug that that stops my teleport script from working how it should, I believe I know what would fix it but i’m not sure how to approach it… Here’s the function:

--[ loops through all players in the game, gets their character and teleports them to the spawnpad on the map... ]--
--[ ISSUE: when the player dies before this function runs, it doesn't teleport as the script wasn't able to find their character (since they're dead) ]--

function TeleportPlayers(spawnPad)
	for _, plr in pairs(Players:GetChildren()) do
		local character = plr.Character or plr.CharacterAdded:Wait()
		
		if character and character.Parent then
			character:PivotTo(spawnPad.CFrame * CFrame.new(0, 5, 0))
			print("teleporting "..plr.Name.." to map")
		else
			warn("could not find "..plr.Name.." character")
		end
	end
end

ISSUE:

The issue is as i described in the comment of the code… i just need a way to repeat searching for the Players new Character to then assign the variable to and teleport them.

EXTRA:

I’ve been scavenging the internet for like 4 hours just hoping someone had found a solution but unfortunately not…

Any help is greatly appreciated, thank you! :slight_smile:

Try this code:

function TeleportPlayers(spawnPad)
	for _, plr in pairs(Players:GetPlayers()) do
		local character = plr.Character or plr.CharacterAdded:Wait()
		
		if character and character.Parent then
			character:PivotTo(spawnPad.CFrame + CFrame.new(0, 5, 0))
			print("teleporting "..plr.Name.." to map")
		else
			repeat wait() until plr.Character -- This will wait() until plr.Character is found
		end
	end
end

2 things i noticed the first thing is that this might be intentional or i just dont fully understand the script but at line 9 yout multiplying the new spawn pads position by 0,5,0 this could pose a problem because 0 x anything is 0 that would eliminate the x and y cords and leave the y cord(up and down) second thing there is a function not sure if this is what you need but it might provide a lead Its called character appearance loaded there is also character loaded

Hope this helps if this doesent help let me know bc i might have more ideas

Ps sorry for typos im on mobile and sorry for grammar and punctuation stuff im dislexic :stuck_out_tongue:

the PivotTo(____ * CFrame.new(0, 5, 0)) is just teleporting the player +5 studs above the SpawnPad to stop any weird bugs with the Character, I’ll try out that AppearanceLoaded function and let you know!

I think he was just recommending to not multiply. If you want to move the player upwards by 5 studs, just add the CFrame instead. PivotTo(____ + CFrame.new(0, 5, 0))

1 Like

You can only add Vector3 & Position values together, CFrames have to be multiplied together or else they return a syntax error!

Nevermind, sorry :man_facepalming:. But do try or plr.CharacterAppearanceLoaded:Wait() when defining the character. I think that might work.

I tried this out and unfortunately it doesn’t work, honestly it made a lot of sense to use a repeat loop but nothing changed, when the Player dies before teleporting it respawns them in the default spawn rather than on the map…

Maybe this? I think it should yield and wait until the character is found.

function TeleportPlayers(spawnPad)
	for _, plr in pairs(Players:GetPlayers()) do
		local character = plr.Character or plr.CharacterAdded:Wait()

		if not plr.Character then repeat wait() until plr.Character

		if character and character.Parent then
			character:PivotTo(spawnPad.CFrame + CFrame.new(0, 5, 0))
			print("teleporting "..plr.Name.." to map")
		end
	end
end

Try teleporting the characters after they respon like maybe there is somthing like character respon im just taking guesses ill do some diging

Found something! Woulf player.respawnlocation work! If you change the respon location every time the player dies! If your trying to make it respawn at a random spawn location you could do somthing like check the humanoids health every time its changed then if its 0 set the respawn location to a random 1 across the game this would be done across the server you also would have to set it random when the player joins this would spawn the player at the original spawn location then immediately set its new spawn location to a new place when the player dies it will respawn it a said respawn location and then pick a new random respawn location…
Check the properties of the respawn pad and see if there is somthing like spawn here on default anf de check that

Sorry if that was realy long or didnt help

:sparkles: SOLUTION

I was just messing around with repeat loops and managed to make it work like this:

function TeleportPlayers(spawnPad)
	for _, plr in pairs(Players:GetPlayers()) do
		local humanoidRootPart = plr.Character:WaitForChild("HumanoidRootPart", 1)
		
		if humanoidRootPart then
			print("found rootpart, player is alive")
			local character = plr.Character or plr.CharacterAdded:Wait()
			
			if character and character.Parent then
				character:PivotTo(spawnPad.CFrame * CFrame.new(0, 5, 0))
				print("teleporting "..plr.Name.." to map")
			end
		else
			repeat
				print("waiting for player to respawn")
				wait(0.25)
			until plr.Character:FindFirstChild("HumanoidRootPart")
			
			plr.Character:PivotTo(spawnPad.CFrame * CFrame.new(0, 5, 0))
			print("teleporting "..plr.Name.." to map")
		end
	end
end

thanks for the code suggestions and ideas! @J_Angry @ElipsGames

Glad to hear it works!! Good luck on your future endeavors!

1 Like

I would not recommend polling (repeatedly waiting and checking in a loop) when you can use events. I would suggest the following code as an alternative solution (I haven’t tested whether it works, though). Some checks in isCharacterAlright may be unnecessary, you could remove some if you want and only keep the ones you think are needed.

Your current code may give errors which is another thing I would recommend you to avoid. If plr.Character is nil when TeleportPlayers is called (which is the case if the player has just joined), your code will give an error ‘Attempt to index nil with WaitForChild’. I’m also not sure if your code will actually always work even in cases where it doesn’t throw an error. I mean, the HumanoidRootPart’s existence doesn’t tell whether the Humanoid is alive.

As you can see, I added some code for preventing memory leaks. Storing the connection also allows disconnecting it if it’s possible that something changes such that teleporting to the map should no longer be allowed. In such a case, you could just disconnect the connection.

local Players = game:GetService("Players")

-- The purpose of this is to store connections so that they can be disconnected when the player leaves.
local characterAddedConns = {}

local function teleportCharacter(character, spawnPad)
	character:PivotTo(spawnPad.CFrame * CFrame.new(0, 5, 0))
	print("teleporting "..character.Name.." to map")
end

local function isCharacterAlright(character)
	if character == nil then
		return false
	end
	if character.Parent == nil then
		return false
	end
	if character:FindFirstChild("HumanoidRootPart") == nil then
		return false
	end
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid == nil then
		return false
	end
	if humanoid.Health == 0 then
		return false
	end
	return true
end

function TeleportPlayers(spawnPad)
	for _, plr in pairs(Players:GetChildren()) do
		local currentCharacter = plr.Character
		print(isCharacterAlright(currentCharacter))
		if not isCharacterAlright(currentCharacter) then
			warn(plr.Name.." character cannot be teleported at the moment.")
			-- Using :Once instead of :Connect causes the connection to be disconnected when CharacterAdded fires next time.
			-- Without it, the connection would have to be disconnected in the connected function when it's only needed once.
			characterAddedConns[plr] = plr.CharacterAdded:Once(function(newCharacter)
				teleportCharacter(newCharacter, spawnPad)
			end)
		else
			teleportCharacter(currentCharacter, spawnPad)
		end
	end
end

local function onPlayerRemoving(plr)
	-- These lines of code are for preventing memory leaks caused by connections that are no longer needed.
	-- Disconnecting here is only needed if the player leaves before respawning. If the player leaves
	-- while their character is alive, the connection has already been disconnected, but calling :Disconnect again
	-- doesn't cause any problems. Removing the connection from the table is necessary regardless of whether the character
	-- is alive when the player leaves.
	if characterAddedConns[plr] ~= nil then
		characterAddedConns[plr]:Disconnect()
		characterAddedConns[plr] = nil
	end
end

Players.PlayerRemoving:Connect(onPlayerRemoving)
1 Like

amazing, this all seems to work just the same and is evidently much more secure than my previous approach, thank you!