So i have 2 remote events in replicated storage: Event2 and RemoteEvent
I also have a simple client script:
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.X then
game.ReplicatedStorage.RemoteEvent:FireServer()
elseif input.KeyCode == Enum.KeyCode.Z then
game.ReplicatedStorage.Event2:FireServer()
end
end)
After pressing X and then Z i expect nothing to happen because for the RemoteEvent to fire Event2 has to be fired before it, not after. For some reason RemoteEvent is being fired and 1 is getting printed AND 2 is getting printed after it. So for some reason the RemoteEvent fires as soon as it is summoned. Why?
(2 and 1 are printed the same exact moment)
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.X then
game.ReplicatedStorage.RemoteEvent:FireServer()
elseif input.KeyCode == Enum.KeyCode.Z then
game.ReplicatedStorage.Event2:FireServer()
end
end)
server
game.ReplicatedStorage.Event2.OnServerEvent:Connect(function()
local remoteEvent = game.ReplicatedStorage.RemoteEvent
local connection
connection = remoteEvent.OnServerEvent:Connect(function()
print(1)
connection:Disconnect() -- Disconnect the event after it's fired once
end)
print(2)
end)
This behavior is occurring as a result of the āinvocation queueā. When a RemoteEvent is fired, it creates a queue of inbound events. I donāt recall the exact behavior off the top of my head, but essentially what is happening here:
You press X. An event is added to the āRemoteEventā invocation queue. Then, you press Z. āRemoteEventā is connected, and it can now process its queue. Since it is synchronous and is connected before print(2), it will run print(1) before proceeding.
You can further see this behavior by pressing X several times. Upon pressing Z, youāll notice print(1) will execute the same number of times you pressed X.
The easiest way to fix this behavior is to avoid putting event connections inside of other event connections. Keep them top-level, and then handle the logic inside the connection itself.
I think i understand and i think i found 2 solutions for that (it would be difficult to have the events on the top level):
Putting a timer so for example the event cannot be fired the first 2 miliseconds and would automaticaly stop after 50 miliseconds passed so it wouldnt have a bad effect on the server.
game.ReplicatedStorage.Event2.OnServerEvent:Connect(function()
local TimerStopped = false
local TimerAmount = 0
task.spawn(function()
while not TimerStopped do
TimerAmount += 1
task.wait()
end
end)
game.ReplicatedStorage.RemoteEvent.OnServerEvent:Once(function()
print(TimerAmount)
if TimerAmount - 2 > 0 then
TimerStopped = true
print("Second event fired")
end
end)
print("First event fired")
end)
Creating another empty event before the main event is fired so it unloads the que. It seems more efficient in terms of performace and overall cleaner but could im not sure if it could affect other players experience.
Both of these solutions seem a bit hacky. Iād be especially hesitant to use the first one because timing can be inconsistent. The second solution is somewhat unpredictable, potentially firing the second event multiple times with only one corresponding Z press.
I donāt know your exact use-case, but hereās my general recommendation, keeping the connections top-level. This also ensures that there can be, at most, 1 āresponseā (X key processing) for any given Z press:
local awaitingResponse = false
Event2.OnServerEvent:Connect(function()
awaitingResponse = true
print(2)
end)
RemoteEvent.OnServerEvent:Connect(function()
if awaitingResponse then
awaitingResponse = false
print(1)
end
end)