Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

I made a blinker script, but it dosen't blink?

Hello. I am trying to make a blinker script for a car using the a-chassis.

When I click **'E'**it turns on the blinker but the light dosen't blink, it just stays on until I click 'E' again. It is the same problem for the 'Q' key.

It is a local script inside the plugins folder of the a-chassis.

LocalScript:

local UIS = game:GetService("UserInputService")
local car = script.Parent.Car.Value
local RRightBlinker = car.Body.blinkersright
rightblinkeron = false
local RLightBlinker = car.Body.blinkersleft
leftblinkeron = false

UIS.InputBegan:connect(function(input)
	if (input.KeyCode == Enum.KeyCode.E) then
		if (rightblinkeron == false) then
			rightblinkeron = true
			repeat
				RRightBlinker.Material = Enum.Material.Neon
				wait(.9)
				RRightBlinker.Material = Enum.Material.SmoothPlastic
			until rightblinkeron == false
		elseif (rightblinkeron == true) then
			rightblinkeron = false
			RRightBlinker.Material = Enum.Material.SmoothPlastic
		end
	end
	
		if (input.KeyCode == Enum.KeyCode.Q) then
			if (leftblinkeron == false) then
			leftblinkeron = true
			repeat
				RLightBlinker.Material = Enum.Material.Neon
				wait(.7)
				RLightBlinker.Material = Enum.Material.SmoothPlastic
			until leftblinkeron == false
		elseif (leftblinkeron == true) then
			leftblinkeron = false
			RLightBlinker.Material = Enum.Material.SmoothPlastic
		end
	end
end)

2 answers

This was really messy , I tried putting my own vars you can change them if you want. Lights will blink 10 times before going off with a cooldown of 1 second before they can be turned on again.

local UIS = game:GetService("UserInputService")
local car = script.Parent:waitForChild("Car").Value
local RRightBlinker = car.Body.blinkersright
Rblinking = false
local RLightBlinker = car.Body.blinkersleft
Lblinking = false
local cdR = false
local cdL = false
UIS.InputBegan:connect(function(input, GPE)
	
    	if input.KeyCode == Enum.KeyCode.E and cdR == false then
			if Rblinking == false then
				cdR = true
				for i = 1,10 do
					wait(.5)
                	RRightBlinker.Material = Enum.Material.Neon
                	wait(.25)
               		RRightBlinker.Material = Enum.Material.SmoothPlastic
					wait(.5)
				end
				wait(1)
				Rblinking = true
				cdR = false
			end
    	end
		if input.KeyCode == Enum.KeyCode.E and cdR == false then
			if Rblinking == true then
				wait()
				cdR = true
				RRightBlinker.Material = Enum.Material.SmoothPlastic
				Rblinking = false
				wait(1)
				cdR = false
			end
    	end
		if input.KeyCode == Enum.KeyCode.Q and cdL == false then
			if Lblinking == false then
				cdL = true
				for i = 1,10 do
					wait(.5)
                	RLightBlinker.Material = Enum.Material.Neon
                	wait(.25)
               		RLightBlinker.Material = Enum.Material.SmoothPlastic
					wait(.5)
				end
				wait(1)
				Lblinking = true
				cdL = false
			end
    	end
		if input.KeyCode == Enum.KeyCode.Q and cdL == false then
			if Lblinking == true then
				wait()
				cdL = true
				RLightBlinker.Material = Enum.Material.SmoothPlastic
				Lblinking = false
				wait(1)
				cdL = false
			end
    	end		
end)

Thank you for reading! Goodluck while scripting !

2 comments

0

This is inferior to the OP's script (bugs aside), which allowed the user to turn on/off the lights at will. You should have an 'if' statement before each Material change to see if the user wants to turn off the blinking. Also, if the user press E, waits a second, then presses it twice more, I would expect the light to be on, but due to cdR, it will remain off (assuming you fix the 1st bug).

0

On the other hand, cdR is an improvement compared to the OP's script in the sense that it prevents multiple coroutines from going into each loop. (Note: I have not +1/-1ed your answer, just letting you know.)

Tip: Use print statements to see what's going on, like this (this is just part of your script):

    if (input.KeyCode == Enum.KeyCode.E) then
        if (rightblinkeron == false) then
            rightblinkeron = true
print("e turning on")
            repeat
	print"about neon"
                RRightBlinker.Material = Enum.Material.Neon
                wait(.9)
print"aft wait, smooth"
                RRightBlinker.Material = Enum.Material.SmoothPlastic
            until rightblinkeron == false
print"loop done"
        elseif (rightblinkeron == true) then
	print"e turning off"
            rightblinkeron = false
            RRightBlinker.Material = Enum.Material.SmoothPlastic
        end
    end

The output was this (and where I put '--pause', I mean there was a pause before the output continued):

e turning on
neon
--pause
smooth
neon
--pause
smooth
neon

Clearly, it is turning the brick smooth, but it is immediately turning it back to neon! You forgot a wait command after setting the material to smooth.

Tip: You don't need ()s around an if statement. ex, you can just do if rightblinkeron == false then. Also, val == false is the same as not val (if you don't care about the difference between false and nil), and val == true is identical to val

Also, stylistically, variables should be capitalized with lowerCamelCase -- that is, every word except the first should be capitalized. Function names often use UpperCamelCase, where every word including the first is capitalized.

Problem: while the blinker is blinking but in the 'off' state (ie it's Smooth material but still in the repeat loop), if you tap 'e' twice very quickly, you will cause it to start blinking faster -- this is because you will create two coroutines that are both in the repeat loop (the first repeat never exited because when it checked to see if it should keep on blinking, the answer is "yes"). To fix this, you can keep track of the number of times the player has stopped the blinking light and then exit the loop early if they've pressed it more times than when the loop started.

So that you don't have to write the same code twice, I've turned it into a basic "class". Improved script:

local UIS = game:GetService("UserInputService")
local car = script.Parent.Car.Value
local function Blinker(blinker, blinkTime) -- blinker is the part to blink, blinkTime is the number of seconds to wait before blinking on/off
	local self = {}
	local on = false -- true if the blink loop is supposed to be running
	local calls = 0 -- number of calls to Stop that have occurred
	function self:Blink() -- start the blink loop
		if on then return end -- already blinking
		on = true
		local startCalls = calls
		repeat
			blinker.Material = Enum.Material.Neon
			wait(blinkTime)
			if startCalls ~= calls then break end
			blinker.Material = Enum.Material.SmoothPlastic
			wait(blinkTime)        
		until not on or startCalls ~= calls
	end
	function self:Stop() -- stop the blink loop
		on = false
		calls = calls + 1
		blinker.Material = Enum.Material.SmoothPlastic
	end
	function self:Toggle() -- toggle the blink loop on/off
		if on then
			self:Stop()
		else
			self:Blink()
		end
	end
	return self
end

local right = Blinker(car.Body.blinkersright, .9)
local left = Blinker(car.Body.blinkersleft, .7) -- TODO is the .7 supposed to be different than .9?

--Note: you can now do things like right:Blink(), right:Stop(), and right:Toggle(). You cannot do right.on = true to change the "on" variable because it was declared "local". If you want to make a variable available outside of the class, you must use "self.var = 5" instead of "var = 5" in the class. In this case, however, you don't need to access those variables outside of the Blinker class - you are meant to only use the functions.

UIS.InputBegan:connect(function(input)
    if input.KeyCode == Enum.KeyCode.E then
		right:Toggle()
	elseif input.KeyCode == Enum.KeyCode.Q then
		left:Toggle()
	end
end)

This discussion is preserved as it was. New answers, comments, and votes are closed.