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)
Implementation
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 “ServerRunTime”.
Place the code below in LocalScript:
local serverRunTime = workspace:WaitForChild('ServerRunTime')
local pingEvent = game:GetService('ReplicatedStorage'):WaitForChild('PingEvent')
pingEvent.OnClientEvent:Connect(function(lastServerRunTime)
task.wait()
local runTimeValue = serverRunTime.Value
local runTimeDifference = runTimeValue-lastServerRunTime
pingEvent:FireServer(runTimeDifference,runTimeValue)
end)
Place the code below in Script:
local serverRunTime = workspace.ServerRunTime
local pingEvent = game:GetService('ReplicatedStorage').PingEvent
local runService = game:GetService('RunService')
runService.Heartbeat:Connect(function(deltaTime)
serverRunTime.Value += deltaTime
end)
pingEvent.OnServerEvent:Connect(function(player,clientRunTimeDifference,lastClientRunTime)
local ping = math.round((serverRunTime.Value-lastClientRunTime+clientRunTimeDifference)*100000)/100
print(player,' ping: ',ping,' ms')
end)
while true do
pingEvent:FireAllClients(serverRunTime.Value)
task.wait(.5)
end
Congratulations, you now have a system for determining a accurate player’s ping!
Maybe you will ask the question, where is the declared high measurement accuracy and why in some moments the error is extremely high? This happened because I used RemoteEvent instead of UnreliableRemoteEvent, which was not a very good decision. Everything should be fine now.
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.
just have the client send the value to the server, the server just does this instance[property] = value
it syncs it and also makes your game vulnerable >~<
Good idea, only when I put your code in a LocalScript like you said, it gave me an error.
The current thread cannot call ‘GetValue’ (lacking capability Plugin)
I found the answer about it here:
From a technical point of view I agree that your method is a solution, but for now we don’t have the ability to use it in the game through regular scripts, not exploits.