You are infact incorrect. I have benchmarked whether or not numeric is faster than the generic loop. Numeric loops seemed to be significantly faster whether or not the amount of elements in the array was 10 or 10,000,000. Here is the source code:
local array = {}
for i = 1, 10000000 do
array[#array + 1] = math.random(1, 100)
end
for i = 1, 5 do
local startTimeOne = os.clock()
for index, value in ipairs(array) do
end
local ipairsTime = os.clock() - startTimeOne
print('ipairsTime: ' .. ipairsTime)
local startTimeTwo = os.clock()
for i = 1, #array do
end
local numericTime = os.clock() - startTimeTwo
print('numericTime: ' .. numericTime)
print('')
end
The results I got when i appended 10 elements or 10,000,000 were the same. The reason I prefer ipairs over the numeric is that ipairs caches the value inside the numeric. The ‘speed’ of the loops don’t really matter when you are accounting for what goes inside the loop when using numeric ’ t[i] '. Luckily, the ipairs iterator caches the value. Numeric is indeed faster though.
It is best like @TheEdgyDev said, to use what is best practice rather than trying to find cases where something becomes acceptable over the latter.
If you read sections on the roblox task scheduler, it mentions that ‘The most direct way to add frame-by-frame game tasks is through the following members of RunService’. Instead of nitpicking ways to advocate for wait() usage you should pick an overall better yieldMethod that is practical in most scenarios. Also, having a custom wait function is not to be rude, a terrible idea for the following reasons.
-
Polling is bad practice. You can read a more indepth explanation on why: Avoiding wait() and why
-
Now you may be wondering. Whats wrong with polling? Polling is bad since you are constantly yielding even when not needed. You are adding constantly adding those instructions into the task scheduler. The issue is when you use this practically in game development and have lots of custom wait functions being called.
When you delay the task scheduler to do a certain task, it will push that task to the next frame. It’s good that you are using heartbeat which has the lowest priority, but other more relevant functions could be using heartbeat as well. As you can see from a game development standpoint it’s quite impractical.
- There is a much better way of creating a custom wait without polling!
local runService = game:GetService('RunService')
local signal = require(game:GetService('ReplicatedStorage'):WaitForChild('Signal'))
local function smarterWait(yieldTime)
yieldTime = yieldTime or 0
local signalOBJ = signal.new()
local accumulated, connection = 0, nil
connection = runService.Heartbeat:Connect(function(dt)
accumulated = accumulated + dt
if accumulated >= yieldTime then
signalOBJ:Fire()
end
end)
signalOBJ:Wait()
connection:Disconnect()
signalOBJ.BindableEvent:Destroy()
end
return smarterWait
Do I recommend using this?: Heck no. I’d rather just do wait(5). There still comes the creation costs of implementing bindables and destroying them.
Is this better than using a custom wait that polls: Heck yeah
Custom Signal Source Code
It also seems you use Heartbeat in your custom wait function instead of wait()? That dissaproves your point in using wait() over Heartbeat:Wait() in the first place.