GetCharacter function yields forever

I made a custom chunk loader that worked before in a separate place. However when I integrated the code into the rest of my game it suddenly breaks. As soon as the player connects the character is deleted for a loading menu. The function GetCharacter waits for a character to be added when the player spawns in before continuing. However after the 2nd time the while do loop at the end runs suddenly the whole script yields because it is waiting for a character to be added even though the character already exists which should’ve completely bypassed the if statement.

local function GetCharacter()
	local Character = Player.Character
	if not Character or not Character.Parent then
	    Character = Player.CharacterAdded:wait() --point of failure
	end
	return Character
end
local function UpdateChunks()
	local Character = GetCharacter()
	local CurrentPosition = AssignPartChunk(Character.Head) --deleted rest of function as not needed
end
local LastPosition = Vector3.new(0, 0, 0)
local LastCurrentXChunk = 0
local LastCurrentZChunk = 0
local ChunkUpdateDebounce = false
spawn(function()
	while wait(0.1) do --loop
		if ChunkUpdateDebounce == false then
			local Character = GetCharacter()
			if Character.Humanoid.Health > 0 and Character:FindFirstChild("Head") then
				if (Character.Head.Position - LastPosition).magnitude >= ChunkConfig.ChunkUpdateDistance then
					local CurrentPosition = AssignPartChunk(Character.Head)
					local CurrentXChunk = CurrentPosition.X
					local CurrentZChunk = CurrentPosition.Y
					if LastCurrentXChunk ~= CurrentXChunk or LastCurrentZChunk ~= CurrentZChunk then
						ChunkUpdateDebounce = true
						UpdateChunks()
						LastPosition = Character.Head.Position
						LastCurrentXChunk = CurrentXChunk
						LastCurrentZChunk = CurrentZChunk
						wait(1)
						ChunkUpdateDebounce = false
					end
				end
			end
		end
	end
end)

Try turning this part of code:

if not Character or not Character.Parent then
	Character = Player.CharacterAdded:wait() --point of failure
end

Into this:

if not Character then
	Character = Player.CharacterAdded:wait()
end
while not Character.Parent do -- probably an if would work too
	Character.AncestryChanged:wait()
end

You may have an edge case where the character is set already but is not parented to the game yet. You’d subsequently be waiting for CharacterAdded, but the character was already set, so it won’t fire if the character is just parented to the game after that.

Your solution didn’t work but you did get me thinking which led me to this solution which worked. Thanks!

if not Character or not Character.Parent then
   Character = Player.CharacterAdded:wait()
end
repeat wait() until Character.Parent ~= nil

Here’s what I do:

-- declare char,root,hum externally
local player = game.Players.LocalPlayer
local char,root,hum

function SetupCharacter(newChar)
char = newChar
root,hum = newChar:WaitForChild("HumanoidRootPart"),newChar:WaitForChild("Humanoid")
-- other setup stuff
end

-- this will most often happen when testing in Studio
if player.Character then 
SetupCharacter(player.Character)
end

-- every other time they respawn
player.CharacterAdded:connect(function(newChar)
SetupCharacter(newChar)
end)

-- now my character and its important components are referenceable directly with variables

The condition will cut off if “not Character” is true. It’s called short circuit evaluation. Therefore, “not Character.Parent” will only be evaluated if Character holds.

Handy, I’ll omit that in case people refer to this thread