Make your own custom wait function! (FASTER THAN 1/180 of a second!)

I made a custom wait function and would like your thoughts on it. It is very easy to make, use, and explain, so feel free to try it for yourself!
The function code:

local function wait(TIME: number?)
	local t = tick
	local i = t()
	TIME = TIME or 0.01
	local w = task.wait
	local r = math.random
	while t() - i < TIME do
		if r(1,10000) == 1 then w() end
	end
	return t() - i
end

The explanation:
1: The first line declares the name of the function and states that the function may have one integer argument, but the ‘?’ also lets it know that we can leave it blank.

  • Note: make sure you have type checking on default or strict mode.

2-3: The next two lines create variables to tick and set up a starting time so we can measure how long has passed.

4: We now set TIME to itself if it exists, and set it to a default value of 0.01 if it is nil (missing).
5-6: We set reference variables to math.random and task.wait to use later.

7: We start a while loop that will keep going until the time passed (calculated by
current time - start time) is greater than or equal to the time amount set by the function caller.

8: A debounce value that will ensure the while loop stops every so often (1 per 100000). Without this, large wait times will cause a script execution overflow.

9-11: We end the while loop and afterward return true from the function. This allows us to do while wait() do because it is true. Finally, we close our function with the end.

How to use:
Call it by simply doing wait() and either provide a wait time or not. The default wait time is 0.01 so, if you want it faster, make it even smaller and specify it as the argument. You can use It alone to halt program execution, or in a while wait() do.

Accuracy and Speed:
Accuracy: This is the only accurate wait function below normal wait() and task.wait() time bounds. Comparing to wait and task.wait:

For 0.001 second counting:
wait() – normal: ~ 0.57
task.wait(): ~ 0.026
wait() - new: ~ 0.001

For 0.1 second counting:
wait() – normal: ~ 0.2
task.wait(): ~ 0.14
wait() - new: ~0.15

For 1 second counting:
wait() – normal: ~ 1.06
task.wait(): ~ 1
wait() - new: ~ 1

For 100 second counting:
wait() – normal: ~ 100
task.wait(): ~ 100
wait() - new: ~ 100

Conclusion of accuracy: It does not matter which you use for normal timeframes, so just go ahead and use task.wait for that. Where the new function really shines is below the others’ bottom clamp. The others are totally inaccurate with really small times, whereas the new wait is extremely accurate.

Conclusion and Final Notes: If you need a really fast loop, or a really accurate small timekeeper, this function will be useful! Please let me know if I should repost this in resources, and share any and all bugs that you may find!

1 Like

This doesn’t work. You’re just running code that does nothing. Using this in a forever loop will just crash the game.

This is basically what you’re doing:

local function fasterWait()
    return
end
local start = os.clock()
fasterWait() --> woah! this wait is even faster!
print(os.clock() - start)
2 Likes

Isn’t this like DeltaTime or am I wrong?

local function wait(TIME: number?)
	local t = tick or os.clock
	local i = t()
	TIME = TIME or 0.01
	local w = task.wait
	local r = math.random or Random.new
	while t() - i < TIME do
		if r(1,100000) == 1 then w() end
	end
	return true
end

while true do
    wait(0.5) 
end

Oops, the client crashed

It is working for me, try decreasing the second value of the random arguments in the if statement, It seems to be working for me, at least in the studio.

delta time basically means subtracting the newer time from the old time, so yes, it is delta time. But lua is so fast, it will basically either be 0 or less than 0.03

How is that what I am doing? Mine works for any time by having a while loop that every so often waits for task.wait until the time elapsed it equal to or greater than requested. The reason for the return statement is so that loops will recognize that it is true.

This code is absolutely not going to work. The code below will crash because the loop is only waiting under a hyperspecific window. Also, in your example, task.wait() was equal or more effective… so… why?

while ... do
	if r(1,100000) == 1 then w() end
end

As I explained, it’s for very fast times, and when you want loops to run faster, did you look at the first test? Decrease the 100000 to lower if you would like. That should prevent lag.

If your code requires you to rely on randomness, it is not effective. Plus, this code is not at all for “fast times.” Waiting at a random chance would cause the total wait time to be inconsistent.

Yes, if you would like, there is a non-random way. Would you like to see the code with that?

I do not think this “non-random way” will be any more effective than task.wait. I’ll take a look, though

1 Like

Ok, like i said previously in the post, just use that for almost everything you could want to do, this was just for fun.

The way I was thinking of did not work, but the reason why I did not mention the inconsistency in wait times is that real wait times also have the same, if not more inconsistency (at least with wait). The chance of the random being picked if you just wanted to wait for a very small time, is very small. The main idea was to see how quickly a loop could go, without crashing.

Why? Just why? You do understand that you’re completely relying on RNG that this thing even work right? If the RNG is having a really bad day, there goes one player. There’s so much to say about the code here.

  1. Why are you localizing globals in the function?
  2. Why are you checking tick or os.clock if tick will always exist? It’s going to get deprecated, not removed.
  3. Same thing with math.random or Random.new but the API for Random.new is different.
  4. Why is true being returned? You better not be trying to make it compatible with the while wait() do idiom. wait() and task.wait() returns the elapsed time.
1 Like
  1. To make it look more concise.
  2. tick does not work on the luau demo page, so just added it as an extra precaution.
  3. I have never used Random, so thanks for correction, I thought it might also be replacing math.random.
  4. Thanks for letting me know, I have never needed the time returned.

This was only a fun way to make loops that ran faster than normal, yet still waited and did not crash.

This is just a stylistic note here (I promise I’m not piling on the rage train!!!), but readability should always be prioritized above concision. Remember, we aren’t being charged by the character or by the line here! Truncated code also doesn’t give you any performance benefits. A great rule of thumb is that good code should be able to read like plain-text

Example
Code 1 - reads like plain English
local Players = game:GetService("Players")

local WhitelistedUsersIds = {
	1,
	2,
	45,
	73,
	97,
}

--// Preceding code/sub-functions also reads easily so that anyone reading it should be able to understand the logic pretty easily
local function CheckIfPlayerIDIsWhitelisted(PlayerID: number)
	local FoundInWhitelistTable = table.find(WhitelistedUsersIds, PlayerID)
	
	if FoundInWhitelistTable then
		return true
	else
		return false
	end
end

--// Core code reads like English - even a non-programmer could get what is going on pretty easily
Players.PlayerAdded:Connect(function(Player: Player)
	local PlayerIsWhitelisted = CheckIfPlayerIDIsWhitelisted(Player.PlayerId)
	
	if PlayerIsWhitelisted then
		print("Whitelisted Player Found")
	else
		print("Player is not whitelisted")
	end
end)
Code 2 - does the same thing in 5 lines, but is much harder to read
local WhitelistedUsersIds = {1, 2, 45, 73, 97}

game:GetService("Players").PlayerAdded:Connect(function(Player: Player)
	if table.find(WhitelistedUsersIds, Player.PlayerId) then print("Whitelisted Player Found") else print("Player is not whitelisted") end
end)

Clarity over concision makes your own projects easier to maintain as things scale up and easier for other developers to grasp what your code is doing on the first look versus having to re-reference the code over and over (ex: I had to read the code multiple times to figure out what variable t, i, w, and r meant - reading variable names captured in single letters versus just writing out random or tick [a separate discussion of whether these really need to be localized at all does exist]).

Just wanted to add that as a small note!

I definitely don’t suggest doing this. What this code does is rev up the processors as a yielding function. In other words, it does this:

--"Yield"
for i = 1, 50000 do
	--fake "yielding" by doing something
end
--Resume
2 Likes

Don’t use this code.

This is literally wasting so much processing power that it slows down code execution.

This is completly false. A really fast loop should just run for x number of times then yield to the next execusion cycle. Someone can use the time library for a timekeeper. There is no reason to wait less than the events Roblox already gives you, and definitely no reason to do something that slows down your entire game.

2 Likes

Agreed,

That would be slowing down Computers since the said computers can barley process stuff that fast, You would pretty much be overwhelming the Computer with all the Data in a short Period of time,
Don’t get me wrong, they are fast, but not that fast,

For Example:
functions like print and math take time to process, this would just cause lag due to that time needed to process that information, and execute it.

Since it runs so fast, It will either freeze the Server (or client), or Lag the game

2 Likes