How to get only one child from i, v in pairs()?

Hello,
I was wondering if there was a way to get only one specific child from a table?

For example,


If a player approaches one of the two doors (the two doors are in a folder), it will only open up that one door.

Server Script:

nearEvent.OnServerEvent:Connect(function(plr)
	for i, door in pairs(doors:GetChildren()) do
	local dist = (plr.Character:FindFirstChild("Torso").Position - door[i]:FindFirstChildOfClass("Model").MainPart.Position).magnitude
	
		if dist < setting.radius and deb2 == false then
			deb2 = true
			print("Gui Fade In")
			guiFadeIn()
			setting.deb = true
			deb = false
		end
	
		if dist > setting.radius and deb == false then
			deb = true
			print("Gui Fade Out")
			guiFade()
			setting.deb = false
			deb2 = false
		end
	end
end)

Local Script:

	for i, door in pairs(doors:GetChildren()) do
		local dist = (player.Character:FindFirstChild("Torso").Position - door[i]:FindFirstChildOfClass("Model").MainPart.Position).magnitude
		if dist < setting.radius or dist > setting.radius then
			nearEvent:FireServer()
		end
	end

You do Table[Number]

So for example if you wanted to select only the first child you do Table[1]

1 Like

I tried that but I get an error showing “1 is not a valid member of Folder”

Been stuck on this for a while now, tried looking up tutorials, am I missing something?

Send us your code first, so we can actually see what you’re doing wrong
please
edit : is setting.Radius from a module?

1 Like

Edited it, should be there now. I might be doing this completely wrong, been getting a headache from all this

Yeah, setting.radius is from a module

local setting = {
	radius = 12,	-- Distance the player must be near the door for them to interact with it (studs)
	camSpeed = 0.7,	-- Speed of the camera zooming into the doors
	doorSpeed = 1.25,	-- Speed of the doors opening
	doorOpenStyle = Enum.EasingStyle.Sine, -- Refer to this link if you want to change opening/easing styles (https://developer.roblox.com/en-us/api-reference/enum/EasingStyle)
	doorSound = "157167203",	-- Sound the doors make when opening
}
	
	--[[ Instructions for pretty much everything --
		
		* Keep everything in a folder inside of the 'doors' folder
				
		* Make sure to weld everything you want to move/animate, to the 'hingePart'. If you don't already,
			here's a link to a plugin that automatically welds everything to one part. (https://www.roblox.com/library/148570182/Weld-Plugin)
		
		* Feel free to move the 'begDest', 'camPart', 'endDest', 'guiPart', 'moveToPart' to wherever you want, as long as it's inside of the folder.
		
	]]

return setting

It’s for a commission so I provided some instructions for the person (saying this incase someone thinks its a free model)

You can pass the door so server knows which door it was.

–client
nearEvent:FireServer(door)

–server
nearEvent.OnServerEvent:Connect(function(plr, door)

end)

1 Like

Folder[1] isn’t going to work and will say “1 is not a valid member of folder”.
You need to do Folder:GetChildren()[1] instead.

6 Likes

Minor unrelated things regarding the code but if you’re going to index with . right after anyways don’t use FindFirstChild, since with or without you will error.

Prefer player.Character.Torso.Position to player.Character:FindFirstChild("Torso").Position, the latter is more typing and operations for worse code.

Also for tables you get from GetChildren, always use ipairs over pairs. GetChildren returns an array which is to be iterated with the array iterator ipairs.

Since it returns an array, it also solves your problem as you can directly access it for any element you want using my_children[n] style.

3 Likes

You have to use :GetChildren() to create a table of the folder’s children before then using Table[1] thats the cause of your error.

I also noticed in your code that you are doing this but your doing it with just the door in the for loop when you should be doing doors[i]

2 Likes

Why not just break the loop after you’ve run it? Seems a bit simpler if you’re looking to do it with the loop.

2 Likes

You’re overthinking it.

local currentDoor
for i, door in pairs(doors:GetChildren()) do 
    currentDoor = door
    -- door is the child, it's not anything else.
end

If you name the doors like “door1” “door2”. You can easily pass through a string with the remote Event. Like this

local:

NearEvent:FireServer(door.Name)

server:

nearEvent.OnServerEvent:Connect(function(plr, doorName)
doors:FindFirstChild(doorName) -- Through this you get the door that was 'touched' and you can now do something with it.
end)

A way you can do this is to create a table of all available doors to interact with and then insert them into an array. You can then sort this table based on the distance the character is to the door and then return the first indice of the array, which will be the door closest to the player.

1 Like

If u wanna search for specific child just use Instance:FindFirstChild() or Instance:WaitForChild()
in this way you don’t need to get all children when u need only one
Edit. you can use it even when you already need all children

Look at the topic again. The specific use case is to get one item out of a table of them. The table happens to be one of doors and OP only wants the nearest one to open. In a streamlined structure, this won’t be a viable solution because it’ll only get the first child matching a specific name. It doesn’t allow you to filter results and pick the one that best matches.

oh I meant something like getting name of nearest door and then finding it (my fault bec I didn’t specified)
I’m gonna try making it

Just adding, if anyone searches this thread in the future, actually wanting “one thing from a table”, the call you’re looking for is:

local key, value = next(myTable),

Which will give you exactly one key/value pair from the table without iterating it, even if it’s a table of arbitrary key/values and not an array.

ok maybe I was wrong with findfirstchild I mean it could be but it would be longer so I made this script (ye it uses for loop)

`game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(char)
	local area = Instance.new("Part", workspace) -- add new part that is area around player
	area.Name = player.Name .. "'sArea"
	area.Size = Vector3.new(10,0.1,10) -- Size of area in studs
	area.Transparency = 1 -- transparency
	area.CanCollide = false -- cancollide to false
	area.Anchored = true -- make it anchored
	while wait(0.0001) do -- infinite loop with delay 
		area.CFrame = char.HumanoidRootPart.CFrame -- make area be where you
		for _,v in pairs(area:GetTouchingParts()) do 
			-- do something
		end
	end
end)

end)`
That should work

I know this topic is rather old, however, I think the fix for it would be to add break inside the if statements scope.
Why I think this would fix the problem you have which is that all the doors are opening, is because it’s not gonna continue the loop if it has found the door.
Now you already have the specific door child you want, as it is defined in the for key, value loop.

The fixed code would be

nearEvent.OnServerEvent:Connect(function(plr)
	for i, door in pairs(doors:GetChildren()) do
	local dist = (plr.Character:FindFirstChild("Torso").Position - door[i]:FindFirstChildOfClass("Model").MainPart.Position).magnitude
	
		if dist < setting.radius and deb2 == false then
			deb2 = true
			print("Gui Fade In")
			guiFadeIn()
			setting.deb = true
			deb = false
			break
		end
	
		if dist > setting.radius and deb == false then
			deb = true
			print("Gui Fade Out")
			guiFade()
			setting.deb = false
			deb2 = false
			break
		end
	end
end)
2 Likes