Remote Function: How to deal with latency?

I am having issues when retrieving the most recent data from the server through RemoteFunctions because of the latency issues regarding them, by the time it makes the roundtrip back the data could already be outdated.

I wrote a bit of code below to give an example of when initializing data through a remotefunction could already be outdated by the time it makes it trip back to the client.

Server

-- Localize Globals
local task_wait   = task.wait
local task_defer  = task.defer



-- Services
local ReplicatedStorage = game:GetService 'ReplicatedStorage'
local Players           = game:GetService 'Players'



-- Events
local OnDataUpdated = ReplicatedStorage:WaitForChild 'OnDataUpdated'
local RequestData   = ReplicatedStorage:WaitForChild 'RequestData'



-- Information
local Num = 0



-- Functions
local function onDataRequested()
	
	
	return Num
end



task_defer(function()
	while true do
		Num += 1
		OnDataUpdated:FireAllClients(Num, 'Update')
		task_wait()
	end
end)



-- Connections
RequestData.OnServerInvoke = onDataRequested



Client

-- Services
local ReplicatedStorage = game:GetService 'ReplicatedStorage'



-- Events
local OnDataUpdated = ReplicatedStorage:WaitForChild 'OnDataUpdated'
local RequestData   = ReplicatedStorage:WaitForChild 'RequestData'



-- Information
local CurrentNum = -1



-- Functions
local function UpdateData(num, invokedBy)
	local result
	
	if (num > CurrentNum) then
		CurrentNum = num
		result = 'Updated'
	elseif (num == CurrentNum) then
		result = 'Up to date'
	else
		result = 'Outdated'
	end
	
	print(('%s [%s] (Invoked by: %s)'):format(num, result, invokedBy))
end



-- Connections
OnDataUpdated.OnClientEvent:Connect(UpdateData)
UpdateData(RequestData:InvokeServer(), 'Request')



Output

16:21:15.534  3 [Updated] (Invoked by: Update)  -  Client - LocalScript:28
16:21:15.535  4 [Updated] (Invoked by: Update)  -  Client - LocalScript:28
[[16:21:15.535  5 [Updated] (Invoked by: Update)  -  Client - LocalScript:28]]
16:21:15.925  6 [Updated] (Invoked by: Update)  -  Client - LocalScript:28
16:21:15.926  7 [Updated] (Invoked by: Update)  -  Client - LocalScript:28
[[16:21:15.936  5 [Outdated] (Invoked by: Request)  -  Client - LocalScript:28]]

Any solutions to prevent this would be greatly appreciated!

You cannot do anything to reduce the latency. You have to design your game in such a way that it is resistant to a normal amount of latency.

What kind of data is this? Maybe there’s a better solution

I’m aware that I can’t doing anything to reduce the latency, but I am looking for workarounds so that old data doesn’t overwrite the most recent data.

I have already thought up a couple solutions to prevent this

  • Used a RemoteEvent to let the client know a update has occured then retrieve the data through a RemoteFunction this way all data is retrieved in the order they were called.
  • Timestamp all data sent and compare it to the current data (even though this could go wrong because multiple data can be changed on the same timeframe)
  • Similar to step #2 use a incremented id and compare it to the current data

I made this post entirely to see how people would work around this and possibly give a more elegant solution than what I have thought of.

Any data in general that needs to be displayed on the client

I’m pretty sure RemoteEvents guarantee delivery in order, so you shouldn’t need to check for ordering.

They do, but my worry is when a player joins the server and gets initialization data by the time it makes the trip back it could potentially be outdated.

As you can see in the output section of my post the data was already updated to 7 before the request(5) made it back to the client.

What happens if it does end up outdated?

It would display old data on the client

from the output it would display the most recent data from a brief second then it would display the old data because of the latency.

That sounds fine, no need to fix it. I think players will not be too confused and reasonably understand that the information takes a second to load.

I think you’re misunderstanding the problem, I’ll try to give a example.

Let’s say when a player joins a server they want to retrieve their inventory info from the server, we would a invoke a remotefunction that returns that data back to the client. BUT if that players inventory was to be updated with new information (via RemoteEvent) before that remotefunction made its trip back to the client. That new information would reach the client first before the information we requested would.

Meaning the players inventory will display the data from the remoteevent first then it would be overriden with the data from the remotefunction, leaving the information being displayed outdated.

You would use one or the other, either an Event or Function, not both. For getting the inventory you should choose one based on whether or not something other than the client can change the inventory. The server-to-client remote gives the player their updated inventory, there can be a separate client-to-server event that requests a manual update. If these use the same RemoteEvent instance, then order is enforced and your out of order condition never happens.

Yeah that’s what I been usually using

I would have a RemoteEvent that fires when the player inventory is updated but it wouldn’t send the data over through it.

Then when the client received that event it would invoke a RemoteFunction to retrieve the new inventory data thus keeping all updates in order.

I was only curious to how other people deal with this and maybe shed light on a better alternative.