Remote Events Not Doing Triggering My Countdown Script

I’m trying to make a countdown that counts down from 5 to 0, while changing lights on my light post at the same time how I want them to. I want it to fire this countdown for all players when someone clicks the “Start Race” button. I first started by making one script that did it all (with no remote events), which I put in the StartGui. I got some help with it to understand that I need to use Remote Events to accomplish this. So, I took the code from the original script and tried using Remote Events.

I need help with the scripts I made to do this, as they’re not doing anything when I click the “Start Race” button, even though there are no apparent errors in the output. I’m likely doing something wrong with the Remote Events and how I integrated them, as I’m new to them.

Here’s a screenshot of the Explorer, and the script and localscript I’m using.

image

In Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("RemoteEventCountdown")

local text = game.StarterGui.ScreenGui.Countdown
local button = game.StarterGui.ScreenGui.StartRace
local seconds = game.ReplicatedStorage.Time

text.Visible = false

button.MouseButton1Click:connect(function(play)
	text.Visible = true
	RemoteEvent:FireAllClients()
end)

In LocalScript:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("RemoteEventCountdown")

RemoteEvent.OnClientEvent:connect(function()

local text = game.StarterGui.ScreenGui.Countdown
local button = game.StarterGui.ScreenGui.StartRace
local seconds = game.ReplicatedStorage.Time

text.Text = seconds.Value -- Makes the text in the TextLabel the same as what is in the "Time" Value under ScreenGui.

--text.Visible = false

local function PreStage()
	
	local prestagelights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.PreStageLights:FindFirstChildOfClass("PointLight")
	local prestagelightsparts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.PreStageLights:GetChildren()
	
for _, prestagelightsparts in pairs(prestagelightsparts) do
   
    if prestagelights then
        prestagelights.Enabled = true
    end
end

for _, prestagelightsparts in pairs(prestagelightsparts) do
    prestagelightsparts.Material = Enum.Material.Neon
	end
end


local function Stage()
	
	local stagelights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.StageLights:FindFirstChildOfClass("PointLight")
	local stagelightsparts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.StageLights:GetChildren()
	
for _, stagelightsparts in pairs(stagelightsparts) do
   
    if stagelights then
        stagelights.Enabled = true
    end
end

for _, stagelightsparts in pairs(stagelightsparts) do
    stagelightsparts.Material = Enum.Material.Neon
	end
end


local function Red()
	local RedLights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.RedLights.Lights:FindFirstChildOfClass("PointLight")
	local RedLightsParts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.RedLights.Lights:GetChildren()
	
for _, RedLightsParts in pairs(RedLightsParts) do
   
    if RedLights then
        RedLights.Enabled = true
    end
end

for _, RedLightsParts in pairs(RedLightsParts) do
    RedLightsParts.Material = Enum.Material.Neon
	end
end


local function Yellow()
	local YellowLights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.YellowLights.Lights:FindFirstChildOfClass("PointLight")
	local YellowLightsParts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.YellowLights.Lights:GetChildren()
	
for _, YellowLightsParts in pairs(YellowLightsParts) do
   
    if YellowLights then
        YellowLights.Enabled = true
    end
end

for _, YellowLightsParts in pairs(YellowLightsParts) do
    YellowLightsParts.Material = Enum.Material.Neon
	end
end


local function Green()
	local GreenLights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.GreenLights.Lights:FindFirstChildOfClass("PointLight")
	local GreenLightsParts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.GreenLights.Lights:GetChildren()
	
for _, GreenLightsParts in pairs(GreenLightsParts) do
   
    if GreenLights then
        GreenLights.Enabled = true
    end
end

for _, GreenLightsParts in pairs(GreenLightsParts) do
    GreenLightsParts.Material = Enum.Material.Neon
	end
end



local function Countdown() -- Makes the countdown code into a local function.
	
text.Visible = true

if seconds.Value == 5 then
	PreStage()
end

while seconds.Value > 0 do
	seconds.Value = seconds.Value - 1
	wait(1)
 script.Parent.Text = seconds.Value -- Makes the TextLabel countdown from whatever number is in the "Time" Value under ScreenGui.

if seconds.Value == 3 then
	Stage()
end

if seconds.Value == 2 then
	Red()
end

if seconds.Value == 1 then
	Yellow()
end

if seconds.Value == 0 then
	script.Parent.Text = "GO!"
	Green()
end

if script.Parent.Text == "GO!" then
	wait(1)
	text.Visible = false
	end 
end
-- Waits for _ seconds, and then makes the TextLabel not visible.

end

end)
1 Like

A couple issues here

local text = game.StarterGui.ScreenGui.Countdown
local button = game.StarterGui.ScreenGui.StartRace

You’re using starterGui rather than the actual player Gui. The Guis that users see on the screen are NOT in the StarterGui. They are instantly replicated from the StarterGui into every player’s “PlayerGui” (located within the player). The most ideal way to handle this would be to just have a local script inside the GUI, so you can reference the GUI with “script.Parent” or whatever. Notice how I said local script, because it is more optimal to run LocalScripts on Guis so that everything is handled only on a client-to-client basis.

The second issue I notice is that your “onClientEvent” function never runs. All you do is define functions in it, but never actually run the functions.

Try fixing these two things and let me know if the problem still persists, then I’ll take a deeper look into your script.

I completely forgot about the first thing you noticed, even though I’ve ran into the same problem before. :man_facepalming: So would I change it to this?:

local text = game.PlayerGui.ScreenGui.Countdown
local button = game.PlayerGui.ScreenGui.StartRace

And for the second thing you mentioned, how do I run the “onClientEvent” function? I thought that the “RemoteEvent:FireAllClients()” in the Script is supposed to fire it. By the way, I’ve only been doing Roblox Lua scripting for about 3 weeks now, and I’m new to the concept of RemoteEvents. Thanks very much for help!

local text = game.PlayerGui.ScreenGui.Countdown
local button = game.PlayerGui.ScreenGui.StartRace

Not quite. What Roblox does is, every time a player joins, things in the “StarterGui” are replicated (cloned and then moved) into the player’s PlayerGui. When you join the game in Studio, go into the explorer and go to Players > MJTFreeTime, and you will see there is “PlayerGui.” Every player has their own PlayerGui. This means that it is best to handle GUIs with a local script that is inside of the Gui (because if it were server sided, you would have 1 script that will constantly need to control the Guis of a large number of people). What I recommend you do is that you remove this “server to client” communication entirely and just run this script fully locally. Or, you could switch the two functions around, since it would make more sense for the “Red(),” “Countdown(),” etc. functions to be run on the server while the Gui handler is run on the client.

When I said your functions aren’t running, it had nothing to do with your use of onClientEvent or FireAllClients()-- you are using both of those correctly. The issue was that you were only defining the functions (you were writing local function something() end) but never actually called the function in the script.

Ohhhh man I completely missed that!

About running it locally, the problem with that is that I want all players in the game to have the countdown show up. That’s why I ended up trying to use Remote Events.

When you say to have the GUI handler on the local script, would I just switch the code out between the server and local script? I did find a problem with that a few days ago, where you can’t use “FireAllClients()” if you’re firing from a local script to a server script.

Is there a way you’d recommend I try to switch out the GUI handler to be the local script? Thanks very much.

I think Chatowillwin is referring to the fact that you didn’t call the Countdown() function.

Also, I agree, since everyone will be viewing the countdown of stoplights in the workspace, you should use a server script to set it up.

So, the GUI handler would just be responsible for detecting if someone clicked it. It would fire an event that triggers the countdown on the server.

Yeah, I got the part where he said that I forgot to call the Countdown() function.

If I used a localscript in the GUI to be the GUI handler and detect if someone clicked it, like what my server script is doing, my question is, how would I do that while being able to do FireAllClients()? As I was saying before, from what I understand, FireAllClients() can only be used from a serverscript to a localscript.

I did find something interesting that seems like a bit of a workaround. Here: Why will not FireAllClients() work? - Scripting Helpers

Thanks.

Is this the sorta thing you’re talked about doing?

Just pseudocode, the idea of it:

Ah, I wasn’t thinking about the fact that you need to fire all clients after clicking a screenGUI button. I suppose what you could do is have the local script handle the Click, have it fire a remote event to the server, and the server could then do :FireAllClients() back to the client which would, then, start the countdown and stuff. Definitely not the most efficient way, though. I wish I could think of something better. It’d be nice if Roblox allowed you to do :FireAllClients from the client, but you aren’t able to.

2 Likes

Another way to do it, is to have a boolValue in either workspace or replicated storage.
Whenever some clicks the start game, you would change the boolValue to True.
Then in your local script, you would detect that the bool Value has changed, check if the new value is true and if it is, then you would hide the Gui (this is the local script in your Gui).
I think this is another way to set up this event.

1 Like

Oh thats a smart way to do it. Thanks for the suggestion! I’ll test both ways out later when I get on my PC.

First I’m trying the 3 RemoteEvent approach. I’ve been trying to do this, but when I click the Start Race button it doesn’t do anything. I also, just now, tried placing the two server scripts inside of StarterPlayer—StarterPlayerScripts, but still got nothing.

Here’s a screenshot of the explorer, and the scripts I’ve been trying to make work so far:

Explorer Screenshot:
image

Server Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent1 = ReplicatedStorage:WaitForChild("RemoteEventCountdown")
local RemoteEvent2 = ReplicatedStorage:WaitForChild("RemoteEventCountdown2")

RemoteEvent1.OnServerEvent:Connect(function(play)
	
	RemoteEvent2:FireAllClients(play)
	
end)

LocalScript:

local LocalPlayer = game.Players:WaitForChild("LocalPlayer")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent1 = ReplicatedStorage:WaitForChild("RemoteEventCountdown")
local RemoteEvent2 =  ReplicatedStorage:WaitForChild("RemoteEventCountdown2")

local button = LocalPlayer.PlayerGui.ScreenGui.StartRace

button.MouseButton1Click:connect(function(play)
RemoteEvent1:FireServer(play) 
end)

LocalScript2:

local LocalPlayer = game.Players:WaitForChild("LocalPlayer")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent1 = ReplicatedStorage:WaitForChild("RemoteEventCountdown")
local RemoteEvent2 = ReplicatedStorage:WaitForChild("RemoteEventCountdown2")


RemoteEvent2.OnClientEvent:Connect(function()
	
	
local text = LocalPlayer.PlayerGui.ScreenGui.Countdown
local button = LocalPlayer.PlayerGui.ScreenGui.StartRace
local seconds = ReplicatedStorage:WaitForChild("Time")

text.Text = seconds.Value -- Makes the text in the TextLabel the same as what is in the "Time" Value under ScreenGui.

text.Visible = false

local function PreStage()
	
	local prestagelights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.PreStageLights:FindFirstChildOfClass("PointLight")
	local prestagelightsparts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.PreStageLights:GetChildren()
	
for _, prestagelightsparts in pairs(prestagelightsparts) do
   
    if prestagelights then
        prestagelights.Enabled = true
    end
end

for _, prestagelightsparts in pairs(prestagelightsparts) do
    prestagelightsparts.Material = Enum.Material.Neon
	end
end


local function Stage()
	
	local stagelights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.StageLights:FindFirstChildOfClass("PointLight")
	local stagelightsparts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.StageSigns.StageLights:GetChildren()
	
for _, stagelightsparts in pairs(stagelightsparts) do
   
    if stagelights then
        stagelights.Enabled = true
    end
end

for _, stagelightsparts in pairs(stagelightsparts) do
    stagelightsparts.Material = Enum.Material.Neon
	end
end


local function Red()
	local RedLights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.RedLights.Lights:FindFirstChildOfClass("PointLight")
	local RedLightsParts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.RedLights.Lights:GetChildren()
	
for _, RedLightsParts in pairs(RedLightsParts) do
   
    if RedLights then
        RedLights.Enabled = true
    end
end

for _, RedLightsParts in pairs(RedLightsParts) do
    RedLightsParts.Material = Enum.Material.Neon
	end
end


local function Yellow()
	local YellowLights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.YellowLights.Lights:FindFirstChildOfClass("PointLight")
	local YellowLightsParts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.YellowLights.Lights:GetChildren()
	
for _, YellowLightsParts in pairs(YellowLightsParts) do
   
    if YellowLights then
        YellowLights.Enabled = true
    end
end

for _, YellowLightsParts in pairs(YellowLightsParts) do
    YellowLightsParts.Material = Enum.Material.Neon
	end
end


local function Green()
	local GreenLights = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.GreenLights.Lights:FindFirstChildOfClass("PointLight")
	local GreenLightsParts = game.Workspace["Racing System"]["Countdown Lights"].RaceTimer3.GreenLights.Lights:GetChildren()
	
for _, GreenLightsParts in pairs(GreenLightsParts) do
   
    if GreenLights then
        GreenLights.Enabled = true
    end
end

for _, GreenLightsParts in pairs(GreenLightsParts) do
    GreenLightsParts.Material = Enum.Material.Neon
	end
end



local function Countdown() -- Makes the countdown code into a local function.
	
text.Visible = true

if seconds.Value == 5 then
	PreStage()
end

while seconds.Value > 0 do
	seconds.Value = seconds.Value - 1
	wait(1)
 script.Parent.Text = seconds.Value -- Makes the TextLabel countdown from whatever number is in the "Time" Value under ScreenGui.

if seconds.Value == 3 then
	Stage()
end

if seconds.Value == 2 then
	Red()
end

if seconds.Value == 1 then
	Yellow()
end

if seconds.Value == 0 then
	script.Parent.Text = "GO!"
	Green()
end

if script.Parent.Text == "GO!" then
	wait(1)
	text.Visible = false
			end 
			Countdown()
end
		-- Waits for _ seconds, and then makes the TextLabel not visible.

end
	
end)

end
	
end)

Thanks for the help!

Okay, you’re now making everything much more complicated, I can’t really even understand the scripts you sent since they’re all over the place. So let’s start fresh and rethink how the script is supposed to work.

All you will need to do is this (like I said, maybe there’s a more efficient way but this is what comes to my head.)

1 local script. The script will do this:

button.MouseButton1Click:Connect(function()
RemoteEvent:FireServer()
end)

Then, a server script. It’ll do this:

RemoteEvent.OnServerEvent:Connect(function()
RemoteEvent:FireAllClients()
end)

Then, on the SAME local script mentioned before, you will want:

RemoteEvent.OnClientEvent:Connect(function()
-- Countdown and all of the other stuff you wanted
end)

Remember, in the LocalScript when you reference the GUI, make sure you use :WaitForChild() and stuff. Or, you could just insert the local script right into the GUI so you can make a script.Parent type of path instead.

2 Likes

Hey, that’s a much better way to work with it, thanks. I did it that way, but it still didn’t work. Keyword: “didn’t”.

It finally worked! Turns out, I simply called the “Countdown()” before the wrong “end”. I just called the countdown function in the function by accident lol.

Thanks so much you guys for helping me out! There’s still a couple things I gotta try to do to the countdown, but I’ve been struggling with this problem for over a week.

Big Thanks,

Matthew

1 Like