Could this code create lag?

Hello all. Today I’m not necessarily asking for help on a specific issue, instead, I want to make sure I’m using ReplicatedStorage in the least resource-demanding way possible.

I’m making a destruction physics game, and as part of the game, you can regenerate structures. I have a script that, when you click a button, will fire a RemoteEvent to the server that will loop through the Workspace, find any houses (houses are the structures the players are destroying), destroy the house, and regenerate a new one.
My code works miraculously, but I’m not sure if there’s a better way I could go about this. There are a lot of welds and broken parts in my game, which I know can be resource-demanding at times. Should I maybe invest in a cool down, if I constantly have people sending server requests and stuff?

local RS = game:GetService("ReplicatedStorage")
	
RS.ResetHouse.OnServerEvent:Connect(function()
	for _, house in pairs(game.Workspace:GetChildren()) do
		if house.Name=="ReplicatedHouseModel" then
			house:Destroy()
		end
	end
	print("gen new house")
	local houseClone = game.ReplicatedStorage.Model:Clone()
	houseClone.Parent=workspace
	houseClone.Name="ReplicatedHouseModel"
end)
2 Likes

I think you should really put a cool-down, or else people is able to keep spamming crashing the Server

5 Likes

It could. Maybe try testing it, if it does then replace it with this.

local RS = game:GetService("ReplicatedStorage")
	
RS.ResetHouse.OnServerEvent:Connect(function()
	for _, house in pairs(game.Workspace:GetChildren()) do
		if house.Name=="ReplicatedHouseModel" then
			house:Destroy()
            wait(0.01)
		end
	end
	print("gen new house")
	local houseClone = game.ReplicatedStorage.Model:Clone()
	houseClone.Parent=workspace
	houseClone.Name="ReplicatedHouseModel"
end)
1 Like

I’ve tested it, only in Roblox Studio on my beefy PC, not on a lower-end mobile device. It doesn’t crash, in fact, it works pretty well.

2 Likes

easy enough to stop spamming lag

local DB =  true
local RS = game:GetService("ReplicatedStorage")

RS.ResetHouse.OnServerEvent:Connect(function()
	if DB == true then DB = false
		for _, house in pairs(game.Workspace:GetChildren()) do
			if house.Name=="ReplicatedHouseModel" then
				house:Destroy()
				task.wait(0.01)
			end
		end
		print("gen new house")
		local houseClone = game.ReplicatedStorage.Model:Clone()
		houseClone.Parent=workspace
		houseClone.Name="ReplicatedHouseModel"

		task.wait(3)
		DB = true
	end
end)

I wish people would stop using this inferior debounce method, it forces you to yield (which, in this instance, would cause any listener after this one on ResetHouse.OnServerEvent to be held up).

People really need to move over to a time-based (either using tick() or os.time()) system, which can avoid yielding altogether.

-- On another note, do not abbreviate names. It only serves to make code
-- more difficult to read.
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local HouseModel = ReplicatedStorage.Model
local ResetHouse = ReplicatedStorage.ResetHouse

local lastCalled: number, timeout = nil, 3
ResetHouse.OnServerEvent:Connect(function()
    if lastCalled and tick() - lastCalled < timeout then return end
    lastCalled = tick()

    -- You should consider placing these houses in a folder in the workspace,
    -- as to avoid having to grab EVERY child of workspace. This example will
    -- still treat it as though they're parented to workspace.
    for _, child in workspace:GetChildren() do
        -- Luau has continue.
        if child.Name ~= "ReplicatedHouseModel" then continue end

        child:Destroy()
        -- You don't need to pass anything to task.wait if you're just trying
        -- to avoid setting the parent more than once per frame.
        task.wait()
    end

    print("Generating a new house.")

    local clonedHouse = HouseModel:Clone()
    -- Don't set the parent first, do it last. Otherwise you'll cause Roblox's
    -- reactive system to unnecessarily send out waves of updates.
    clonedHouse.Name = "ReplicatedHouseModel"
    clonedHouse.Parent = workspace
end)

That being said, if you really do need to yield for your debounce, please use Parallel Luau (Actor instances, RBXScriptSignal:ConnectParallel(), task and coroutine etc.) to ensure you don’t interrupt anything else. In most cases, you do not need to yield.

3 Likes

The pause is a good thing and this totaly stops button spamming. The whole point of a DB …
I actually call this a FTF but put DB so he would know what it is … (First Time Flag). With my programs I go one step more with this and drop the click distance to 0 for that pause.

The code I provided still debounces, it just doesn’t yield in order to do it. Just try the following code yourself, you’ll see it’ll “ignore” the second call to x().

-- When we last called x, and how long to wait between honoring calls.
local lastCalled: number, timeout = nil, 5
local function x(): ()
    -- Check if x is being called before the timeout has passed.
    if lastCalled and tick() - lastCalled < timeout then return end
    lastCalled = tick() -- Reset lastCalled to when we last honored the call.

    print("Hello, World!")
end

x() -- "Hello, World!"

-- We can do other things here, we don't yield in x.

-- If what we did between now and the last call to x took less than the
-- timeout, this won't actually print anything!
x() 

-- Ask the Engine to call x after timeout, this also doesn't yield.
task.delay(timeout, x) -- "Hello, World!"

A less complex system would be.

local __DATA = game
local __CS = __DATA:GetService("CollectionService")
if not __CS:HasTag(__PLAYER, "__EVENTCD") then
    __CS:AddTag(__PLAYER, "__EVENTCD")
    task.delay(3,function()
        __CS:RemoveTag(__PLAYER, "__EVENTCD")
    end)
end

That is not at all less complex, and I would really avoid doing this unless you’re working with an entity component system (ECS) or something similar.

I mainly use that cooldown system for ease due to its simplicity. Besides, It’s much better than table cooldowns.

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