Remote event not firing

When I try to start a local server for my game and fire a remote event from 2 of the clients at about the same time, the event doesn’t fire for one of them while the other one works fine. Here is my code:

if ison.Value == false then 
			levelstat:FireServer(stage)
		else
			ec.Value = false
			levelstat:FireServer(stage)  
			game.Players.LocalPlayer.CharacterAdded:Connect(function() 
				if deathcheck.Value == false then
					starttimer:FireServer(game.Players.LocalPlayer)   
				end
			end)

		end

This is inside of a gui. Im not sure whats wrong but none of the code in the onserverevent function will run for the 2nd client

1 Like

The issue is likely more to do with the server code. However, it seems that you’re using remotes inefficiently.

Also unrelated, but you don’t need to do ison.Value == false, you can just do if not ison.Value. An if statement will simply check if the statement is true or false. It works even with an object/variable to see if it exists or not.

Can you explain what you mean when you say I’m using them inefficiently? Also I don’t understand how the server code could be the issue since one of them does run the server code, but the other one doesn’t run through a single line of it so I assumed it never got there.

I don’t have access to your project, so I don’t really have enough information to help. Debugging is a part of development that can be rather difficult and requires a certain way of thinking, as most debugging has nothing to do with errors.

You should find out exactly where it stops, then look at all code related to that, including external scripts. Considering you’re using if statements, it’s likely that the conditions aren’t being met. You’ll need to test things out until you find out exactly where and what the issue is.

Also as far as efficiency goes, again it’s hard to say without knowing everything you’re doing, but it seems that you’re using a lot of remotes for things that don’t appear to be necessary. Things such as the start timer could be tracked from the server with no remote at all. I’m not sure what levelstat is, but if it’s gui related, that’s probably fine.

I guess what I’m trying to say is that you should minimize the amount of requests you make. The reason for this is both to keep the network as free as possible, but also to avoid desynchronization. In which values may not be consistent due to things occurring at de-serialized times (not exclusively one after the other). This problem also exists with parallel processing (called parallel lua in Roblox). RemoteFunctions are better in that they yield the client until the server returns a value.

I am turning this more into an unrelated rant than anything, but basically, keep your usage of remotes to a minimum.

1 Like

How would I track something from the server without an event, I’m basically firing that event on the click of a gui button, so how else would I do that?

As far as this shows anyway, you’re doing it when the local player’s character is added, not anything related to a gui?

Either way, you should find continue debugging until you find the issue before doing anything else.

I haven’t shown the full code but that code is inside a mouse button up function. Also I don’t wanna go back later cause I ran into the issue you were talking about, but does that mean it’s fine since it’s for a gui?

From what I know so far, it also seems that your character added event is within another event.

While this isn’t technically exactly the same as parallel processing, it’s also not directly one after the other. An event is similar to task.spawn(), in which a new simulated thread is created, which works at its own time, instead of pausing the rest of the script.

Why does this matter? In this case, it probably doesn’t. The part that matters is that it creates a new thread each time. When you have an event within an event, that means that the nested event will be created each time the first event is triggered. This means that if the first event, such as a button click, is triggered twice, now you have two events listening for the character spawning, which will both execute their own code separately.

There is a solution for this, and it’s called Disconnect(). Either that or just not putting events inside of other events. You can also wait for an event with Event:Wait(), but that will yield indefinitely until the event is fired once.

Here’s an example of how to use Disconnect() and some other cleanup:

local Players = game:GetService('Players')
local characterAddedEvents = {}
Players.PlayerRemoving:Connect(function(player)
	local event = characterAddedEvents[player.Name]
	if event then
		event:Disconnect()
		characterAddedEvents[player.Name] = nil
	end
end)
Players.PlayerAdded:Connect(function(player)
	characterAddedEvents[player.Name] =  player.CharacterAdded:Connect(function(character)
		local died
		died = character:WaitForChild('Humanoid').Died:Connect(function()
			died:Disconnect()
			print(player.Name..': has died!')
			--do stuff
		end)
	end)
end)

Good chance CharacterAdded has already fired for that player instance before you attempt to wait for it to fire (which will cause the entire script to yield), could you perhaps provide the entire script?

player.Character:Connect(function(character)

This would error, you can’t call the event connection instance method “:Connect()” on a non-event instance (in this case the player’s character, which is a “Model” instance).

I meant CharacterAdded, I’m a bit used to Studio’s autocomplete. But thanks for pointing that out.

Here is the full code, and also the server code

button.MouseButton1Up:Connect(function() 
	if script.Parent.Locked.Visible == false then
		if ison.Value == false then 
			levelstat:FireServer(stage)
		else
			ec.Value = false
			levelstat:FireServer(stage)  
			game.Players.LocalPlayer.CharacterAdded:Connect(function() 
				if deathcheck.Value == false then
					starttimer:FireServer(game.Players.LocalPlayer)   
				end
			end)

		end

	end
end)

server

local rs = game:GetService("ReplicatedStorage")
local starttimer = rs:WaitForChild("StartTimer")
local timecheck = rs:WaitForChild("EndCheck")
local endtime = rs:WaitForChild("EndTimer")
local dc = rs:WaitForChild("DeathCheck")
local ct = rs:WaitForChild("ClientTimer")
local st = rs:WaitForChild("SaveTime")
local sy = rs:WaitForChild("SaveYes")
 
local milliseconds = 0
local seconds = 0
starttimer.OnServerEvent:Connect(function(player)
	ct:FireClient(player) 
	timecheck.Value = false
	dc.Value = true
	print("b")   
	local Value = 0
	local Time = os.clock()
	while timecheck.Value == false do 
		wait()
		Value = os.clock() - Time 
		seconds = math.floor(Value % 10000)
		milliseconds = (Value % 1)*100
		local timevalue = string.format("%.2d.%.2d", seconds, milliseconds) 
		print(timevalue)
	end  
	sy:FireClient(player)
	endtime:FireClient(player, seconds, milliseconds)
	st.OnServerEvent:Connect(function(player)
		local sec = Instance.new("IntValue")
		local mil = Instance.new("IntValue")
		sec.Parent = game.Workspace.Times
		mil.Parent = game.Workspace.Times
		sec.Value = seconds
		mil.Value = milliseconds
	end)
	timecheck.Value = false 
end)

I know this code is pretty messy and not well written so ill have to apologize for that, also I didn’t know to keep remote usage to a minimum.

did you try FireAllClients instead of FireClient on server side script?

What would fireallclients do? I’m assuming it fires the event to every client but I only want it to fire to the specific client that clicks the gui, either way the server script isn’t being run when the2nd client fires it so that isn’t being run for the 2nd client at the moment anyways.

I’m not entirely sure what you mean, can you explain how I can use that here? Also I’m not sure if you’re saying that’s how I should fix my problem, or if that’s also another thing I should do.

Can you explain what you mean by “before you attempt to wait for it to fire”?

Remotes usually return the player as a start point so adding game.Players.LocalPlayer as an argument is pointless.

game.Players.LocalPlayer.CharacterAdded:Connect(function() 

When this line of code is executed you are essentially instructing the script to wait (yield) until the “CharacterAdded” event has fired for the local player (this event is fired whenever the player’s character is added). If this event has already fired before that line of code is executed then the script will end up yielding indefinitely (halting) as it is waiting for an event to fire which has already fired.

Yea that makes sense, but then why is one of them working properly? When I fire level stat it kills the player immediately so the event should fire at the same time.

Also just found out that whichever one of those players that gets the timer is, always gets the timer if u reset them both and try again while the other one never gets it, even if u only fire the client that doesn’t get the timer, so the issue isnt about the same time, one of them just never has the timer.