So I want to create a server script that manages multiple buttons instead of a unique script for each button.
I’ve tried to use CollectionService to tag every button, but it results in every button acting as if it was touched simultaneously. (Tagged every button with “Button”, looped through all tagged buttons to connect them to Touched event)
Is there a better way to do this, preferably without something like OOP?
EDIT: Code as requested
local CollectionService = game:GetService("CollectionService")
local LargeNumbers = require(game:GetService("ReplicatedStorage"):WaitForChild("LargeNumbers"))
local Connections = {}
local function Purchase(Player, Config)
print('test')
end
---
local function InstanceAdded(ins)
if ins:IsA("BasePart") and ins:FindFirstChild("Configuration") then
Connections[ins] = ins.Touched:Connect(Purchase)
print(Connections[ins], #Connections)
end
end
local function InstanceRemoved(ins)
if Connections[ins] then Connections[ins]:Disconnect() Connections[ins] = nil end
end
CollectionService:GetInstanceAddedSignal("Button"):Connect(InstanceAdded)
for i, v in pairs(CollectionService:GetTagged("Button")) do
InstanceAdded(v)
end
---
for i, v in pairs(workspace:GetDescendants()) do
if v:IsA("BasePart") and v:FindFirstChild("Configuration") then
CollectionService:AddTag(v, "Button")
end
end
---
wait(3)
print("Made " .. #Connections .. " connections")
Interestingly enough, #Connections print 0.
Output is initially “test x9” (there are 9 buttons), and significantly increases when player is near/touching any button
Oh, duh. I should have figured, lol.
Was just a debug to test the amount of connections. Every button is connected but they all seem to function as a single unit compared to individually
In case you need to know ‘which particular part/object was touched’ in your general method, then I suggest using an anonymous function, so it can “transfer” the knowledge of the part/object together with what is touching it:
Connections[ins] = ins.Touched:Connect(
function(other)
Purchase(ins, other)
end
)
And then change your general Purchase method to something like:
local Players = game:GetService("Players")
local function Purchase(button, otherPart)
-- Make sure this `button` actually has a configuration
local config = button and button:FindFirstChild("Configuration")
if nil ~= config then
-- Find player that touched it
local otherModel = otherPart and otherPart:FindFirstAncestorWhichIsA("Model")
local player = otherModel and Players:GetPlayerFromCharacter(otherModel)
if nil ~= player then
print("Player ",player," touched ",button)
end
end
end
You should definitively also add some kind of debounce / ‘stop-too-many-touch-events’ functionality, to avoid getting the Touched-event fired continuously, when each part (that a player-character-humanoid consist of) is (re-) touching the part/object.