What is the ":Wait()" equivalent of this code?

So for example, instead of doing repeat wait() until player.Character, we can do, player.CharacterAdded:Wait()

So for, repeat wait() until character.Humanoid:GetState() == Enum.HumanoidStateType.Landed, what would be it’s more efficient equivalant?

1 Like

Something like this?

humanoid.StateChanged:Connect(function(oldState, newState)
    if newState == Enum.HumanoidStateType.Landed then
         print("landed")
    end
end)
2 Likes

There is no equivalent what amadeup said is the best way in doing it

You have to be a bit careful here, these are not equivalent if player.Character is already non-nil before the code is executed. Your repeat loop will wait() once unnecessarily, and continue on. player.CharacterAdded:Wait() will wait for the next time the player character gets added, i.e. a respawn. So if you have code like this that runs right around the time your character is spawning, it can cause a timing-related bug.

That said, Humanoid.StateChanged is the event you’d block on.

1 Like

Or:

local _, state
repeat
    _, state = character.Humanoid.StateChanged:Wait()
until
    state == Enum.HumanoidStateType.Landed
5 Likes

There is no equivalent for that, but if you want to avoid using wait()s, I suggest you use a BindableEvent like so.

local bindable = Instance.new("BindableEvent")

--waiting for the right humanoid state
local event = humanoid.StateChanged:Connect(function(oldState, newState)
    if newState == Enum.HumanoidStateType.Landed then
         bindable:Fire()
    end
end)
bindable.Event:Wait()
--we got the right state
event:Disconnect()

No, you should really only use bindable events between different scripts, ideally only when there is a sensible reason to not have direct coupling via function references (e.g. callbacks). The usage you show is an unnecessary extra event.

I disagree. You don’t have to use BindableEvents only for two separate scripts, even though that’s that the purpose of it is. You can get creative with it. The event I made is efficient and necessary because doing repeat wait() until condition is not that great.

Well, yes, however I believe this can be fixed by doing

local Character = Player.Character or Player.CharacterAdded

By using this inline expression, we have more control and don’t need to wait if the character is already added.

This is what I usually do if I need to wait for the character to be added.

You’re creating a new event, and firing it from within the event handler function of an existing event. That’s not efficient, it’s an extra event for no reason. And I didn’t say BindableEvents can’t be used within the same script, only that they shouldn’t be, since there is never a need to do this.

I’m assuming you meant to write
local Character = Player.Character or Player.CharacterAdded:Wait()
which is correct, that form is fine.

2 Likes

Didn’t bother to doublecheck, but yes - that is what I’m saying, I forgot to add the actual :Wait().
I assume it could have been done in two ways, however not needed:

local Character = Player.Character or Player.CharacterAdded:Wait()
local Character = Player.Character
if not Character then
   Character = Player.CharacterAdded:Wait()
end

I do prefer what I first replied with, though.

1 Like

Whoops, forgot to say I do. character = player.Character or player.CharacterAdded:Wait(), but that’s an interesting to note.

I like this implementation so I decided to use this. I really didn’t want to use a BindableEvent. I don’t even know how to use them…

You know you can do this without a BindableEvent, right? You should also be accounting for initial state in case it’s what you already want, otherwise you’re going to be waiting unnecessarily or potentially permanently. Use the event you’re already given.

local humanoidState = humanoid:GetState()

while not (humanoidState == Enum.HumanoidStateType.Landed) do
    local _, newState = humanoid.StateChanged:Wait()
    humanoidState == newState
end

Same job, no BindableEvent, loop only starts if the state we want is not initialised and it updates the condition so that it can be checked again in the future if it needs to run another iteration to find if the right state type has been reached or not.

Pretty sure this is also a case where Promises can shine.

How would a promise implementation work?

Also which would be more efficient?
This code provided by, @nicemike40 or the code you provided just now?
Also how would a “promise” preform in this case?

The primary difference to understand is that between a repeat and a while loop. A repeat loop will always run its iteration once, while a while loop will not start at all if the condition is met before an iteration occurs. In JS, it’s the equivalent of “while x do {}” vs “do {} while x”. I do think my code is better, maybe not in this specific case but in a good number of them.

My code makes sure to use GetState first to check if the HumanoidStateType is already the value we want. The while loop check if the HumanoidStateType is not what we want: if it isn’t, then we listen for StateChanged and update the variable to the new Humanoid state. This process repeats, only running code when HumanoidStateType isn’t what we want, until it is what we want.

nicemike40’s code does not start with initial state, so even if you start off with the HumanoidStateType you want your code will not continue and will start off by listening for StateChanged until it returns the state type you want. You want to avoid doing iterations if you don’t need to. That’s where the power of my solution comes into play: avoiding unnecessary initial iterations.

In terms of efficiency, it’s negligibly efficient. I’d strive to use the while one though.


A Promise represents a value that may exist in the future but doesn’t now. I was thinking about applying a Promise to this problem so that your code could continue to check states in the background without interfering with the rest of your code, given that either of these solutions would cause your code to yield until the HumanoidStateType returns back the value you want.

I don’t think it’s necessary in this case though. I just stuck it up there in the air.

1 Like

That’s awesome, you taught me something new. I’ll have to use implementations like this in the future. Thanks!

What is more “efficient” is coming up a lot in this thread, and it’s basically irrelevant because we’re talking about suspending a thread waiting for a network operation (actually multiple, plus memory allocations and other expensive things) that’s going to take several orders of magnitude longer than executing any of the code associated with it. So try not to get too hung up on this; plus or minus one stack variable allocation in code that runs once per character load really doesn’t matter.

The benefits of Promises are not performance benefits. Just like with using Object Oriented Programming vs. procedural, it’s more about the organization and extensibility of the code, and resistance of the code to becoming spaghetti as it grows.

You could certainly use Promises to manage the Player, Character, and CharacterAppearance loading process if you find that the pattern appeals to you. You might find the resulting code structure cleaner and easier to manage, such that you end up writing fewer bugs (particularly bugs relating to unhandled or mis-handled failure cases in chains of async calls). Promises are basically an organization pattern for handling asynchronous operations, to make your code for handling the success, failure, and chaining of dependent operations cleaner.

2 Likes