When a client calls a RemoteFunction to fetch data from the server and the server sends a RemoteEvent to the client at around the same time that the RemoteFunction has reached the server, there is a chance that the server’s RemoteEvent signal will reach the client before the RemoteFunction has returned to the client. This sounds a bit vague so to better illustrate the problem, consider the following example.
Example
When a player joins a game, they may want to ask the server if they can join an ongoing round. The server will have a boolean stored in a script indicating if players are allowed to join the ongoing round. When a player joins, they invoke a RemoteFunction to grab and return this value. When this value changes on the server, the server calls a RemoteEvent for all players with the new value of the boolean. In this example, the player should always have the correct value of the boolean observed on the client.
When the value of the boolean changes on the server while the RemoteFunction is ‘on its way’, one of two cases should happen:
Case 1
- The client calls the RemoteFunction
- The RemoteFunction reaches the server and returns the value ‘false’
- Before the RemoteFunction has returned to the client, the value on the server changes from ‘false’ to ‘true’
- Right after the value changes, the RemoteEvent gets called and sends the value ‘true’ to the client
- The RemoteFunction arrives back at the client and the client sets their stored boolean to ‘false’.
- The RemoteEvent reaches the client with the value ‘true’ and the client now changes their value from ‘false’ to ‘true’.
Case 2
- The client calls the RemoteFunction
- Before the client reaches the server, the boolean on the server changes from ‘false’ to ‘true’
- Right after the value changes, the RemoteEvent gets called and sends the value ‘true’ to the client
- The RemoteFunction reaches the server and returns the value ‘true’
- The RemoteEvent reaches the client with the value ‘true’ and the client now sets their value to ‘true’
- The RemoteFunction arrives back at the client and the client sets their stored boolean to ‘true’, even though it was already set to ‘true’.
However, there is a small chance that case 3 happens, which may cause bugs in your game.
Case 3
- The client calls the RemoteFunction
- The RemoteFunction reaches the server and returns the value ‘false’
- Before the RemoteFunction has returned to the client, the value on the server changes from ‘false’ to ‘true’
- Right after the value changes, the RemoteEvent gets called and sends the value ‘true’ to the client
- The RemoteEvent reaches the client with the value ‘true’ and the client sets their local value to ‘true’
- The RemoteFunction arrives back at the client and the client changes their stored boolean from ‘true’ to ‘false’.
In this third case, the boolean has incorrectly changed to false on the client! RemoteFunctions and RemoteEvents are supposed to arrive in the right order, however in this case they don’t (assuming there are no yields, which there aren’t any in the given example). The RemoteEvent is fired after the RemoteFunction is on its way back to the client but arrives before the RemoteFunction has arrived back!
My friend @Telosmos was kind enough to provide this reproduction file below which shows the problem. Sometimes when you run the file in play solo, the LocalScript will output that stateClient.SpawningEnabled
is set to ‘false’. This should in theory never happen, but it does. It should never happen because there are no yields, the RemoteEvent is fired immediately after the boolean changes on the server, and the RemoteFunction immediately returns the boolean from the server.
Late_RemoteFunction_Repo.rbxl (56.4 KB)
In the reproduction file it may be required to change the for-loop in the server script to wait slightly longer to better line up the requests. In my case I had to change it to loop 20 times. After that, when running the file I sometimes output ‘true’ as the final value and sometimes ‘false’.
In the given file the output should always return ‘true’ however.