How to make parts continuously change colour while player is still on it?

Hello. I’m new to scripting.
I have this, which changes the colour of part whenever a player steps on it.

for _, v in pairs(workspace["testing color"]:GetDescendants()) do
	if v:IsA("Part") then
		local r = math.random(0,255)
		local g = math.random(0,255)
		local b = math.random(0,255)
		v.Touched:Connect(function(hit)
			if hit.Parent:FindFirstChild("Humanoid") then
				v.Color = Color3.new(r,g,b) --random colour
			end
		end)
	end
end

I was wondering, how do you make it so that when a player is still on it, it changes colours continuously until the player has stepped off the parts, which then reverts it back to its original colours?

Any help would be greatly appreciated. :slight_smile:

1 Like

Server script in workspace

Time = 1 -- Time after changing color

for i, Part in pairs(workspace["testing color"]:GetDescendants()) do -- You can use diff keys and values, e.g. 'x, y' 
	if Part:IsA('Part') then -- You can use diff type of quotes, e.g. "'", '"'
		local Touched = true -- As you see this is like having the TouchEnded event inside of the Touched event
		local LastHit -- This variable is empty until you change it, so i can change it to the last hit detected
		Part.Touched:Connect(function(Hit)
			Touched = true -- In this case this can be inside the Touched event or outside of the Humanoid detection
			if Hit.Parent:FindFirstChildOfClass("Humanoid") then
				LastHit = Hit.Parent -- I use Hit.Parent to have a precise detection
				coroutine.wrap(function() -- This is better than using loops, it's like a ghost for the end of the function it's inside
					repeat wait(Time) -- A loop
						Part.Color = Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255)) -- math.random in every color value
					until Touched == false -- You can use two equal symbols to check a value
				end)() -- This parenthesis is important for the coroutine function
			end
		end)
		Part.TouchEnded:Connect(function(Hit) -- Here's the TouchEnded event which can be inside (better) or outside of the Touched event (worse)
			if LastHit == Hit.Parent then -- In this case LastHit is the last Hit.Parent, this has better precision
				Touched = false
			end
		end)
	end
end
3 Likes

This sure worked like a charm when it comes to changing its colour, though how do I get the parts to revert back to its original colour, maybe 3 seconds later?

Thanks. :hidere:

1 Like

Tell me in case it has any error (I’ll add some examples later, so you can understand these codes :slight_smile: )

Time = 1
ResetTime = 3

for i, Part in pairs(workspace["testing color"]:GetDescendants()) do
	if Part:IsA("Part") then
        OldColor = Part.Color
		local Touched = true
		local LastHit
		Part.Touched:Connect(function(Hit)
			Touched = true
			if Hit.Parent:FindFirstChildOfClass("Humanoid") then
				LastHit = Hit.Parent
				coroutine.wrap(function()
					repeat wait(Time)
						Part.Color = Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255))
					until Touched == false
				end)()
			end
		end)
		Part.TouchEnded:Connect(function(Hit)
			if LastHit == Hit.Parent then
                wait(ResetTime)
                Part.Color = OldColor
				Touched = false
			end
		end)
	end
end
2 Likes

Wow! This is pretty impressive, it works.
Though, I’d like some explanation because this looks quite complicated to me. :sweat_smile:

I’ll mark this as the solution.

2 Likes

@OunceOfEmpathy Here’s the explained ver, so you can understand

1 Like
local run = game:GetService"RunService"
local players = game:GetService"Players"
local part = script.Parent
local current = part.BrickColor

local connection
local lastTouched = 0

part.Touched:Connect(function(hitPart)
	local hitModel = hitPart:FindFirstAncestorOfClass"Model"
	if hitModel then
		local hitPlayer = players:GetPlayerFromCharacter(hitModel)
		if hitPlayer then
			lastTouched = os.clock()
			if connection then
				if connection.Connected then
					return
				end
			end
			connection = run.Stepped:Connect(function()
				part.BrickColor = BrickColor.Random()
			end)
			
			part.TouchEnded:Connect(function(_hitPart)
				if hitPart == _hitPart then
					if connection then
						if connection.Connected then
							connection:Disconnect()
							connection = nil
						end
					end
					task.delay(3, function()
						if os.clock() - lastTouched >= 3 then
							part.BrickColor = current
						end
					end)
				end
			end)
		end
	end
end)
2 Likes