Why won't this script pass through all parts?

Hey! I currently have a group of parts, and I want to change their color.

So I have this script here, BUT it’s only changing one of the parts in the model, not them all.

local parts = script.Parent:GetChildren()

for i, v in pairs(parts) do
	if v:IsA("BasePart") then
		while true do
			for i = 0,2,0.05 do
				v.Color =v.Color:lerp(Color3.new(255/255, 18/255, 225/255), i / 100)
				wait()
			end
			for i = 0,2,0.05 do
				v.Color =v.Color:lerp(Color3.new(30/255, 41/ 255, 255/255), i / 100)
				wait()
			end
			for i = 1,2,0.05 do
				v.Color = v.Color:lerp(Color3.new(43/255, 170/255, 255/255), i / 100)
				wait()
			end
			for i = 1,2,0.05 do
				v.Color =v.Color:lerp(Color3.new(43/255, 255/255, 50/255), i / 100)
				wait()
			end
			for i = 1,2,0.05 do
				v.Color = v.Color:lerp(Color3.new(245/255, 255/255, 46/255), i / 100)
				wait()
			end
			for i = 1,2,0.05 do
				v.Color = v.Color:lerp(Color3.new(255/255, 0/255, 0/255), i / 100)
				wait()
			end
		end
	end
end	

No errors either.

Any help would be appreciated, thanks.

- SimplyFrazer

1 Like

I believe it’s because of the while true do and wait() which forces the script to endlessly cycle through the while true do loop and not continue. I believe you can solve this by wrapping the while true do in a coroutine wrap to prevent the wait() from yielding the entire script and not letting the forloop pass.

However I do believe there are better ways to do this though I’ll leave that to someone else.

Pretty sure it was made purposely, since, I’ve seen a similar script to this one, which works.

@SimplyFrazer, I believe the issue is that you are looping IN one of the BaseParts. Otherwise, try print debugging, and, for one specified print statement, place it under the first for loop, and do print(v:GetFullName()), which will print the path of the child of the object being looped.

PROBLEM
So the main problem I see here is the While true do like @dthecoolest said. This problem could be fixed with a coroutine however as he also said, im not sure its the best way to do this.

The code will be getting stuck in the while loop for the first object which is why it doesn’t continue for the others.

POTENTIAL FIX
You could use Tween Service and bind colour tweens to each object however im not sure this is any better than the coroutine option.

local parts = script.Parent:GetChildren() --I Think this is linking to the workspace children (Maybe???)

for i, v in pairs(parts) do --for all parts in the workspace
	if v:IsA("BasePart") then --If its a basepart then perform colour code on it
        while true do   --THIS WHILE LOOP WILL BREAK THE CODE - code gets stuck here for first part
            --Colour code was in here
        end
    end
end

HOW LERP WORKS
So the lerp function works by taking a input Colour and a final colour and returning a mix between the two by a factor give between 0 and 1. e.g.

if lerping a number 0 to 100 by having this number in a variable called numberToLerp the following would happen

NOTE: Not actual code, just for example purpose

local numberToLerp = 0

numberToLerp = numberToLerp.Lerp(100, t) --t is the factor it will use to return its value

t = 0.5 would return 50
t = 0.2 would return 20
t = 1 would return 100
t = 0 would return 1

So when using this for loop in your code

for i = 0,2,0.05 do
    v.Color =v.Color:lerp(Color3.new(255/255, 18/255, 225/255), i / 100)
    wait()
end

i’s max value is 2

then your setting your t value to 2/100 this is 0.02

This will probably result in a weird colour which is not what you originally intended as it is only 1/50th of the way to its final colour of Color3.new(255/255, 18/255, 225/255)

1 Like

The script is doing the parts one by one. It first picks a part. Then it lerps its color, waits, lerps, waits etc…
It does not start doing this for the other parts until it’s done.

Here’s what you get when rearrange the first 3 lines of the loop.

local parts = script.Parent:GetChildren()

while true do -- do the following repeatedly forever
	for i, v in pairs(parts) do -- pick a part
		if v:IsA("BasePart") then
			for i = 0,2,0.05 do
				-- make that one chosen part change color
				v.Color =v.Color:lerp(Color3.new(255/255, 18/255, 225/255), i / 100)
				wait()
			end
			for i = 0,2,0.05 do
				v.Color =v.Color:lerp(Color3.new(30/255, 41/ 255, 255/255), i / 100)
				wait()
			end
			-- etc etc...
		end
	end
end

Now the script will, one by one, make each of the parts go through the spectrum.
This seems like an improvement, because before, it was stuck on just one of the parts!

Here’s how you’d rearrange the script to work how you expected it to:

while true do -- do the following repeatedly forever
	for i = 0,2,0.05 do
		for i, v in pairs(parts) do -- pick a part
			if v:IsA("BasePart") then
				v.Color =v.Color:lerp(Color3.new(255/255, 18/255, 225/255), i / 100) -- set its color
			end
		end
		wait() -- we've set the colors of all parts, let's finally wait
	end
	for i = 0,2,0.05 do
		for i, v in pairs(parts) do
			if v:IsA("BasePart") then
				v.Color =v.Color:lerp(Color3.new(30/255, 41/ 255, 255/255), i / 100)
			end
		end
		wait()
	end
	-- etc. etc...
end

But there’s a simple way to turn your first code into what you expected, and that’s making a new thread/coroutine for each part.

local parts = script.Parent:GetChildren()

local function makePartCycleColors(part)
	while true do
		for i = 0,2,0.05 do
			v.Color =v.Color:lerp(Color3.new(255/255, 18/255, 225/255), i / 100)
			wait()
		end
		-- etc etc etc. copy-paste your own example here
	end
end

for i, v in pairs(parts) do
	if v:IsA("BasePart") then
		-- wrap the above function in a coroutine
		local coro = coroutine.wrap(makePartCycleColors) -- coro is actually a function
		coro(v) -- call the function with the part
		-- when it uses wait() for the first time, it returns right here, to
		-- continue the loop and make a coroutine for the next part
		-- the game will then resume the coroutine after that wait() has finished,
		-- independently from this loop and anything else happening
		
		-- what if you didn't use coroutine.wrap()? what if you just used
		-- makePartCycleColors(v)?
		-- then wait() would pause this for loop, and the for loop wouldn't continue
		-- until makePartCycleColors() has finished
		-- and that function NEVER finishes, so the next part will never start changing colors
		-- it'd be exactly what you had before
	end
end
1 Like