I want to make a sink where on the click of a button, it makes water (initally at Transparency = 1) appear (stage1) by changing the Transparency value to ".55". After 10 seconds, more water will appear (stage2), and after another 10 seconds, more water will appear (stage3). This seems like an easy script but I don't know what I'm doing wrong.
local stage1 = game.Workspace.Stage1Water:GetChildren() local stage2 = game.Workspace.Stage2Water:GetChildren() local stage3 = game.Workspace.Stage3Water:GetChildren() function onClick() if script.Parent.OnOff.Value == false then script.Parent.OnOff.Value = true stage1.Transparency = .55 wait(10) stage2.Transparency = .55 wait(10) stage3.Transparency = .55 else script.Parent.OnOff.Value = false stage1.Transparency = 1 stage2.Transparency = 1 stage3.Transparency = 1 end end script.Parent.ClickDetector.MouseClick:connect(onClick( ))
DanzLua is correct, but that isn't your only problem -- you also called onClick
when trying to give MouseClick
something to connect to. Since onClick doesn't return anything, you effectively told it to connect to nil
(or "nothing"). It evaluates like this:
script.Parent.ClickDetector.MouseClick:connect(onClick()) --onClick is called and returns nil, so statement now looks like: script.Parent.ClickDetector.MouseClick:connect(nil) --which probably raised an error
To see such errors in the future, be sure to have the Output window open. (The Script Analysis window is also very helpful - if it displays a warning, there is almost always something wrong that you should fix; it can also catch syntax errors before you run the script.)
Below, I show how you might use a function to ensure that you needn't copy/paste code:
local stage1 = game.Workspace.Stage1Water:GetChildren() local stage2 = game.Workspace.Stage2Water:GetChildren() local stage3 = game.Workspace.Stage3Water:GetChildren() function setTransparency(list, transparency) for i = 1, #list do if list[i]:IsA("BasePart") then -- this 'if' is only needed if some children *aren't* a BasePart list[i].Transparency = transparency end -- end the 'if' end end function onClick() if script.Parent.OnOff.Value == false then script.Parent.OnOff.Value = true setTransparency(stage1, .55) wait(10) setTransparency(stage2, .55) wait(10) setTransparency(stage3, .55) else script.Parent.OnOff.Value = false setTransparency(stage1, 1) setTransparency(stage2, 1) setTransparency(stage3, 1) end end script.Parent.ClickDetector.MouseClick:Connect(onClick)
Note:
setTransparency
- as you can see, it's much more efficient than copy pasting the for
loop 6 times (instead, we just have to call the function 6 times).connect
is deprecated, use Connect
insteadstage
s in a table and then iterate over them with a for loop (but this isn't necessary and doesn't save any code when you only have 3 stages -- but if you ever end up wanting 4+ stages, it's becomes worth it)There is another problem with your script - it won't prevent someone from clicking it multiple times. This will mess up the animations. ex, say someone clicks it at "t=0" (let that mean "time of 0"), then stage1 will be semi-transparent at t=0 and stage2 will be semi-transparent at t=10 -- but say someone activates the ClickDetector at t=15 -- then everything will become transparent immediately (which is fine), but your script will then make stage3 semi-transparent at t=20.
There are two fixes:
Since you can look up "debounce" examples, I will show you the 2nd option. New script:
local stage1 = game.Workspace.Stage1Water:GetChildren() local stage2 = game.Workspace.Stage2Water:GetChildren() local stage3 = game.Workspace.Stage3Water:GetChildren() function setTransparency(list, transparency) for i = 1, #list do if list[i]:IsA("BasePart") then -- this 'if' is only needed if some children *aren't* a BasePart list[i].Transparency = transparency end -- end the 'if' end end local callNumber = 0 function onClick() local thisNumber = callNumber callNumber = callNumber + 1 if script.Parent.OnOff.Value == false then script.Parent.OnOff.Value = true setTransparency(stage1, .55) wait(10) if callNumber ~= thisNumber then return end setTransparency(stage2, .55) wait(10) if callNumber ~= thisNumber then return end setTransparency(stage3, .55) else script.Parent.OnOff.Value = false setTransparency(stage1, 1) setTransparency(stage2, 1) setTransparency(stage3, 1) end end script.Parent.ClickDetector.MouseClick:connect(onClick)
The new code involves the variables callNumber
and thisNumber
. Quite simply, the function will stop animating if onClick is called during the animation. In the same example I stepped through before, if a user clicks at t=0, pretend callNumber is 3, so thisNumber will also be 3. At t=10, stage2 is semi-transparent (as before). The script then compares callNumber and thisNumber, but doesn't return early because they are still the same. At t=15, the user clicks again and everything becomes semi-transparent -- and callNumber is increased by 1 and is now 4. Thus, at t=20, when the script would normally make stage3 semi-transparent, it instead compares callNumber (4) with thisNumber (still 3) and returns early -- thus, everything remains fully transparent. (In contrast, if you added debounce, the user clicking would do nothing until after t=20, since the animation would still be running.)
Well when you use :GetChildren() it returns a table, so what you'll want to do is when ever you are doing stage1.Transparency or something like that you want to go through all of the table's values and change their transparency IF its a basepart
for _,v in pairs(stage1) do if v:IsA("BasePart") then v.Transparency=1 end end