How would I correctly wait for the character?

Hello everyone! I have a question. I have this module script:

local module = {}
local laneManager = require(script.Parent.Parent.gameModules.laneManager)

function module.run(player)
	
	wait(0.1)
	local char = player.Character
	local humanoid = char.Humanoid
	humanoid.WalkSpeed = 0
	humanoid.JumpHeight = 0
	
	local lane = laneManager.setPlayerLane(player)
	char:SetPrimaryPartCFrame(lane.spawn.startPoint.CFrame)
	laneManager.clearLane(player)
end

return module

which gets triggered by this in a normal script:

local playerModules = script.Parent.modules.playerModules

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(char)
		require(playerModules.characterAdded).run(player)
	end)
end)

If I remove the wait(.1) in the module script, it stops moving the player’s character. Is there anything other than just setting a fixed wait() in there?
I tried player.CharacterAdded:Wait() doesn’t help.

Thanks already!
-flojo

While you properly use the CharacterAdded event, the issue may lie in the humanoid not being loaded into the game fast enough, resulting in a race condition. Try using :WaitForChild to ensure that the humanoid first loads into the game, avoiding any potential errors with essentially bad timing.

Also, are there any errors in your output?

What you can do is when the function runs if the character is nil, you can wait for it to load.

local module = {}
local laneManager = require(script.Parent.Parent.gameModules.laneManager)

function module.run(player)
	local char = player.Character or player.CharacterAdded:Wait()
	local humanoid = char:WaitForChild("Humanoid")
	humanoid.WalkSpeed = 0
	humanoid.JumpHeight = 0

	local lane = laneManager.setPlayerLane(player)
	char:SetPrimaryPartCFrame(lane.spawn.startPoint.CFrame)
	laneManager.clearLane(player)
end

return module

No, I don’t get any errors & WaitForChild() also doesn’t help

As already mentioned, I tried it already with player.CharacterAdded:Wait(), it doesn’t help.

By “moving”, what are you referring to? Is the :SetPrimaryPartCFrame function not being called? Do you reset the humanoid WalkSpeed and JumpHeight to the default values after module.run is executed?

I want to teleport the player to their spawn

It should since I get the print() in my output if I add a print() after it.

No, these work fine. Since even if I don’t get teleported, I cant move & jump.

I think what you can do is wait for the humanoid and HumanoidRootPart to load using WaitForChild.

1 Like

If @iBuzzes’s solution doesn’t work, it could be the case that the character is loaded properly; the issue can lie in some other factor, such as the laneManager, causing a yield or some other issue. Could you look into that?

Waiting for the HumanoidRootPart does also not work.
I don’t think that this happens because of the laneManager, but you can also look into it:

local module = {}
local lanes = game.Workspace:WaitForChild("lanes")
local lanesMemory = {}

function module.setPlayerLane(player)
	if lanesMemory[player.UserId] then
		
		return lanesMemory[player.UserId]
	else
		
		for _, i in pairs (lanes:GetChildren()) do 
			
			if i:GetAttribute("userId") == 0 then
				
				i:SetAttribute("userId", player.UserId)
				lanesMemory[player.UserId] = i
				return i
			end
		end
	end
end

--clearLane just deletes everything besides the spawn
function module.clearLane(player)
	
	if lanesMemory[player.UserId] then
		print("clearing lane:", lanesMemory[player.UserId])
		
		local lane = lanesMemory[player.UserId]
		lane.PrimaryPart = lane.spawn.stageEnd
		for _, i in pairs(lane:GetChildren()) do
			
			if i.Name ~= "spawn" then
				
				i:Destroy()
				wait(0.05)
			end
		end
	end
end

return module

Maybe the PlayerAdded event is not being fired at all because the PlayerAdded event is set up after you join the game. We can manually ensure that every player goes through the initializing process when they join the game.

local Players = game:GetService("Players") 
local playerModules = script.Parent.modules.playerModules

local function CharacterAdded(character) 
	require(playerModules.characterAdded).run(player)
end 

local function PlayerAdded(player) 
    if player.Character then 
         CharacterAdded(player.Character) 
    end 
    player.CharacterAdded:Connect(CharacterAdded) 
end 

Players.PlayerAdded:Connect(PlayerAdded) 

-- Any new players that joined too early for PlayerAdded to be fired
for _, newPlayer in ipairs(Players:GetPlayers()) do
     PlayerAdded(newPlayer) 
end

Oh, I’m sorry I forgot to mention I have this added but when I reset myself it doesn’t work

A few post above we tried that already, it doesn’t help

repeat task.wait() until char.PrimaryPart does the trick.
Thank you all! If someone has another solution, please let me know!

1 Like

This is great! However, I’d avoid using polling like this, as there is usually a better, event-based solution possible:

if not char.PrimaryPart then
    char:GetPropertyChangedSignal("PrimaryPart"):Wait()
end
1 Like

I will try it out tomorrow, thanks
Also, if you celebrate Christmas and it’s not already over for you, Merry Christmas!
And to everyone else reading this of course!

1 Like

It didnt work, however I did change a little bit of PAGO’s solution.
I have this now & it works:

repeat wait(0.1) until char.PrimaryPart
1 Like