While loop is tied to framerate

Hello.
I’m working on a first-person shooter, and one problem I’ve come across is the shooting while loop for automatic weapons is tied to what I think is the player’s framerate. This usually occurs when I shoot a character, which I find to be somewhat performance intensive. Here’s a video of the issue;

(the output shows the wait time between the beginning and end of the loop)

I want to know what the solution to this problem is, or at least if there is a better approach to making this less noticable. Here’s the code to the client shooting.

local t

while userInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
	t = tick()
	if
		weaponInfo
		and weaponInfo.Ammo.Value > 0
		and weaponInfo.OnCooldown.Value == false
		and weaponInfo.Reloading.Value == false
	then
		local result = getFireDirection()
		actionVisualFunctions[1]() -- viewmodel visuals when shooting
		weaponActionEvent:FireServer(1, result ~= nil and result.Position or currentCamera.CFrame.Position + currentCamera.CFrame.LookVector * 16384)
	end
	if not weaponIdInfo[weaponId].Auto then break end
	task.wait()
	print(t - tick())
end

Any help is appreciated!

1 Like

well, yeah, the framerate is the fastest your game can process code, and while true is spamming the same block of code as fast as possible

you would use something called “deltaTime” inside of runservice to measure the amount of time for code that needs to be more precise

I’ve heard of deltaTime, but I’m not sure how to implement it to the loop.

If I used RenderStepped, it would still be tied to framerate, specifically the player’s. Using Stepped would tie the loop to the framerate of the physics simulation. If this is the most precise option, I will use it, but I’m pretty sure there are more precise loops. Heartbeat is also a similar case.

What I’m trying to say is that I know about RenderService, but I’m not sure how to get the most precise loop from it. Could you tell me which event would be the most precise to use for a loop?

there is no “most precise loop”

if your framerate is horrible enough, any loop will break

what you should do is use delta time to sort of “make up” for the lost time

like how when you lag really badly, everything sort of just warps to where its supposed to be once you receive all the delayed info packages before the game goes back to normal

task.wait Is equivalent to RunService.Heartbeat:Wait() which means its tied to the framerate so try adding .001 to task.wait(.001) this should stop it from running each frame (or even higher)

Or use the deprecated wait global

Actually this value is really small since most clients run on 1/60 fps which is roughly 0.016 seconds. A safe delay to add in that is 1/30 or 0.0333.

The issue with the post is that task.wait() without arguments assumes minimum time, and that’s directly related to the client fps.

You’re going to have to use a deltatime to solve this.

Psudocode:

(sorry if this is hard to follow, i dont have enough code snippets to create it myself, as it appears .oncooldown controls when the gun can fire, which isn’t controlled by this code snippet)

New frame:
Check time since last frame (deltatime)
Add deltatime to “timepool” variable
If the timepool variable is too high, reset it down to a maximum cap.
Check if the timepool variable is above the theshold:
- if so, fire (or in your case disable.OnCooldown), then reduce the timepool variable by the threshold

Let me know how it goes!

This works very well, but I have one question;
How can I make this system harder for hackers to just fire without a cooldown? I will still use this, but if it’s really easy for hackers to just exploit the system, I might not use it.

For this you only work on the server side and add a rate limiter as you cannot fully control the client.

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