Best way to Wait() for Character?

I had some trouble with my local script, located in the StarterPlayerScript, as It would not execute when I’ve spawned. I’ve finally come to a solution; here’s the code →

wait()

local player = game.Players.LocalPlayer

local character = player.Character

if not character or not character.Parent then

character = player.CharacterAdded:Wait()

end

My question is if there is a more efficient or better way of doing this, suggestions would be appreciated. :slight_smile:

5 Likes

Yes, there is by using or keyword.

local player = game.Players.LocalPlayer
local Character = player.Character or player.CharacterAdded:Wait() --If player.Character is nil then it will wait for CharacterAdded event to fire because of :Wait()
13 Likes

This would usually work except this is located in the StartPlayerScripts, and for some reason I need to use a wait() for the script to execute.

1 Like

If you have an issue that is being fixed by wait(), something is wrong and that is not the solution. What do you mean by having to use it to execute?

5 Likes

I mean the only time this would not work is when player respawns, which in that case you can just connect it to CharacterAdded event but what do you mean by you have to use wait() to make the script execute? Are you changing client’s cameraType or something?

1 Like

An easy solution to this would be to put the script in StarterCharacterScripts instead of StarterPlayerScripts

In StarterCharaterScripts, the script executes only once the character instance has been added.

If you absolutely cannot put the script there, you can always assume the player will load before the character, because it’s not possible to have a character without having a player instance first. I would edit your script to have as few yields as possible. Getting rid of the first wait() you have will ensure that the script initializes before the character is added. So your script should look something like this in the end:

local player = game.Players.LocalPlayer
player.CharacterAdded:Connect(function(character)
  --Do stuff with character instance here, this will only fire once the character has been added
end))
5 Likes

If I don’t place the wait() function at the beginning of the local script, then everything after the function would not take action when I spawn my character.

Something is definitely wrong then. Have you tried placing prints or using the debugger to see exactly where it halts? Maybe you’re trying to wait for the character after it’s already spawned or have some other yielding method.

3 Likes

here’s an example →

wait()
local player = game.Players.LocalPlayer
local character = player.Character
if not character or not character.Parent then
	character = player.CharacterAdded:Wait()
end

local hum = character:FindFirstChild("Humanoid")
if hum then
	print("Humanoid found")
	while wait(1.2) do
		hum.Jump = true
		print("Start jumping")
	end
end

I see your issue. Instead of :FindFirstChild do :WaitForChild and remove the wait at the top.

The reason you had to wait() before was because the humanoid does not load at the same time as the character and gets added after the character is added.

The optimal layout for this script would be a script in StarterCharacterScripts which contains the following

local Character = script.Parent -- because the script will be a decendant of the character if placed under StarterCharacterScripts
local Humanoid = Character:WaitForChild("Humanoid") -- wait for the humanoid to get added

while wait(1.2) do
 Humanoid.Jump = true
 print("Jumped")
end 
2 Likes

I got a warning, and it still doesn’t execute. Oh, I thought script.Parent would be the Character for some reason. Be right back. I think you’ve paved the path for me to find a solution to this. :grin:

Infinite yield possible on 'Players.Tixabel.PlayerScripts:WaitForChild(“Humanoid”)

Did you put the script in StarterCharacterScripts or StarterPlayerScripts? Make sure its in StarterCharacterScripts otherwise you’ll be trying to look for the humanoid inside of the PlayerScripts folder which wont work.

1 Like

Also, the StarterCharaterScript is a good solution, I’m just trying to see what’s possible with StarterPlayerScripts.

local Players = game:GetService("Players")
local player = Players.LocalPlayer or Players:GetPropertyChangedSignal("LocalPlayer"):wait()
player.CharacterAdded:Wait()
local character = player.Character
local hum = character:WaitForChild("Humanoid")

while wait(1.2) do
	hum.Jump = true
	print("Start jumping")
end

Found a solution without using the wait() function at the beginning of the script :grin:

just to point out, you can also update the character and humanoid variable through player.CharacterAdded event and it should work again after the character Instance is destroyed.

edit: same goes for localscripts located in StarterPack

1 Like
local Players = game:GetService("Players")
local player = Players.LocalPlayer or Players:GetPropertyChangedSignal("LocalPlayer"):wait()
player.CharacterAdded:Connect(function(character)
	local hum = character:WaitForChild("Humanoid")

	while wait(1.2) do
		hum.Jump = true
		print("Start jumping")
	end
end)

Thanks for pointing out, now I’ll be more aware to not rely on wait() functions alone by any means necessary :yum:

1 Like

LocalPlayer should also always be available as far as I know. I doubt it’s necessary to yield for it.

5 Likes

Don’t forget to call the function in CharacterAdded if the player.Character exists!
Also made a few edits that I think would improve your code.

So like this:

local Players = game:GetService("Players")
local player = Players.LocalPlayer -- no need to wait for LocalPlayer

local function onCharacterAdded(character)
    -- I prefer a little more verbose variables.
    local humanoid = character:WaitForChild("Humanoid")

    -- while wait() do isn't the best practice. Use the condition of while x do to check if character and
    -- humanoid exist

    while character and humanoid do
       wait(1.2)
       -- Possible bug since the character may not exist after 1.2 seconds, even though we did a check.
       -- Not a big deal since it simply errors, but if you'd like to remove some random errors.

       if not character then
          break
       end

       if not humanoid then
          break
       end

       humanoid.Jump = true
	   print("Start jumping")
	end
end

if player.Character then
   -- You should probably use FastSpawn instead of coroutines if you want good errors
   coroutine.wrap(onCharacterAdded)(player.Character)
end

player.CharacterAdded:Connect(onCharacterAdded)
6 Likes

This has some unnecessary code. Neither the loop condition nor loop body need to check character and humanoid. Since these are local variables, they only change when explicitly set by the user.

1 Like

Thanks, @Autterfly, for the information. The link above clarifies what you say; the only time LocalPlayer is necessary to yield would be if the local script were located in the ReplicatedFirst. The LocalScript can sometimes run before the LocalPlayer is available, so it needs to be yielded.