How to connect multiple eventListeners to the results from a for loop

Okay I have an issue
Now I know how to use a for loop to connect each iterated instance to a function. Just in case I’m wording that strangely, here’s what I mean:

local function executor()
	local lighting = script.Parent
	for i, c in lighting:GetChildren() do
		local prox = c
		c.Triggered:Connect(function()
			print("Prox triggered")
		end)
	end
end
wait(1)
executor()

I made this up as an example of a nifty lua feature that allows you to connect to multiple ProximityPrompts Triggered events(this is just one application of this feature)

That script will work fine

However, I have a problem, I need to be able to use that function far more than once. So I need to use multiple eventListners to connect to a function instead of one. So I did this:


local function executor()
	local lighting = script.Parent
	for i, c in lighting:GetChildren() do
		local prox = c
		local function printProx()
			print("Prox triggered")
		end
		wait(0.1)
		prox.Triggered:Connect(printProx)
		lighting:GetPropertyChangedSignal("Name"):Connect(printProx)
	end
end
wait(1)
executor()

But the issue is the code above stops when it finds ONE match for the for loop. That would work fine if there was one ProximimityPrompt, but there are like 100+. What have I done wrong and how can I fix it?

2 Likes

Just remove the yielding code within the loop

which does nothing.

You should end up with

local function executor()
	local lighting = script.Parent
	for i, c in lighting:GetChildren() do
		local prox = c
		local function printProx()
			print("Prox triggered")
		end
		prox.Triggered:Connect(printProx)
		lighting:GetPropertyChangedSignal("Name"):Connect(printProx)
	end
end
wait(1)
executor()

Well I should have put the wait(0.1) right after

for more clarity instead of where I did place it, but either way it’s for performance so that if I have 1000 chilren I don’t get a script timeout

Either way the script still doesn’t work after removing it; do you see any other issues with the code?

1 Like

The 0.1 delay is still way too long you should opt with using task.wait() on its own which defaults to a ~0.017 second delay.

You’re right there, I made it like that because the script is an example script, but I get your point

Sadly though this is not what’s causing the issue

You have decent scripting experience, if you wanted to do a for loop which connected to multiple iterated instance’s events, how would you do that?

I’d need more context because this code looks like it should work.

Alright, once I get back home to my PC I’ll send some screenshots that will make things clearer

Since you have multiple ProximityPrompts, you can use ProximityPromptService.PromptTriggered.

local ProximityPromptService = game:GetService("ProximityPromptService")

ProximityPromptService.PromptTriggered:Connect(function(prompt, player)
  print(`{player.Name} triggered prompt {prompt:GetFullName()}`)
end)

Also, please note that script.Parent:GetChildren() will return an array with { script, ... }, so you should actually use an if statement if c:IsA("ProximityPrompt") then ... end

Wow, I was completely unaware that even existed, I’ll use that when I get to my PC and see if it works

Okay, thank you so much I appreciate this tip; it’s helpful to know a way to connect to all Prox’s in the game. However, it isn’t exactly a complete solution to my problem, because it connects to every proximityprompt in the game which isn’t performant, and on top of that I still can’t execute the behavior outlined in script 2

I need to connect to a local function within a for loop for every single child in this scenario using more methods than just Prox.Triggered

Yeah in the real script I do check if it’s a prox

If you find a solution let me know

Okay here is a random script a wrote a while ago

local floor = script.Parent

wait(10)
for i, v in floor:GetDescendants() do
	if v:IsA("ProximityPrompt") then
		v.Triggered:Connect(function()
			if v.Name == "HallPrompt" then
				-- the door
				local prox = v
				local green = prox.Parent.Parent.Green
				local red = prox.Parent.Parent.Red
				local Storage = prox.Parent.Parent.Parent
				local In = Storage.Orange.In.Union
				local Out = Storage.Orange.Out.Union
				local rollup = Storage.Orange.RollUp
				local update = Storage.oclosed
				wait(0.2)
				if In.Transparency == 0 then
					green.Material = "Neon" -- door opened
					green.Color = Color3.fromRGB(33, 243, 22)
					green.Massless = false
					red.Material = "Glass"
					red.Color = Color3.fromRGB(153, 0, 74)
					In.Transparency = 1
					In.CanCollide = false
					Out.Transparency = 1
					Out.CanCollide = false
					prox.ObjectText = "Status: Open"
					rollup.Transparency = 0
					update.TextScaled = true
					In.creak:Play()
				else
					green.Material = "Glass" -- door closed
					green.Color = Color3.fromRGB(0, 138, 99)
					green.Massless = true
					red.Material = "Neon"
					red.Color = Color3.fromRGB(186, 64, 8)
					In.Transparency = 0
					In.CanCollide = true
					Out.Transparency = 0
					Out.CanCollide = true
					prox.ObjectText = "Status: Closed"
					rollup.Transparency = 1
					update.TextScaled = false
					In.bang:Play()
				end
				-- the arrows
				local useprox = v.Parent.HallPrompt
				local Storage = useprox.Parent.Parent.Parent
				local needs = Storage["Inside Toggle"]
				local flat = needs.Flat
				local prox = flat.InsidePrompt
				local green = needs.Green
				local red = needs.Red
				local In = Storage.Orange.In.Union
				wait(0.5)
				if In.Transparency == 1 then
					green.Material = "Neon" -- door opened
					green.Color = Color3.fromRGB(33, 243, 22)
					green.Massless = false
					red.Material = "Glass"
					red.Color = Color3.fromRGB(153, 0, 74)
					prox.ObjectText = "Status: Open"
				else
					if In.Transparency == 0 then
						green.Material = "Glass" -- door closed
						green.Color = Color3.fromRGB(0, 138, 99)
						green.Massless = true
						red.Material = "Neon"
						red.Color = Color3.fromRGB(186, 64, 8)
						prox.ObjectText = "Status: Closed"
					end
				end
			elseif v.Name == "InsidePrompt" then
				local prox = v
				local green = prox.Parent.Parent.Green
				local red = prox.Parent.Parent.Red
				local Storage = prox.Parent.Parent.Parent
				local In = Storage.Orange.In.Union
				local Out = Storage.Orange.Out.Union
				local rollup = Storage.Orange.RollUp
				local update = Storage.oclosed
				wait(0.2)
				if In.Transparency == 0 then
					green.Material = "Neon" -- door opened
					green.Color = Color3.fromRGB(33, 243, 22)
					green.Massless = false
					red.Material = "Glass"
					red.Color = Color3.fromRGB(153, 0, 74)
					In.Transparency = 1
					In.CanCollide = false
					Out.Transparency = 1
					Out.CanCollide = false
					prox.ObjectText = "Status: Open"
					rollup.Transparency = 0
					update.TextScaled = true
					In.creak:Play()
				else
					green.Material = "Glass" -- door closed
					green.Color = Color3.fromRGB(0, 138, 99)
					green.Massless = true
					red.Material = "Neon"
					red.Color = Color3.fromRGB(186, 64, 8)
					In.Transparency = 0
					In.CanCollide = true
					Out.Transparency = 0
					Out.CanCollide = true
					prox.ObjectText = "Status: Closed"
					rollup.Transparency = 1
					update.TextScaled = false
					In.bang:Play()
				end
				-- the arrows
				local useprox = v.Parent.InsidePrompt
				local Storage = useprox.Parent.Parent.Parent
				local needs = Storage["Hallway Toggle"]
				local flat = needs.Flat
				local prox = flat.HallPrompt
				local green = needs.Green
				local red = needs.Red
				local In = Storage.Orange.In.Union
				wait(0.5)
				if In.Transparency == 1 then
					green.Material = "Neon" -- door opened
					green.Color = Color3.fromRGB(33, 243, 22)
					green.Massless = false
					red.Material = "Glass"
					red.Color = Color3.fromRGB(153, 0, 74)
					prox.ObjectText = "Status: Open"
				else
					if In.Transparency == 0 then
						green.Material = "Glass" -- door closed
						green.Color = Color3.fromRGB(0, 138, 99)
						green.Massless = true
						red.Material = "Neon"
						red.Color = Color3.fromRGB(186, 64, 8)
						prox.ObjectText = "Status: Closed"
					end
				end
			elseif v.Name == "OuterPrompt" then
				local prox = v
				local green = prox.Parent.Parent.Green
				local red = prox.Parent.Parent.Red
				local Storage = prox.Parent.Parent.Parent
				local In = Storage.Open.In.Union
				local Out = Storage.Open.Out.Union
				local rollup = Storage.Open.RollUp
				wait(0.2)
				if In.Transparency == 0 then
					green.Material = "Neon" -- door opened
					green.Color = Color3.fromRGB(33, 243, 22)
					green.Massless = false
					red.Material = "Glass"
					red.Color = Color3.fromRGB(153, 0, 74)
					In.Transparency = 1
					In.CanCollide = false
					Out.Transparency = 1
					Out.CanCollide = false
					prox.ObjectText = "Status: Open"
					rollup.Transparency = 0
					In.creak:Play()
				else
					green.Material = "Glass" -- door closed
					green.Color = Color3.fromRGB(0, 138, 99)
					green.Massless = true
					red.Material = "Neon"
					red.Color = Color3.fromRGB(186, 64, 8)
					In.Transparency = 0
					In.CanCollide = true
					Out.Transparency = 0
					Out.CanCollide = true
					prox.ObjectText = "Status: Closed"
					rollup.Transparency = 1
					In.bang:Play()
				end
			end
		end)
	end
end

So previously every proximityprompt needed its own script, so I had 200 scripts saying the same thing. Then I decided to let one script do all the work by using a for loop, and it worked fine because I connected each iterated instance to the triggered event. But what if I wanted the function to activate when a bool changed from true to false? Then I would need the function to connect to both the Triggered event and Bool.Changed event.

So the issue I’m having is this method doesn’t work in a for loop for some reason

@bytesleuth
and @technology1111 I’m so sorry, there was another problem in the code

local lighting = hoodchild:FindFirstChild("Lighting")

that basically halted the code after that line so it turns out the method I was using was correct

Just like @bytesleuth claimed. Thank you for your time and effort!

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