I have multiple elevators in a building. Each floor has 3 elevators, and each elevator is it’s own model. 6 floors with 3 elevators on each floor means 18 elevator models. Inside each model is a button to open the elevator doors (inside this button is a ClickDetector)
The problem I am facing is having 1 script handle all of these elevators. Atm I have 16 scripts inside each model. This is becomming a real hassle, as if I want to add more code to it later on, or something breaks, then I have to go and make the changes to all 16 scripts.
local model = script.Parent
local button = model.Button
local clickDetector = button.ClickDetector
local doorLeft = model.DoorLeft
local doorRight = model.DoorRight
local opened = false
local debounce = false
clickDetector.MouseClick:Connect(function()
if debounce then return end
debounce = true
if opened then
opened = false
for i = 1, 20 do
doorLeft.CFrame = doorLeft.CFrame + Vector3.new(0, 0, 0.2)
doorRight.CFrame = doorRight.CFrame + Vector3.new(0, 0, -0.2)
wait()
end
else
opened = true
for i = 1, 20 do
doorLeft.CFrame = doorLeft.CFrame + Vector3.new(0, 0, -0.2)
doorRight.CFrame = doorRight.CFrame + Vector3.new(0, 0, 0.2)
wait()
end
end
debounce = false
end)
This is my current code. Nothing broken with it, but just don’t know how to get the script to reference every single elevator model
There are multiple ways to do this, simplest being, put them all in a folder or whatsoever and loop over it.
local folder = pathtofolder
for _,v in pairs(folder:GetChildren()) do
local model = v
local button = model.Button
local clickDetector = button.ClickDetector
local doorLeft = model.DoorLeft
local doorRight = model.DoorRight
local opened = false
local debounce = false
clickDetector.MouseClick:Connect(function()
if debounce then return end
debounce = true
if opened then
opened = false
for i = 1, 20 do
doorLeft.CFrame = doorLeft.CFrame + Vector3.new(0, 0, 0.2)
doorRight.CFrame = doorRight.CFrame + Vector3.new(0, 0, -0.2)
wait()
end
else
opened = true
for i = 1, 20 do
doorLeft.CFrame = doorLeft.CFrame + Vector3.new(0, 0, -0.2)
doorRight.CFrame = doorRight.CFrame + Vector3.new(0, 0, 0.2)
wait()
end
end
debounce = false
end)
end
From what @Nitefal mentioned, you could additionally put a tag using CollectionService and put in the same loop as what Nitefal mentioned. To make sure the game has loaded, use a :GetPropertyChangedSignal event on game.Loaded to see if the game make sure the game has loaded so you don’t miss out on a model.
Assuming all the tags have been set offline, there’s no reason why CollectionService::GetTagged would miss an instance. If instances are dynamically added/removed, GetInstanceAddedSignal and GetInstanceRemovedSignal can be used to keep track of em.
@op: Should you choose to use the CollectionService instead…
local CollectionAPI = game:GetService("CollectionService")
local CollectionTag = "Elevator"
local CreatedSignal = CollectionAPI:GetInstanceAddedSignal(CollectionTag)
local DeletedSignal = CollectionAPI:GetInstanceRemovedSignal(CollectionTag)
local GetAllTagged = CollectionAPI:GetTagged(CollectionTag)
local Elevators do
Elevators = {}
function Operate(elevator)
print(elevator:GetFullName()) --// elevator code
end
local function tagAdded(instance)
--// new tag dynamically added
Elevators[#Elevators+1] = Operate(instance)
end
local function tagRemoved(instance)
if Elevators[instance] then
Elevators[instance] = nil;
end
end
for i = 1, #GetAllTagged do
tagAdded((GetAllTagged[i]))
end
CreatedSignal:Connect(tagAdded)
DeletedSignal:Connect(tagRemoved)
end
Every edit to the Operate function would apply to all models/instances with the tag Elevator. I don’t know if there’s been an official one since, but this tag editor can be used to visualize and properly assign tags in Studio.
Right - yeah I suppose. That can still be easily managed though with CollectionAPI::GetInstanceAddedSignal, assuming, like you said, that the script itself isn’t in a position where it might be slow to load or replicate.
Works getting new problems no however if I have more buttons inside the elevator
local elevators = workspace.Elevators
function open(doorLeft, doorRight)
for i = 1, 20 do
doorLeft.CFrame = doorLeft.CFrame + Vector3.new(0, 0, -0.2)
doorRight.CFrame = doorRight.CFrame + Vector3.new(0, 0, 0.2)
wait()
end
wait(2)
for i = 1, 20 do
doorLeft.CFrame = doorLeft.CFrame + Vector3.new(0, 0, 0.2)
doorRight.CFrame = doorRight.CFrame + Vector3.new(0, 0, -0.2)
wait()
end
end
for _, elevator in pairs(elevators:GetChildren()) do
local button = elevator.Button
local openDetector = button.ClickDetector
local doorLeft = elevator.DoorLeft
local doorRight = elevator.DoorRight
local debounce = false
print(1)
openDetector.MouseClick:Connect(function()
print(2)
if debounce then return end
debounce = true
open(doorLeft, doorRight)
debounce = false
end)
for _, buttons in pairs(elevator:GetChildren()) do
if buttons:FindFirstChild('ClickDetector') and buttons.Name ~= 'Button' then
openDetector.MouseClick:Connect(function()
if debounce then return end
debounce = true
print('Going up to', buttons.Name)
wait(2)
debounce = false
end)
end
end
end
What this is trying to do is openDetector is the the ClickDetector that’s inside the button that opens the elevator. However, the elevator also has buttons inside it, which are used to go up and down floors. That’s what the second for loop is for. When I click the open button however, it prints ‘Going up to 6’ and then ‘2’. However, when I click the open button, it should not be getting access to the second function, as I have
if buttons:FindFirstChild('ClickDetector') and buttons.Name ~= 'Button' then
Which finds the other buttons, but does not include the open door button