Im trying to make a module that will handle all these parts when they are touched

Hey, I want to get all parts in workspace that are of the name FloorCreak So I did this;

local function Get_CreakParts()
	for _, v in pairs(workspace:GetDescendants()) do
		if v:IsA("Part") and v.Name =="FloorCreak" then
			Part = v
			print(v)
			return Part
		end
	end
end

but it only gets one random part in workspace of that name how can I get them all then I want to do

Get_CreakParts().Touched:Connect(function(hit)
	local timer = math.random(30, 100)
	local character = hit.Parent
	local player = game.Players:GetPlayerFromCharacter(character)

	if not check then
		check = true
		local creaks = {Get_CreakParts().Floor_Creak_SFX1, Get_CreakParts().Floor_Creak_SFX2, Get_CreakParts().Floor_Creak_SFX3}
		local selectedCreak = math.random(1, #creaks)

		if selectedCreak == 1 then
			Get_CreakParts().Floor_Creak_SFX1:Play()
		elseif selectedCreak == 2 then
			Get_CreakParts().Floor_Creak_SFX2:Play()
		elseif selectedCreak == 3 then
			Get_CreakParts().Floor_Creak_SFX3:Play()
		end

		wait(timer)
		check = false
	end
end)

this will play a noise when one of those creak parts are touched.

it only runs once because you are returning the part, which is this line

return Part

But is there some way I can get all of the floor creak parts in workspace?

1 Like
for _, v in pairs(workspace:GetDescendants()) do
	if v:IsA("Part") and v.Name =="FloorCreak" then
		v.Touched:Connect(function(hit)
			local timer = math.random(30, 100)
			local character = hit.Parent
			local player = game.Players:GetPlayerFromCharacter(character)

			if not check then
				check = true
				local creaks = {v.Floor_Creak_SFX1, v.Floor_Creak_SFX2, v.Floor_Creak_SFX3}
				local selectedCreak = math.random(1, #creaks)
				creaks[selectedCreak]:Play()
				wait(timer)
				check = false
			end
		end)
	end
end

this should work fine, I don’t see why you need it to be a module
EDIT: I had to fix something

1 Like

One very important feature of functions is that returning something from a function also leaves the function.

Doing something like this

local function f()
	while true do
		return "value"
	end
end

print(f()) --> "value"

doesn’t return an infinite collection of strings named “value”. It only returns one string, because it exited the function on the first iteration through the loop. The same applies for a for loop.

What you would really want is to return an array of parts outside of the loop.

local function Get_CreakParts()
	local result = {}

	for _, Part in pairs(workspace:GetDescendants()) do
		if Part:IsA("Part") and Part.Name == "FloorCreak" then
			table.insert(result, Part)
		end
	end

	return result
end

And from there, you can use another for loop to connect a function to each part’s Touched event.

for _, CreakPart in ipairs(Get_CreakParts()) do

	CreakPart.Touched:Connect(function(hit)
		local timer = math.random(30, 100)
		local character = hit.Parent
		local player = game.Players:GetPlayerFromCharacter(character)
	
		if not check then
			check = true
			local creaks = {CreakPart.Floor_Creak_SFX1, CreakPart.Floor_Creak_SFX2, CreakPart.Floor_Creak_SFX3}
			local selectedCreak = math.random(1, #creaks)

			creaks[selectedCreak]:Play()

			wait(timer)
			check = false
		end
	end)

end

@D0RYU’s code snippet works as well as what I wrote above, so you can use mine or his interchangeably.

The only suggestion I can give is using CollectionService to get all CreakParts instead of name matching. You can use the Tag Editor plugin to do this from Studio edit mode.

-- example usage of CollectionService
local CollectionService = game:GetService("CollectionService")

-- ...

local function Get_CreakParts()
	return CollectionService:GetTagged("CreakPart") -- simple!
end

Alright this is very interesting I am what of an intermediate scripter and I’ve never heard of this collection service so ill make sure to check it out!

1 Like