When a player join the game, a random part will be Bright green. I’m trying to set this up so that when a player steps on the bright green part the part itself will turn Medium stone grey. However, another part contained in the same model will turn Bright green. I am hoping that this will then continue the same process over and over again of having to tap the green part to turn another random part green.
local workSpace = game:GetService("Workspace")
local randomizer = workSpace.Randomizer
local debounce = false
local children = randomizer:GetChildren()
local part = children[math.random(1, #children)]
part.BrickColor = BrickColor.new("Bright green")
while true do
randomnumber = math.random(1, #children)
for i, v in pairs(children)do
v.Touched:Connect(function(part)
if not debounce then
debounce = true
if part.Parent:FindFirstChild("Humanoid")and v.BrickColor == BrickColor.new("Bright green")then
v.BrickColor = BrickColor.new("Medium stone grey")
end
if part.Parent:FindFirstChild("Humanoid")and i == randomnumber then
v.BrickColor = BrickColor.new("Bright green")
end
debounce = false
end
end)
end
wait(1)
end
The current script gets no error code and the first part turns grey. No other part is made to be green though. I believe this is because I can’t do two if statements like I’ve done here, but I’m not sure. If anyone could recommend a course of action or show me what I’ve done wrong it would be much appreciated.
So you’re connecting a new event to every part, every second.
You actually don’t even need a loop here, since you can do your update when the part gets touched.
Here’s a skeleton to get you started, you’ll need to implement some of it:
local current
local touchedConnection
local function PickRandomPart()
-- change 'current' to gray (if 'current' exists)
-- pick a new part and set 'current' to it
-- change the new 'current' to green
-- call Disconnect() on touchedConnection (if it exists)
if touchedConnection then touchedConnection:Disconnect() end
-- create a new connection instead
touchedConnection = current.Touched:Connect(function(hit)
-- check for humnanoid
-- call PickRandomPart()
end)
end
-- set up initially
PickRandomPart()
@LordIsaacofBargo@nicemike40 is right (thank you!), I almost missed that. Use the updated code, which doesn’t include the loop anymore. Have a good time!
It’s highly suggested to also check if the part is a BasePart just in case. It’s generally good practice, it could be done as shown:
if part:IsA("BasePart") then
-- code here
end
You can put it in the function for change part color or you can put it in your loop. I would suggest in the loop so you can do something like:
for i, v in pairs(children) do
if v:IsA("BasePart") then
v.Touched:Connect(function(part)
if not debounce then
changeColor(v, part.Parent)
end
end)
end
end
I’ve went with the other solution as it’s more efficient, but in future similar situations I will use this as a method to prevent more problems, thank you.
Just going to add it on here incase anyone is interested (or if it works but I made an error of some kind that could cause problems later).
local randomizer = game.Workspace.Randomizer
local children = randomizer:GetChildren()
local current = children[math.random(1, #children)]
local touchedConnection
local function PickRandomPart()
if current then
current.BrickColor = BrickColor.new("Medium stone grey")
current = children[math.random(1, #children)]
current.BrickColor = BrickColor.new("Bright green")
if touchedConnection then touchedConnection:Disconnect() end
touchedConnection = current.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid")then
PickRandomPart()
end
end)
end
end
PickRandomPart()
May I ask, how is it more efficient, with the exception of use of disconnect? I removed the while-loop immediately, so it is fine now. Concept is the same. You needn’t have written your own, only had to add :Disconnect().
The code itself may be more efficient, however you should change the function name to something like: “checkForTouched()” just for readability sake and for any future collaborations or help requests.
I agree with you, the other solution isn’t very readable and isn’t efficient for what he wants to do. The “for” loop method you did is perfectly fine and should work for what he wants. Although you could include the disconnect in some way to make it double the efficiency.
@LordIsaacofBargo it is true that for loop works and is not at all performance demanding, but the truth is that @nicemike40 had a perfect idea. Here is, for my opinion, a final version:
local randomizer = workspace.Randomizer
local COOLDOWN = true
local COOLDOWN_TIME = .5
local children = {}
local debounce = false
local current, tConnection
local function changeColor()
if (not current) then return; end
debounce = true
current.BrickColor = BrickColor.new("Medium stone grey")
current = children[math.random(1, #children)]
current.BrickColor = BrickColor.new("Bright green")
if (tConnection) then tConnection:Disconnect() end
if (COOLDOWN) then wait(COOLDOWN_TIME) end
debounce = false
tConnection = current.Touched:Connect(function(hit)
if (hit.Parent:FindFirstChild("HumanoidRootPart") and not debounce) then
changeColor()
end
end)
end
local function init()
for i, v in pairs(randomizer:GetChildren()) do
if (v:IsA("BasePart")) then
table.insert(children, v)
end
end
if (next(children) == nil) then
warn("There are no parts in Randomizer.")
script.Disabled = true
end
current = children[math.random(1, #children)]
changeColor()
end
init()