First Post - Rookie Question: Call Same Function Touching Different Parts

Hi folks!

New member that is thrilled to be able to engage with the community finally. My first post will expose how new I am and how much I have to learn. At the risk of having my Roblox Dev card revoked, here goes:

In my game you earn points for jumping, and can earn higher points if you jump over certain terrain. I have parts over challenging terrain called Terrain Multipliers. I plan to have many of these multiplier parts sprinkled around the map. My system works fine if I define each part with a unique name, then have a unique touched event trigger a function to change the multiplier. I’m sure this is far from optimal. I’m trying to find the correct solution, where I simply have the function to change the multiplier only defined once, and it is called any time you touch one of the many different multipliers on the map.

TL;DR: I am trying to set player.TerrainMultiplier.Value to 2 when the player touches any of three different parts on the map: TerrMult2x001, TerrMult2x002 or TerrMult2x003, all without writing out the function three times.

local TerrainX2 = game.Workspace.TerrainMultipliers.TerrMult2x001
local TerrainX2 = game.Workspace.TerrainMultipliers.TerrMult2x002
local TerrainX2 = game.Workspace.TerrainMultipliers.TerrMult2x003
--------------------------------------------------
db = false
TerrainX2.Touched:Connect(function(hit)
   print("Player Touched Terrain X2 Part")
      if hit.Parent:FindFirstChild("Humanoid") then
         local player = game.Players:GetPlayerFromCharacter(hit.Parent)
         if db == false then
             db = true
             player.TerrainMultiplier.Value = 2
             wait(1)
             db = false
             end
        end
end)

Thanks much.
3 Likes

Something I quickly wrote up. This would do the trick, and it’s a little more compact than your current one. Put all the things from your function (provided in the OP) in your part.Touched() event in the loop.

local Parts = {game.Workspace.Part1, game.Workspace.Part2}

for _, part in pairs(Parts) do
	part.Touched:Connect(function()
		print(part.Name)
	end)
end
2 Likes

If there are a lot of parts you want to connect this function to, you could go to the specific folder / model where all those parts are and loop through them all with GetChildren()

for i, part in pairs(game.Workspace.terrainPartsFolder:GetChildren()) do
    part.Touched:Connect(function(hit)
    if hit.Parent:FindFirstChild("Humanoid") then
         local player = game.Players:GetPlayerFromCharacter(hit.Parent)
         if player then
              --do something with the terrainMultiplier.Value
         end
    end
end
2 Likes

Thank you so much. I’m floored how folks are so willing and able to help here. I think this is my solution. @Polyheximal - Your code worked perfectly, and drastically cut down my huge script with the same function pasted over and over.

It turns out I’ll likely have well over 100 of these multipliers, so the folder/GetChildren solution should work. A silly question that I’ll test on my own, but will this work if the parts in terrainPartsFolder have the same name, or do they need to be unique?

Thank you both so much.

2 Likes

I’m pretty sure it will work if they have the same name, regardless. In @speeddecoolste’s code, it iterates through the objects in the folder’s children (in this case, the multiplier parts) and then checks if that part was touched. It doesn’t check for the name, but if you wanted to add checks for part names for certain things (e.g. certain multipliers with names like MultiplierX2 gives x2 and MultiplierX5 gives x5) would need to be named differently to each other to differentiate the multiplier value. However, if that isn’t the case, then they can all be the same name.

3 Likes

SUCCESS! Thank you both so much. Yes, the looping through folder with GetChildren works perfectly with same-name parts, which is great because now I can just duplicate and sprinkle the parts around the map easily. I simply made separate folders for the X2 and X3 and X4…and so on…multipliers and it works flawlessly.

3 Likes

If you do prefer to use one script with 1 loop instead of having multiple scripts you could make 1 big folder with multiple folders inside of it, and loop through them all with GetDescendants().

for i, part in pairs(game.Workspace.allTerrainPartsFolders:GetDescendants()) do
    if part:IsA("Folder") == false then
        part.Touched:Connect(function(hit)
        if hit.Parent:FindFirstChild("Humanoid") then
             local player = game.Players:GetPlayerFromCharacter(hit.Parent)
             if player then
                  if part.Name == "X2Part" then
                         --give the player X2
                  elseif part.Name == "X3Part"  then
                         --give the player X3
                  elseif part.Name == "X4Part"  then --etc...
                  end
             end
        end
    end
end
1 Like

Hmm, Interesting, that is probably what I should do. I’m currently working with three different multiplier levels, so I still ended up repeating the function three times in the same script. It seems to be working well, but is probably still longer (less efficient?) than it needs to be. Still certainly much better than my first pass where I had the function pasted for each individual part in the workspace.

db = false
for i, part in pairs(game.Workspace.TerrainMults2x:GetChildren()) do
    part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
        local player = game.Players:GetPlayerFromCharacter(hit.Parent)
        	if player then
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
				if db == false then
				db = true
				player.TerrainMultiplier.Value = 2
				wait(.5)
				db = false
				end
			end
		end
    end)
end
------------------------------------
db = false
for i, part in pairs(game.Workspace.TerrainMults3x:GetChildren()) do
    part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
        local player = game.Players:GetPlayerFromCharacter(hit.Parent)
        	if player then
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
				if db == false then
				db = true
				player.TerrainMultiplier.Value = 3
				wait(.5)
				db = false
				end
			end
		end
    end)
end
------------------------------------
db = false
for i, part in pairs(game.Workspace.TerrainMults4x:GetChildren()) do
    part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
        local player = game.Players:GetPlayerFromCharacter(hit.Parent)
        	if player then
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
				if db == false then
				db = true
				player.TerrainMultiplier.Value = 4
				wait(.5)
				db = false
				end
			end
		end
    end)
end

If you use GetDescendants() it doesn’t really matter how many mulitplier levels you have, as long as the names are the same from each seperate multiplier, you should be able to give them all seperate boosts

this is how the folder structure would look like
image

for i, part in pairs(game.Workspace.allTerrainMults:GetDescendants()) do
    if part:IsA("Part")  then --we check if its a part, and not a folder.
        part.Touched:Connect(function(hit)
	        if hit.Parent:FindFirstChild("Humanoid") then
	             local player = game.Players:GetPlayerFromCharacter(hit.Parent)
	             if player then
	                  if part.Name == "TerrMult2x002" then 
	                         --give boost
	                  elseif part.Name == "TerrMult2x003"  then
	                        --give boost
	                  elseif part.Name == "TerrMult2x004"  then --etc...
				            --give boost
	                  end
	             end
	        end
		end)
    end
end

The reason why I am using folders inside one bigger folder is to make it easier to read. You could also place all parts inside one folder without subfolders and use :GetChildren() instead of :GetDescendants and without checking if its a part

image

1 Like

Thank you for taking the time to illustrate and update the code. Very educational for me. And yes, this works 100% perfectly. I now have good multipliers. I still may use your nested IF statement to further simplify.

1 Like