Change Property of All Objects In One Table INSIDE Another Table?

  1. What do you want to achieve? Keep it simple and clear!
    I want to change the material of objects and tween their color. One group of objects share one tag and the other group share a different tag. I use “GetTagged” and “for i, v do” to find and seperate each group. Then, here is where I am stuck, I want to create a table for each group and put those tables inside another, just to keep it organized. but idk if it helps my script to do all that.

  2. What is the issue? Include screenshots / videos if possible!
    The issue is that once I define the tables and put them inside a single table, when I try to change the properties of the parts inside each group as a whole using a tween, it only tweens the first object inside each table, not every part inside each table.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have already made the tables for each group and put them in a single table, but like I said, once I try to change the material and tween the color only the first part inside each table is found. I want to change the material and tween the parts of each of the two tables inside the main table. (HOPE THIS MAKES SENSE, SORRY).

Here is my original script that works and does what I want, WITHOUT THE TABLES.

local TweenService = game:GetService("TweenService")
local CollectionService = game:GetService("CollectionService")
local Button2 = script.Parent["Lights 1 Fuscia"]
local TweenInfo = TweenInfo.new(
	1, --number of seconds
	Enum.EasingStyle.Linear, --how it moves
	Enum.EasingDirection.InOut, --how it moves
	-1, --how many times to repeat
	true, --go back to start after ending?
	0 --the wait before starting
)
local Color = {
	{Color = Color3.new(0.666667, 0, 0)},
	{Color = Color3.new(0.333333, 0, 1)}
}

for i,LightBulbsGroup1 in pairs(CollectionService:GetTagged("Mainstage Backdrop Lightbulb Lights Alternating Pattern Group 1")) do
for i,LightBulbsGroup2 in pairs(CollectionService:GetTagged("Mainstage Backdrop Lightbulb Lights Alternating Pattern Group 2")) do	

		Button2.MouseButton1Click:Connect(function()
			LightBulbsGroup1.Material = Enum.Material.Neon
			TweenService:Create(LightBulbsGroup1, TweenInfo, Color[1]):Play()
			task.wait(1)

			LightBulbsGroup2.Material = Enum.Material.Neon
			TweenService:Create(LightBulbsGroup2, TweenInfo, Color[2]):Play()
			task.wait(1)	
		end)
	end
end

Here is how this looks in game.

And here is what I have tried to do, but like I mentioned it only find the first part inside each of the tables, and I want to be able to change the properties of each entire table!

local TweenService = game:GetService("TweenService")
local CollectionService = game:GetService("CollectionService")
local Button2 = script.Parent["Lights 1 Fuscia"]
local TweenInfo = TweenInfo.new(
	1, --number of seconds
	Enum.EasingStyle.Linear, --how it moves
	Enum.EasingDirection.InOut, --how it moves
	-1, --how many times to repeat
	true, --go back to start after ending?
	0 --the wait before starting
)
local Color = {
	{Color = Color3.new(0.666667, 0, 0)},
	{Color = Color3.new(0.333333, 0, 1)}
}

local Light = {}

for i,LightBulbsGroup1 in pairs(CollectionService:GetTagged("Mainstage Backdrop Lightbulb Lights Alternating Pattern Group 1")) do
	table.insert(Light,LightBulbsGroup1)
for i,LightBulbsGroup2 in pairs(CollectionService:GetTagged("Mainstage Backdrop Lightbulb Lights Alternating Pattern Group 2")) do	
	table.insert(Light,LightBulbsGroup2)
		
		Button2.MouseButton1Click:Connect(function()
			Light[1].Material = Enum.Material.Neon
			TweenService:Create(Light[1], TweenInfo, Color[1]):Play()
			task.wait(1)

			Light[2].Material = Enum.Material.Neon
			TweenService:Create(Light[2], TweenInfo, Color[2]):Play()
			task.wait(1)	
		end)
	end
end

Video showing what I mean

There are two fundamental problems here. The first, and most severe, is that these two loops are unintentionally nested, resulting in lots of redundant (and competing) tweens playing. This is definitely not what you want. They way you have it, if there are 10 bulbs in Group 1 and 10 bulbs in Group 2, you end up creating 100 click handler functions, each of which starts two tweens. There is one handler for every combination of pair of bulbs from Groups 1 and 2, with 10x redundancy across the board.

The second issue is that it appears to me that what you actually want is to invert the structure so that instead of a loop creating click handler functions for each light, you have a single handler function that runs 2 loops (looping over Group 1 and Group 2 independently, not nested!)

What I mean is that the code would look more like this:

Button2.MouseButton1Click:Connect(function()
	for i, bulb in ipairs(CollectionService:GetTagged("Mainstage Backdrop Lightbulb Lights Alternating Pattern Group 1")) do
		bulb.Material = Enum.Material.Neon
		TweenService:Create(bulb, TweenInfo, Color[1]):Play()
	end
	
	for i, bulb in ipairs(CollectionService:GetTagged("Mainstage Backdrop Lightbulb Lights Alternating Pattern Group 2")) do
		bulb.Material = Enum.Material.Neon
		TweenService:Create(bulb, TweenInfo, Color[2]):Play()
	end
end)

But this is re-arrangement doesn’t fully fix the code. Firstly, I removed your task.wait(1) calls, since they would not have worked to stagger the starts, because of the click handler redundancy. If you want to stagger the starts, it’s better to either make a new TweenInfo with a DelayTime for each group, or you could use task.delay() to stagger the tween:Play() calls.

Secondly, clicking the button multiple times is going to start new tweens playing on things that are already tweening, making a mess. You really need to save the return value from Tween:Create() to cancel currently-running tweens on each bulb before starting new ones using tween:Cancel().

1 Like

Thank you sooooo much for the detailed help! This helps a lot and I didn’t realize there were other issues so thank you for explaining them! I will replace the code with what you wrote! As for the tables, should I just not do that? I don’t think it is necessary I only wanted to do it because I thought it could help organize my script better?

I’m not sure which tables you mean, the arrays from CollectionService? Those seem fine to me; that is how the service is intended to used. One thing to be aware of though: if you add and remove lights from collections at runtime, by setting tags on things from Lua, the code I wrote will always work for everything tagged since it calls GetTagged with each button click, whereas your original code only reads the collections once when it makes the click handlers, so it would not respond to any runtime changes to the collections. This is part of the reason I recommended inverting it, though the more problematic thing was the performance issue of having multiple handler functions all running the same loop code, when only one function is really needed.

1 Like

Yeah I will need to figure out how to make the buttons inverts it once it is clicked a second time. I am not sure on how to do that yet but I will look into it now that you have mentioned it as well! Thank you so much! I will mark your first response as a solution regardless :smiley:

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