Need Help with GetChildren

I am writing a code for a GUI that gives you clothing options. The GUI-related scripting works just fine, but it only works on one of the parts that trigger the GUI. I put all of the parts in a folder and tried using GetChildren, but it still only works for the first child.

Here's the script
local Mouse = Player:GetMouse()

local UIS = game:GetService("UserInputService")

local peeking = false

for i,v in pairs(workspace.Closets:GetChildren()) do

	UIS.InputBegan:Connect(function(input)
		if input.KeyCode == Enum.KeyCode.E then
			if Mouse.Target == v then
				Player.PlayerGui.ClosetHandler.Change.Visible = true
			end
		end
	end)
	
	Mouse.Button1Down:Connect(function()
		if Mouse.Target == v then
			Player.PlayerGui.ClosetHandler.Change.Visible = true
		end
	end)
	
	
	local peeking = false
	
	while true do
		wait()
		if Mouse.Target == v then
			if peeking == false then
				peeking = true
				local bClone = script.Parent.Button:Clone()
				bClone.Parent = workspace.CurrentCamera
				bClone.Adornee = v
				bClone.TextLabel.Visible = true
			end
		else
			if peeking == true then
				if workspace.CurrentCamera:FindFirstChild("Button") then
					workspace.CurrentCamera.Button:remove()
					peeking = false
				end
			end
		end
	end

end

I think it may have to do with the lines using v (ex: if Mouse.Target == v then) but I am not sure.

The reason this is happening is because of your while loop. The program will not continue onto the next item in the for loop because it is stuck executing the code in the while loop. To get around this, you can enclose the while loop in the spawn() function. This starts another thread that executes alongside your existing thread, allowing the existing thread to continue onto the next item in the loop. In your case, you would write it like so:

spawn(function()
    while true do
	    wait()
    	if Mouse.Target == v then
	    	if peeking == false then
	    		peeking = true
	    		local bClone = script.Parent.Button:Clone()
	    		bClone.Parent = workspace.CurrentCamera
	    		bClone.Adornee = v
	    		bClone.TextLabel.Visible = true
	    	end
    	else
    		if peeking == true then
	    		if workspace.CurrentCamera:FindFirstChild("Button") then
	    			workspace.CurrentCamera.Button:remove()
		    		peeking = false
		    	end
	    	end
	    end
	end
end)

Keep in mind, however, you MUST include a way for this loop to terminate after you’re done using it. Somewhere inside that loop, check to see if the loop still needs to be running. If not, then return the function so that the loop stops. Otherwise, you’ll end up opening hundreds if not thousands of duplicate threads which will eventually crash your game.

This is just one of many ways to solve this problem and is my preferred method.

1 Like

Thanks! That works great! One last question though. Is there any way for me to verify that I’ve terminated the loop? I could do print "Terminated" with Output, but don’t know what that would look like when it properly terminates.

1 Like

As long as you have a return statement inside the loop, it effectively terminates the function that we’ve passed through spawn(). Otherwise, you could include a print() statement inside of the loop to know that you’ve terminated it.