Hello, everyone!
I’d appreciate any improvements for my code examples (server and local scripts).
Both the remote event (example_remote_event) and the button (example_btn)'s functions are just debounced on purpose.
Server debounce:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local services_module = require(ReplicatedStorage.services_module)
local services = services_module.services
local debounces = {
example_debounce = {}
}
local default_debounce_time = 0.5
local remotes = {
example_remote_event = services.ReplicatedStorage.Remotes:WaitForChild("example_remote_event")
}
local script_connections = {}
local example_remote_event_connection = remotes.example_remote_event.OnServerEvent:Connect(function(plr)
if debounces.debounce[plr.UserId] then return end
debounces.debounce[plr.UserId] = true
task.delay(0.1, function()
debounces.debounce[plr.UserId] = false
end)
end)
table.insert(script_connections, example_remote_event_connection)
local function player_removing()
for _, connection in ipairs(script_connections) do
connection:Disconnect()
connection = nil
end
table.clear(script_connections)
end
services.Players.PlayerRemoving:Connect(player_removing)
game:BindToClose(function()
if services.RunService:IsStudio() then return end
for _, plr in ipairs(services.Players:GetPlayers()) do
task.spawn(plr, player_removing)
end
end)
Local debounce:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local services_module = require(ReplicatedStorage.services_module)
local services = services_module.services
local debounces = {
example_debounce = false
}
local quick_debounce_time = 0.1
-- UI stuff
local example_gui = script.Parent
local example_btn = example_gui:WaitForChild("example_btn")
local script_connections = {}
local example_btn_activated_connection = example_btn.Activated:Connect(function()
if debounces.debounce then return end
debounces.debounce = true
task.delay(0.1, function()
debounces.debounce = false
end)
end)
table.insert(script_connections, example_btn_activated_connection)
local function player_removing()
for _, connection in ipairs(script_connections) do
connection:Disconnect()
connection = nil
end
table.clear(script_connections)
end
services.Players.PlayerRemoving:Connect(player_removing)
Fixed server script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local services_module = require(ReplicatedStorage.services_module)
local services = services_module.services
local debounces = {
example_debounce = {}
}
local default_debounce_time = 0.5 -- now used
local remotes = {
example_remote_event = services.ReplicatedStorage.Remotes:WaitForChild("example_remote_event")
}
local script_connections = {}
local example_remote_event_connection = remotes.example_remote_event.OnServerEvent:Connect(function(plr)
if debounces.debounce[plr.UserId] then return end
debounces.debounce[plr.UserId] = true
task.delay(default_debounce_time, function()
debounces.debounce[plr.UserId] = false
end)
end)
table.insert(script_connections, example_remote_event_connection)
local function player_removing()
for _, connection in ipairs(script_connections) do
connection:Disconnect()
connection = nil
end
table.clear(script_connections)
end
services.Players.PlayerRemoving:Connect(player_removing)
game:BindToClose(function()
if services.RunService:IsStudio() then return end
for _, plr in ipairs(services.Players:GetPlayers()) do
task.spawn(plr, player_removing)
end
end)
What is that and why is it there?
After all you could just do game.Players.PlayerRemoving:Connect(player_removing)
at that point.
And in any case, this will trigger if any player leaves, not just LocalPlayer.
I also don’t think you even need to disconnect this local event anyway, since you actually want to disconnect when the LocalPlayer leaves. That’s obviously unnecessary.
It’s a module for all of my most commonly used services using: game:GetService("")
I’ve heard about player removing disconnecting things, but just to make sure I do it anyways.
Then just delete your module and use game
. That already has all the most used services.
The type system used to not recognize when you did game.Players
and so on, but now it does. There is no benefit to doing it that way anymore.
It’s redundant.
I also do not recommend debouncing like this. A better practice is to use :Once()
like this:
local function debounce(event, call)
local function connection()
xpcall(call, warn) -- warns when an error occurs
event:Once(connection)
end
event:Once(connection)
end
debounce(example_btn.Activated, function()
-- do some stuff
task.wait(0.1)
end)
There are some cases where you have to do it differently, but usually that can be solved by designing systems around this concept.
here’s the module:
local services_module = {}
services_module.services = {
Players = game:GetService("Players"),
ws = game:GetService("Workspace"),
Lighting = game:GetService("Lighting"),
ReplicatedStorage = game:GetService("ReplicatedStorage"),
ServerScriptService = game:GetService("ServerScriptService"),
TeleportService = game:GetService("TeleportService"),
ServerStorage = game:GetService("ServerStorage"),
TweenService = game:GetService("TweenService"),
SoundService = game:GetService("SoundService"),
TextChatService = game:GetService("TextChatService"),
StarterGui = game:GetService("StarterGui"),
CollectionService = game:GetService("CollectionService"),
MarketplaceService = game:GetService("MarketplaceService"),
BadgeService = game:GetService("BadgeService"),
HttpService = game:GetService("HttpService"),
RunService = game:GetService("RunService")
}
return services_module
Yes, you don’t need this anymore.
And for this you can just use the built-in workspace
.