(Demo of system, notice how the virtual client and server are synced to within a millisecond; watch full video here: https://www.youtube.com/watch?v=YGYGRquqi-c&feature=youtu.be)
Have you ever wanted to synchronize events between clients and the server, but found that tick() returns completely different values on different machines, os.time() simply isn’t accurate enough, and simply triggering an event via remote events results in clients receiving events at inconsistent timings? In that case, this system is for you!
Check it out on github: https://github.com/Kenji-Shore/Roblox-Client-Server-Time-Sync-Module
This system provides incredibly high accuracy (I have measured a consistent ~1 ms accuracy in normal conditions), so much so that this can even be used for things that demand incredibly high precision, like synchronizing a bullet flying through the air on multiple clients.
How do I know it works?
Proving the accuracy of a clock syncing technology is a very difficult task because there is no perfectly synced clock to act as a baseline for comparison. So, I’ve come up with some clever ways to engineer and perfect this system.
- Firstly, I have observed that when you simulate a client and server in Play Solo, tick() is perfectly in sync for both the client and server. I used this knowledge to first extensively study Roblox’s networking behavior, discovering how Roblox fires off signals in larger packages which happen every few frames.
- To prove this system’s capabilities in a more realistic scenario, I’ve created a test where I run a virtual client and server (not Play Solo) and I visualize the two clocks in two side by side windows. I’ve recorded a video of this, and you can advance through the video frame by frame to observe the accuracy of the system: https://www.youtube.com/watch?v=YGYGRquqi-c&feature=youtu.be
Some extra knowledge on Roblox netcode
In a nutshell, Roblox does not fire a signal between a client and server the instant you fire a remoteevent or function; instead, what happens is Roblox waits a few frames and pools together multiple remote firings into one larger package. This is fine, as it prevents network overload and also guarantees packet ordering and delivery, but unfortunately we have no way of knowing exactly when this package gets sent, making it very difficult to make high precision clock syncing. To make a proper high precision synced clock, you must be able to offset this extra delay, which is exactly what I do. There is special logic that does a very good job at guessing what this unknown delay will be every frame on the client and the server.