If you’re planning to use larger values (such as 10 seconds), it should run fine; it wouldn’t hurt for a countdown to fluctuate by 0.1-1%.
I would’ve expected someone to have made them a thing by now; they’ve even stolen Jasmine (a testing framework) and stuck it into the CoreScripts.
I always used:
repeat wait() until players.LocalPlayer.Character
I never knew
local character = player.Character or player.CharacterAdded:Wait()
was faster/even existed so will be using this from now on! Great tutorial!
Dang it, sorry for the necro-bump!
Thank you so much for explaining this. wait()
is generally snake oil when it comes to performance and such.
The worse thing is, wait(5)
can make the script wait at least 10 seconds if the client is not performing well in terms of FPS. So that’s why I’d prefer anything but wait()
.
Though we’ve embarrasingly used wait()
in our lives, it isn’t like that will be removed any later on. It’s a good start for newcomers, though. They’ll eventually learn to use :Wait()
.
It’s not really related to FPS. A client rendering at 60Hz can still have delayed resumes on yielded/newly created threads. It’s just a matter of how many yielded threads you are trying to resume at a certain moment. There’s a quotum on how much can be resumed every 2 frames.
i know that typically WaitForChild is used when scripts are waiting for something (i.e. a new part called “Specific” to be created and have the parent of Workspace, or when the client-side needs to load its entities) but i want to be specific.
when can i effectively use WaitForChild? should i avoid it like the plague as well?
i noticed in a lot of my older scripts, i tend to use this almost religiously-- it’s everywhere. knowing from this post that i’m likely not supposed to rely on waiting, i want to be able to clean that up a bit so my code is more efficient.
i usually avoid wait() itself pretty good, since in general now that i understand events it’s much easier for me to avoid. but i wonder if WaitForChild falls under this?
Nothing wrong with WaitForChild, no.
I don’t use wait function. especially when i need precise control over the flow of the script. for example if i have a tween running, and i want to pause the next frame a button or something got triggered. i can do it easily using a loop and a variable that counts how much time have elapsed. accumulating Render delta.
So what do I do at times when I actually need wait? For example when I use it to wait a certain amount before setting something like a debounce or something (there is no event so :Wait() won’t work in this case)? will I have to make my own version of wait() using a loop and checking how much time has elapsed with render delta?
You said wait() is inconsistent with how long it actually waits? if so, should i make my own version of wait() as a custom wait? then why does wait() even exist?
Implementing a custom wait is pretty easy.
local function realWait(t)
local total = 0
repeat
total = total + RunService.Heartbeat:Wait()
until total >= t
end
Hi I Tried Your Method Doing
local TickAmount = tick()
realWait(1)
print(tick() - TickAmount)
And I Got
0.26110482215881
I Waited Less Than 1 Second.
It Is Not Accurate At All. I Have Read Upon Other Posts Too And All The Implementations Seem To Be Similar But They Are Too Inaccurate. Thank You For Your Time.
Not sure where you’re getting that from. Here’s me putting it in a command line.
> RunService = game:GetService("RunService")
> function realWait(t)
local total = 0
repeat
total = total + RunService.Heartbeat:Wait()
until total >= t
end
> t = tick() realWait(1) print(tick() - t)
0.9992048740387
> t = tick() realWait(1) print(tick() - t)
1.0140511989594
> t = tick() realWait(1) print(tick() - t)
1.0150332450867
Note also that tick()
is not actually guaranteed to be correct. I don’t know if it’s written anyway, but I’ve talked to engineers that caution against using it as a measure of time.
Hi Again, I Tried A Different Waiting Time.
local t = tick()
realWait(5)
print(tick() - t)
I Got
I Don’t Think It Is Due To
tick
Because I Have Used It In Other Places In My Code And It Works Reliably. I Now Waited Even More.
However At Least It Is More Accurate Than
wait
For Me.
Using The Delta Time Return Value Of Wait (For 5 Seconds) I Got
7.1054225999997
2.1 Extra Seconds.
Time this with a stopwatch, and not through Roblox. Let me know the results, this code is extremely basic and battle tested.
I did some similar tests and, I think it’s because heartbeat throttles when the game first starts, this should settle down after a few seconds.
Module Script
local RunService = game:GetService("RunService")
local Heartbeat = RunService.Heartbeat
return function(n)
n = n or 0
local Delta = 0
repeat
Delta = Delta + Heartbeat:Wait()
until Delta >= n
return Delta
end
Script
local wait = require(location to module script)
while true do
local Tick = tick()
wait(1)
print(tick() - Tick)
end
Output
2.1537821292877
1.0095615386963
1.007693529129
1.0085482597351
1.0157716274261
1.0159933567047
So currently I have these 2 functions:
function RoundController:WaitForPlayers()
while #Players:GetPlayers() < PLAYERS_REQUIRED do
wait()
end
end
function RoundController:StartIntermission()
local beginTime = os.time()
while (os.time() - beginTime) < INTERMISSION_LENGTH do
wait()
end
end
I’m assuming the proper way to fix them would be like this:
function RoundController:WaitForPlayers()
local yield = Instance.new("BindableEvent")
local x = Players.PlayerAdded:Connect(function()
if #Players:GetPlayers() > PLAYERS_REQUIRED then
yield:Fire()
end
end)
yield.Event:Wait()
x:Disconnect()
end
function RoundController:StartIntermission()
local yield = Instance.new("BindableEvent")
delay(INTERMISSION_LENGTH, function()
yield:Fire()
end)
yield.Event:Wait()
end
please tell me if I did this the correct way, because I don’t want to make my code worse. thanks
What you have looks fine, but change > PLAYERS_REQUIRED
to >= PLAYERS_REQUIRED
Try this to see the accurate time of how much time has elapsed
local RunService = game:GetService("RunService")
local function RealWait(n)
local DeltaTime = 0
repeat
DeltaTime = DeltaTime + RunService.HeartBeat:Wait()
until not n or DeltaTime > n
return DeltaTime -- return the time elapsed
end
print(wait(1))
print(RealWait(1))
It’s more accurate then tick()
How big of a concern is this? There’s several places in my code where I use tick()
to measure time differences, for instance the custom Wait()
function that I currently use:
local function Wait(n)
local now = tick()
n = n or 0
repeat game:GetService("RunService").Heartbeat:Wait()
until tick()-now >= n
return tick()-now
end
Is this a really bad practice? Should I start using the return of Heartbeat/Stepped
instead of tick()
, or is the difference not noticeable enough to matter?
I’m not sure, I do it too, but I’m just relaying what I’ve heard from engineers.