Instead of placing the same script inside of a part, is there anyway to just use one script for all off the parts?
Yes. Almost always it is better to do it that way.
In general, you'll have a very similar looking script. There will just be an addition of a loop to perform the action on each part (or maybe several loops in things that require wait
ing). For example, if there was a Model of parts that you wanted to change color when touched, you would just have to modify the event to use a closure:
function Touch(hit, me) me.BrickColor = hit.BrickColor end for _, part in pairs( workspace.Model:GetChildren() ) do part.Touched:connect( function(h) Touch(h, part) end) end
The above corresponds to something like this:
function Touch(hit) script.Parent.BrickColor = hit.BrickColor end script.Parent.Touched:connect( Touch )
A more complicated example is to make a list of parts flip between blue and red every second. The single script for each might look like this:
while true do script.Parent.BrickColor = BrickColor.Red(); wait(1) script.Parent.BrickColor = BrickColor.Blue(); wait(1) end
If you don't think carefully about it, you might try translating it into the following:
-- THIS DOESN'T WORK! for _, part in pairs( workspace.Model:GetChildren() ) do while true do part.BrickColor = BrickColor.Red(); wait(1) part.BrickColor = BrickColor.Blue(); wait(1) end end
Why? Because it starts an unending loop for just the first part, and never even gets to the second. Removing the loop will be a bit better, but it will do each part in sequence, rather than all at once.
A simple solution is to use 2 for
loops:
while true do for _, part in pairs( workspace.Model:GetChildren() ) do part.BrickColor = BrickColor.Red(); end wait(1) for _, part in pairs( workspace.Model:GetChildren() ) do part.BrickColor = BrickColor.Blue(); end wait(1) end
This could be cleaned up with the help of a function to paint a list of parts (avoiding the repeated code)
An even more complicated example is when you want to do the above but you want them each to be flashing at random offsets, e.g.,
while true do script.Parent.BrickColor = BrickColor.Blue() wait(math.random()) script.Parent.BrickColor = BrickColor.Red() wait(math.random()) end
A direct way to do it is to spawn a new coroutine for each part:
function flash(part) while true do part.BrickColor = BrickColor.Blue() wait(math.random()) part.BrickColor = BrickColor.Red() wait(math.random()) end end for _, part in pairs( workspace.Model:GetChildren()) do spawn(function() flash(part) end ) end
Though this isn't very elegant because spawning a large number of threads in general can cause difficulties.
Unfortunately, a direct way to do this in one thread is much more sophisticated (though possible):
changes = {} for _, part in pairs(workspace.Model:GetChildren()) do changes[ part ] = { time = math.random() + tick() , red = false } end while true do soonest = tick() + 1 -- The soonest (so far seen) that -- a brick needs updating for part, data in pairs( changes ) do soonest = math.min( soonest, data.time ) end wait( soonest - tick() ) -- Wait just until that moment -- (Less performant, but more responsive, would be -- to just always wait using RenderStepped) for part, data in pairs( changes ) do if data.time < tick() then if data.red then part.BrickColor = BrickColor.Red() else part.BrickColor = BrickColor.Blue() end data.red = not data.red data.time = tick() + math.random() end end end