Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Can one script run many items?

Asked by
Spooce 78
10 years ago

Instead of placing the same script inside of a part, is there anyway to just use one script for all off the parts?

0
It depends on what the script is doing. YasuYoshida 171 — 10y

1 answer

Log in to vote
5
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
10 years ago

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 waiting). 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:

1function Touch(hit, me)
2    me.BrickColor = hit.BrickColor
3end
4 
5for _, part in pairs( workspace.Model:GetChildren() ) do
6    part.Touched:connect( function(h)
7        Touch(h, part)
8    end)
9end

The above corresponds to something like this:

1function Touch(hit)
2    script.Parent.BrickColor = hit.BrickColor
3end
4script.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:

1while true do
2    script.Parent.BrickColor = BrickColor.Red();
3    wait(1)
4    script.Parent.BrickColor = BrickColor.Blue();
5    wait(1)
6end

If you don't think carefully about it, you might try translating it into the following:

1-- THIS DOESN'T WORK!
2for _, part in pairs( workspace.Model:GetChildren() ) do
3    while true do
4        part.BrickColor = BrickColor.Red();
5        wait(1)
6        part.BrickColor = BrickColor.Blue();
7        wait(1)
8    end
9end

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:

01while true do
02    for _, part in pairs( workspace.Model:GetChildren() ) do
03        part.BrickColor = BrickColor.Red();
04    end
05    wait(1)
06    for _, part in pairs( workspace.Model:GetChildren() ) do
07        part.BrickColor = BrickColor.Blue();
08    end
09    wait(1)
10end

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.,

1while true do
2    script.Parent.BrickColor = BrickColor.Blue()
3    wait(math.random())
4    script.Parent.BrickColor = BrickColor.Red()
5    wait(math.random())
6end

A direct way to do it is to spawn a new coroutine for each part:

01function flash(part)
02    while true do
03        part.BrickColor = BrickColor.Blue()
04        wait(math.random())
05        part.BrickColor = BrickColor.Red()
06        wait(math.random())
07    end
08end
09 
10 
11 
12for _, part in pairs( workspace.Model:GetChildren()) do
13    spawn(function() flash(part) end )
14end

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):

01changes = {}
02for _, part in pairs(workspace.Model:GetChildren()) do
03    changes[ part ] =
04        {
05            time = math.random() + tick() ,
06            red = false
07        }
08end
09 
10while true do
11    soonest = tick() + 1
12    -- The soonest (so far seen) that
13    -- a brick needs updating
14 
15    for part, data in pairs( changes ) do
View all 35 lines...
1
For the multiple threads, why not just use spawn(f) or delay(n, f)? Looks cleaner than using a coroutine. Tkdriverx 514 — 10y
0
Just thought of my own answer. This could be useful, but it doesn't relate to my question exactly. I will accept since you put a lot of work into it. Spooce 78 — 10y
0
I am going to contradict myself now. Use `spawn`. Previously I said don't. Use it. If you are only creating coroutines to run them in the background, use `spawn` and make your intent clear. BlueTaslem 18071 — 9y
Ad

Answer this question