Hello, I recently wondered how to get an accurate or very close to the truth value of a player’s ping. The real ping is shown in the panel when you press the key combination Shift+F3.
After reading some topics about this, I learned several common methods, such as:
Using the GetNetworkPing() method, which returns the value in seconds (to get the real ping in ms you need to multiply by 1000). The “main problem” with this method is that it does not give the “accurate” value that we are used to seeing on the panel when pressing Shift+F3. In fact, this is not quite so… Read the post from @ramblinwrek if you want to know why. (The “error” of these measurements with the real ping according to my calculations was 20-30 ms)
By using RemoteEvent or RemoteFunction by transmitting timestamps from the client to the server and vice versa, or waiting for a response from the server, also receiving timestamps with the calculation of the difference between them on the client, which will be the ping. (The error of these measurements with the real ping according to my calculations was 5-10 ms)
I took the idea from this post from @CDDevelopment literally translating his words into code… (The error of these measurements with the real ping according to my calculations was less than 1-3 ms)
Let’s create a RemoteEvent or UnreliableRemoteEvent(which is much better than the first) in ReplicatedStorage and name it PingEvent. After that, we will create LocalScript in ReplicatedFirst and Script in ServerScriptService. Finally, create a NumberValue in Workspace, naming it PingDT.
Place the code below in LocalScript:
if not game:IsLoaded() then
game.Loaded:Wait()
end
local PingDT = workspace.PingDT
local PingEvent = game:GetService('ReplicatedStorage').PingEvent
PingEvent.OnClientEvent:Connect(function(LastServerPingDT: number)
task.wait()
local DTDifference = PingDT.Value-LastServerPingDT
PingEvent:FireServer(DTDifference, PingDT.Value)
end)
Place the code below in Script:
local PingDT = workspace.PingDT
local RunService = game:GetService('RunService')
local PingEvent = game:GetService('ReplicatedStorage').PingEvent
RunService.Heartbeat:Connect(function(DT)
PingDT.Value += DT
end)
PingEvent.OnServerEvent:Connect(function(Player, DTDifference: number, LastClientPingDT: number)
local Ping = math.floor((PingDT.Value-LastClientPingDT+DTDifference)*100000)/100
print('Ping: '..Ping..' ms')
end)
while task.wait(.5) do
PingEvent:FireAllClients(PingDT.Value)
end
Congratulations, you now have a system for determining a accurate player’s ping!
Demonstration
Perhaps you will ask the question, where is the declared high measurement accuracy and why in some moments the error is extremely high? This is due to the fact that I was recording a video and perhaps this somehow affected the quality of the Internet connection. Also used RemoteEvent instead of UnreliableRemoteEvent, which was not a very good decision…
You could use workspace:GetServerTimeNow() to check the difference in ping.
Since the value is time epoc so it can be used to check the difference in time between the server and client similliar to how you checked the difference with PingDt. This will give an accurate ping difference between the server and the client .
I’ve done some tests on your suggestion to replace RemoteEvent with UnreliableRemoteEvent, I found out that the player’s ping results remain roughly the same everywhere (maybe there’s not much difference since the game isn’t heavily loaded).
But I noticed another difference! It is that there are significantly fewer sharp jumps when measuring ping!
I already wrote about this in the second usual method of getting ping and it gives an error of 5-10 ms. The method that I suggested, and also @Yarik_superpro corrected, gives results much more accurately…
Just a note, but when constantly firing events to clients, you might wanna suggest using a networking library to prevent issues and ensure network stability.
Thanks for the suggestion, I’ll read more about it and take it into account for future developments of this system. I’ll probably update this tutorial with more optimized methods if I can.
For the case of measuring ping, you do not want to do this. Most of the networking libraries available on roblox use optimizations such as ratelimiting that may cause bad results.
Anyways there’s barely and data being send so optimizing this is useless in general
To be honest, this system seems a bit confusing to me too and I can’t explain all its subtleties. (как говорилось: “нет времени объяснять … а дальше ты знаешь ”) The main thing is that it works and shows a fairly accurate player ping.
As I said earlier, I simply translated his words into code and that’s it… If you have any questions, I recommend contacting the creator @CDDevelopment of the original post.