Help with GetDescendants

I was trying to make a graphical ambient system in my game but I ran into a roadblock. The script is running through the workspace and looking for parts with the Attribute “Ambient” in them. There were a total of 4 instances that matched, however the scripts only takes one of them to operate with. I don’t know why or how it happened. I would appreciate any help!

for _, desc in pairs(workspace:GetDescendants()) do
	print("test stage 1")
	if desc:GetAttribute("Ambient") and desc:IsA("BasePart") or desc:IsA("SpotLight") then
		print(desc.Name) -- Only printed one instance
		local M1 = TweenService:Create(Lighting, TI, Dawn1)
		local M2 = TweenService:Create(desc, TI, Dawn2)
		local M3 = TweenService:Create(Lighting, TI, Morning1)
		local M4 = TweenService:Create(desc, TI, Morning2)
		local M5 = TweenService:Create(Lighting, TI, Night)
		
		while task.wait() do
			if Lighting.ClockTime >= 5 and Lighting.ClockTime < 8 then
				M1:Play()
				M2:Play()
				print("New day!")
			elseif Lighting.ClockTime >= 8 and Lighting.ClockTime < 17 then
				M3:Play()
				M4:Play()
				print("Good Morning!")
			elseif Lighting.ClockTime >= 17 and Lighting.ClockTime < 5 then
				M5:Play()
				print("Good night~")
			end
		end
	end
end

Most likely it’s only caring for one of them because you have a while task.wait() do loop, which will never end.

If you want to make all of them work, try to encase your loop in a task.spawn so they all work separately

 for _, desc in pairs(workspace:GetDescendants()) do
	print("test stage 1")
	if desc:GetAttribute("Ambient") and desc:IsA("BasePart") or desc:IsA("SpotLight") then
		print(desc.Name) -- Only printed one instance
		local M1 = TweenService:Create(Lighting, TI, Dawn1)
		local M2 = TweenService:Create(desc, TI, Dawn2)
		local M3 = TweenService:Create(Lighting, TI, Morning1)
		local M4 = TweenService:Create(desc, TI, Morning2)
		local M5 = TweenService:Create(Lighting, TI, Night)
		
		task.spawn(function()
			while task.wait() do
				if Lighting.ClockTime >= 5 and Lighting.ClockTime < 8 then
					M1:Play()
					M2:Play()
					print("New day!")
				elseif Lighting.ClockTime >= 8 and Lighting.ClockTime < 17 then
					M3:Play()
					M4:Play()
					print("Good Morning!")
				elseif Lighting.ClockTime >= 17 and Lighting.ClockTime < 5 then
					M5:Play()
					print("Good night~")
				end
			end
		end)
	end
end

I tried using this script but it just broke the whole system. Perhaps the amount of the threads are making the engine overwhelmed

The reason why it only detects 1 is because of the while loop, and because it never stops and I also do not like the way the tweens are being used here. I’m not sure how the tweens are supposed to be used but the task.wait() is really screwing them over.

The TweenServices were for the smooth ambience transition, from Dawn to Morning, Morning to Dusk, etc. I don’t like how it looks either but it’s the only thing I could think of. And by the way, thanks for helping me to figure out the cause!

usually when a tween is used like this it will convert a linear to a quad like so of course it is gonna sort of look smooth, but you should try cleaning the code up a little bit so it is easier to look for the problem

Variables that do not change throughout the whole loop should be declared before the look so M1,M3 and M5 should be outside the for _,desc in pairs() loop. and because you were looking to play them in a loop anyways you can do

task.spawn(function()
    while task.wait() do
        if Lighting.ClockTime>=5 and Lighting.ClockTime<17 then
            M1:Play()
        elseif (--[[Other conditions i wont write]])
        end
    end
end)
for _,desc in pairs(workspace:GetDescendants())do
--block
--be sure to remove the M1, M3, and M5 from the loop
end

you can continue the loop like usual but heres what I think needs to be done

local M1 = TweenService:Create(Lighting, TI, Dawn1)
local M3 = TweenService:Create(Lighting, TI, Morning1)
local M5 = TweenService:Create(Lighting, TI, Night)
task.spawn(function()
	while task.wait() do
		if Lighting.ClockTime >= 5 and Lighting.ClockTime < 8 then
			M1:Play()
			print("New day!")
		elseif Lighting.ClockTime >= 8 and Lighting.ClockTime < 17 then
			M3:Play()
			print("Good Morning!")
		elseif Lighting.ClockTime >= 17 and Lighting.ClockTime < 5 then
			M5:Play()
			print("Good night~")
		end
	end
end)
local Desc={}--this is to collect the descendants
for _, desc in pairs(workspace:GetDescendants()) do
	print("test stage 1")
	if desc:GetAttribute("Ambient") and desc:IsA("BasePart") or desc:IsA("SpotLight") then
        table.insert(Desc,desc)
		print(desc.Name) -- Only printed one instance
		local M2 = TweenService:Create(desc, TI, Dawn2)
		local M4 = TweenService:Create(desc, TI, Morning2)
		
		task.spawn(function()
            while task.wait() do
		    	if Lighting.ClockTime >= 5 and Lighting.ClockTime < 8 then
				    M2:Play()
			    elseif Lighting.ClockTime >= 8 and Lighting.ClockTime < 17 then
				    M4:Play()
				end
			end
		end)
	end
end

although this code is still not very good, it gets all of the descendants, and the Lighting is still being ran the same way as it would.
I would still like to see the whole script so I can see what else is wrong with it.
As of right now I am still not 100% sure of what you are trying to do.

Your script worked, thank you! I never thought about using a table to store the descendants.

The rest of the codes are just variables setting the up the tween. Though if you still need the whole updated code, here it is:

local Lighting = game:GetService("Lighting")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")

local TI = TweenInfo.new(
	5,
	Enum.EasingStyle.Quad,
	Enum.EasingDirection.InOut
)

local Dawn1 = {Ambient = Color3.fromRGB(124, 85, 50)}
local Dawn2 = {Color = Color3.fromRGB(150, 140, 104)}

local Morning1 = {Ambient = Color3.fromRGB(97, 97, 97)}
local Morning2 = {Color = Color3.fromRGB(255, 255, 255)}

local Night = {Ambient = Color3.fromRGB(0, 0, 0)}

local M1 = TweenService:Create(Lighting, TI, Dawn1)
local M3 = TweenService:Create(Lighting, TI, Morning1)
local M5 = TweenService:Create(Lighting, TI, Night)
task.spawn(function()
	while task.wait() do
		if Lighting.ClockTime >= 5 and Lighting.ClockTime < 8 then
			M1:Play()
			print("New day!")
		elseif Lighting.ClockTime >= 8 and Lighting.ClockTime < 17 then
			M3:Play()
			print("Good Morning!")
		elseif Lighting.ClockTime >= 17 and Lighting.ClockTime < 5 then
			M5:Play()
			print("Good night~")
		end
	end
end)

local Desc={}--this is to collect the descendants
for _, desc in pairs(workspace:GetDescendants()) do
	print("test stage 1")
	if desc:GetAttribute("Ambient") and desc:IsA("BasePart") or desc:IsA("SpotLight") then
		table.insert(Desc,desc)
		print(desc.Name) -- Only printed one instance
		local M2 = TweenService:Create(desc, TI, Dawn2)
		local M4 = TweenService:Create(desc, TI, Morning2)

		task.spawn(function()
			while task.wait() do
				if Lighting.ClockTime >= 5 and Lighting.ClockTime < 8 then
					M2:Play()
				elseif Lighting.ClockTime >= 8 and Lighting.ClockTime < 17 then
					M4:Play()
				end
			end
		end)
	end
end
1 Like

you are very welcome. I know the code works fine but I would still recommend a better way to handle the tween, or you can leave it how it is.

@apictrain0
This isn’t a good System.

With this system, you are telling the the Code to Create Loops depending on the number of Descendants within your Instance, it doesn’t make your code more efficient, it makes your code use more resources to accomplish a task than more simple methods

A way more efficient Method would be to place the while loop OUTSIDE the for loop, which will make only one loop instead of the number of how many children you have with the Instance

You should also create a table with a list of times to iterate through

local Times = { -- List of Times for the code to keep track of
    [0]  = {M1, M2} -- to store Tweens Inside
    [8]  = {M3, M4}
    [17] = {M5}
}

This make your code store the Tweens you want to Play, and if you want to make a system with this, you can:

function C_Times(x: number) -- the x variable is used to indicate the number
    local foundtime = 0 -- used to track the if statements
    local list -- placeholder for table
    for t,v in Times do
        if x >= t and foundtime < t then
            foundtime = t -- new time found
            list = v -- returns the list
        end
    end
    for i = 1,#list do -- runs for how many items are in the list (2 max, 1 min)
        list[i]:Play() -- plays the item under the current index
    end
end

So with this code, you can efficiently check the times, what this code does is iterates through all the values within the stored table and checks if the time number given is equal to the set time inside the Array, if the result is true, we can set a new limit to check for, if the next time the code fires returns true, it will set a new value until there is no more you can chceck through

within your while loop, you can do this:

task.spawn(function()
    while task.wait(.1) do -- this is so there is interval that wont cause lag
        C_Time(Lighting.ClockTime) -- fires function
    end
end)

This will greatly simplify your code.

I even said it wasnt a good system But I didnt really understand what had to be done.

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