Hello. I’m trying to make a script where a loop occurs while the mouse button is held down. A remote event is fired when the mouse is held and fired again when it is released. The script works perfectly, with the exception of the fact that Studio freezes for a short moment and returns a script timeout if the player clicks twice, supposedly if the player clicks while the looped code is still running.
I tried a debounce but it didn’t help. How could I prevent this timeout from occurring? Thanks in advance.
Below is my server-side code:
local replicated = game:GetService("ReplicatedStorage")
local hold = false
replicated.Combat:FindFirstChild(script.Name).OnServerEvent:Connect(function(player, attacktype, holding)
if holding == true and hold == false then
hold = true
while hold == true and holding == true do
--lots of redacted code here
task.wait(0.3)
else
hold = false
end
end)
And below is my client-side code, in case it is needed:
local uis = game:GetService("UserInputService")
local storage = game:GetService("ReplicatedStorage")
local event = storage.Combat:FindFirstChild(script.Name)
uis.InputBegan:Connect(function(input, _gameProcessed)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
local attacktype = "Primary"
local holding = true
event:FireServer(attacktype, holding)
end
end)
uis.InputEnded:Connect(function(input, _gameProcessed)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
local attacktype = "Primary"
local holding = false
event:FireServer(attacktype, holding)
end
end)
I decided to turn the attack code into a function:
replicated.Combat:FindFirstChild(script.Name).OnServerEvent:Connect(function(player, attacktype, holding)
print(holding)
if holding == true then
hold = true
elseif holding == false then
hold = false
end
while hold == true do
attack(player, attacktype)
end
end)
And it still works, but the script timeout still occurs if I click while the code triggered by the loop is still running.
Edit: I fixed it by adding “task.wait(0.01)” to the “while true do” part of the code, but I feel like it’s more of a bandaid solution than anything. Are there any better ways of fixing that issue?
It really depends how many times per seconds do you want the code inside the while loop to execute. Ideally, you would try to minimize that amount, especially if the code is heavy and can cause some performance issues. Nonetheless, there exists RunService.Heartbeat, which marks a function as executing every frame (I believe the server runs at 60 FPS so we’re looking at a cooldown of 1/60 so 0.016 seconds).
Connections aren’t as easy to interrupt as loops, but you can disconnect any time you need.
In pratice,
local RunService = game:GetService("RunService")
local connection: RBXScriptConnection? = nil
enableSomeFunctionality:Connect(function()
connection = RunService.Heartbeat:Connect(function()
-- something that runs every frame
end)
end)
disableSomeFunctionality:Connect(function()
connection:Disconnect()
-- prevent the connection from running (until it is connected back again)
end)
Not that it’s my problem, but you should consider a better approach for how you’re handling input. As a reference, check out Suphi’s video. It’s for a different purpose but you could learn a lot from the way he does it.