Hello delevopers! I’ve encoutering a problem where touched works for multiple time, i’ve tried to add a debounce system but i think it doesn’t work
local buttonPart = script.Parent
local debounce = false
local BASE_PRICE = 50
local PRICE_MULTIPLIER = 1.15
local function formatNumber(n)
local val = math.floor(tonumber(n) or 0)
local suffixes = {"", "K", "M", "B", "T", "Q", "Qi", "Sx"}
if val < 1000 then return tostring(val) end
local index = math.floor(math.log10(val) / 3)
if index >= #suffixes then index = #suffixes - 1 end
local shortValue = val / (10 ^ (index * 3))
return string.format("%.1f%s", shortValue, suffixes[index + 1]):gsub("%.0", "")
end
local info = buttonPart:WaitForChild("Info")
local container = info:WaitForChild("Container")
local textLabel = container:WaitForChild("T_Cost")
local function forceShorten()
local rawText = textLabel.Text
local numericValue = tonumber(rawText:match("%d+%.?%d*"))
if numericValue and numericValue >= 1000 then
local shortened = formatNumber(numericValue)
if textLabel.Text ~= shortened then
textLabel.Text = shortened
end
end
end
textLabel:GetPropertyChangedSignal("Text"):Connect(forceShorten)
buttonPart.Touched:Connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if player and not debounce then
debounce = true
local lstats = player:FindFirstChild("leaderstats")
local cash = lstats and lstats:FindFirstChild("Cash")
local stairs = player:FindFirstChild("StairsCount")
if cash and stairs then
local price = math.floor(BASE_PRICE * (PRICE_MULTIPLIER ^ stairs.Value))
if cash.Value >= price then
cash.Value -= price
stairs.Value += 1
end
end
task.wait(1.0)
debounce = false
end
end)
forceShorten()
Hi! I’m not sure exactly what you mean but just walking over the buttonPart seems to work fine in playtesting. Could you explain what the problem is with more detail?
Is there more than one script running? Didn’t test anything here, but that looks like it should work.
The debounce logic looks right anyways for one player at a time. How is this being touched? Are you walking on it, standing on it for a bit, then moving away?
buttonPart.Touched:Connect(function(hit)
if hit.Name ~= "HumanoidRootPart" then return end
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if player and not debounce then
debounce = true
local lstats = player:FindFirstChild("leaderstats")
local cash = lstats and lstats:FindFirstChild("Cash")
local stairs = player:FindFirstChild("StairsCount")
if cash and stairs then
local price = math.floor(BASE_PRICE * (PRICE_MULTIPLIER ^ stairs.Value))
if cash.Value >= price then
cash.Value -= price
stairs.Value += 1
end
end
task.wait(1.0)
debounce = false
end
end)
I turned off anchor on main part but still the same issue
The event is correct
I use it in my script
here is script now
local buttonPart = script.Parent
local BASE_PRICE = 50
local PRICE_MULTIPLIER = 1.15
local COOLDOWN = 1.0
local activeCycles = {}
local function formatNumber(n)
local val = math.floor(tonumber(n) or 0)
local suffixes = {"", "K", "M", "B", "T", "Q", "Qi", "Sx"}
if val < 1000 then return tostring(val) end
local index = math.floor(math.log10(val) / 3)
if index >= #suffixes then index = #suffixes - 1 end
local shortValue = val / (10 ^ (index * 3))
return string.format("%.1f%s", shortValue, suffixes[index + 1]):gsub("%.0", "")
end
local info = buttonPart:WaitForChild("Info")
local container = info:WaitForChild("Container")
local textLabel = container:WaitForChild("T_Cost")
local function forceShorten()
local rawText = textLabel.Text
local numericValue = tonumber(rawText:match("%d+%.?%d*"))
if numericValue and numericValue >= 1000 then
local shortened = formatNumber(numericValue)
if textLabel.Text ~= shortened then
textLabel.Text = shortened
end
end
end
textLabel:GetPropertyChangedSignal("Text"):Connect(forceShorten)
buttonPart.Touched:Connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player or activeCycles[player.UserId] then return end
activeCycles[player.UserId] = true
task.spawn(function()
while true do
local isStillOn = false
local parts = workspace:GetPartsInPart(buttonPart)
for _, p in pairs(parts) do
if p:IsDescendantOf(player.Character) then
isStillOn = true
break
end
end
if not isStillOn then break end
local lstats = player:FindFirstChild("leaderstats")
local cash = lstats and lstats:FindFirstChild("Cash")
local stairs = player:FindFirstChild("StairsCount")
if cash and stairs then
local price = math.floor(BASE_PRICE * (PRICE_MULTIPLIER ^ stairs.Value))
if cash.Value >= price then
cash.Value -= price
stairs.Value += 1
end
end
task.wait(COOLDOWN)
end
task.delay(0.1, function()
activeCycles[player.UserId] = nil
end)
end)
end)
forceShorten()
Keep in mind the touched part, as a trigger, will fire when touched as you walk onto it at first.
It will not fire if you’re standing on it and not moving. It will again fire when you start to move.
In your case, there is a one second debounce after any touch is fired, it will not fire again at all.
That can be a bit misleading.
I analyzed your script carefully, and I’ve came to the conclusion nothing seems out of the ordinary, only plausible explanation I can think of is that you have multiple scripts of the same kind running. Please let us know if you found a solution and tell us what went wrong!
I’ve setup the same button system myself, with the .Touched event and the debounce, and I’ve play tested it extensively. I even added debug prints, tried different debounce implementations, and even used your character model. In isolation everything works fine, only one purchase triggers per step, exactly as expected.
Given that you’re still seeing multiple triggers, the issue may not be the script itself but one of these structural things in the game:
Duplicate scripts - make sure there aren’t multiple copies of the purchase script anywhere.
Multiple overlapping parts - check the button for invisible or cloned parts that might also fire .Touched
Based on my testing, the script logic itself works perfectly, any duplicate triggers in this case may be caused by environmental factors. For a more reliable system, I recommend filtering for the HumanoidRootPart and using a per-player debounce.
You were right, the problem was in my core server script, basically it’s listening to buyEvent.OnServerEvent and gives +1 step
and my button script just changes cash.Value and stairs.Value at touch.
It’s my first serious project, so I guess mistakes like these are bound to happen. Thanks everyone for help!
For some reason they swapped of the signal behavior to deferred by default. That messes with lot of things it seems. Setting it back to default in the Workspace fixes a lot of theses sort of issues.