For Loop takes longer than intended

I am working to gradually decrease a humanoid.WalkSpeed in 0.3 seconds. I initially prompted to using TweenService to execute this and utilize the Time parameter. But I read here somewhere that it is not performant to tween on the server. Hence, I proceeded to simulate tweening with for loops. The issue is that my for loop takes longer than tweening when I intended it to take the same amount of time.

Tween:

local tween = TweenService:Create(humanoid, TweenInfo.new(0.3), {WalkSpeed = 0})

local oldTime = tick()

tween:Play()

tween.Completed:Connect(function()
	print(tick() - oldTime) --prints close to 0.3
end)

For Loop:

local oldTime = tick()

for i = 1, 9 do
	humanoid.WalkSpeed -= 16/9
			
	task.wait(1/30)
end
		
print(tick() - oldTime) --prints close 0.4

If I’m doing my maths correctly, the for loop should also take 0.3 seconds as it iterates 9 times in 1/30 seconds interval. 9/30 = 0.3.

Somebody please enlighten me on what I have done incorrectly, what actually takes place behind the scenes, and the proper route to approach this phenomena. Every comment will be greatly appreciated. Thank you! :smile:

4 Likes
task.wait(1/30)

I don’t know why, but doing 0.3 instead of 1/30 makes the wait way more accurate.

I conducted a little experiment, 0.3 is more consistent and closer to actual 0.3.

This simple fix will work, however, just so you know, task.wait isn’t going to be accurate and you shouldn’t heavily rely on it.

2 Likes

But I read here somewhere that it is not performant to tween on the server.

First off, I think what you were being warned about here is not so much about using a Tween, but gradually manipulating the walkspeed on the server. The server will regularly send information to the client about the new walkspeed, and the client will update that walkspeed whenever it receives new information. However, if you have an inconsistent ping, you may see your walkspeed jump to lower values erratically rather than smoothly - regardless of whether you use tweening or a for loop. I would do this manipulation on the client instead (at which point, feel free to use whatever method, even tweens).

As for your issue of inaccurate times: task.wait(t) will wait at least t seconds, but may wait longer than this. Note that task.wait also returns the actual amount of time it waited, so if you wanted to make a more robust loop, you’d want to keep track of those returned values and adapt accordingly. You can find an example of that in the default Health script of any roblox character, where if wait actually waited 1.03 seconds, you’ll actually heal 1.03 percent of your health:

local REGEN_RATE = 1/100 -- Regenerate this fraction of MaxHealth per second.
local REGEN_STEP = 1 -- Wait this long between each regeneration step.

--blah blah some more stuff

while Humanoid.Health < Humanoid.MaxHealth do
	local dt = wait(REGEN_STEP)
	local dh = dt*REGEN_RATE*Humanoid.MaxHealth
	Humanoid.Health = math.min(Humanoid.Health + dh, Humanoid.MaxHealth)
end
2 Likes

Thank you for your comment! I used 0.03 for task.wait and noticed closer accuracy. I would assume that since 1/30 = 0.333… is a repeating decimal, it takes the engine longer to compute. (By all means, correct me if I am mistaken)

However, this still does not beat the accuracy and consistency that I get when using Tween. I appreciate your insight!

1 Like

(By all means, correct me if I am mistaken)

Not gonna lie, no idea, but I think you’re on the right tracks.

However, this still does not beat the accuracy and consistency that I get when using Tween. I appreciate your insight!

I would suggest just editing the walkspeed on the client, after all the server trusts the client on walkspeed, and it would just be so much more smoother overall.

2 Likes

Thank you for your comment! That is a brilliant example! I also thought of doing it on the client, but its major issue is risking exploitation. (My last post was actually about this. [Server or client? Where should I change Humanoid properties?]) But then, from what I know, the client has access already with WalkSpeed, so might as well break the golden rule and trust the client??? Let me know your thoughts. Thank you!

The server trusts the client on specific things; an example of two of these are character position and walkspeed. That means they’ll be able to change those two things no matter what you do. To implement anti exploit on properties controlled by the client, we just check on the server. If the character position changes by a big amount over a small period of time, that’s either 1. the character glitching out and being flung or 2. the client exploiting and teleporting. If you never edit the walkspeed in one of your scripts, and the clients walk speed isn’t the default one, then the client is editing the walkspeed.

So, it’s fine to edit the walkspeed of the humanoid on the client and it changes nothing in terms of exploitability.

edit: some spelling mistakes

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.