Inaccurate timestamp synchronization

Hey !

I try to synchronize the server timestamp for an algorithm.

For the moment I have this code :

            if (!NetworkServer.active)
            {
                newTimestampDelta = netMsg.ReadMessage<IntegerMessage>().value;
                newTimestampDelta += NetworkTransport.GetRemoteDelayTimeMS(client.connection.hostId, client.connection.connectionId, newTimestampDelta, out error);
                newTimestampDelta = (newTimestampDelta - NetworkTransport.GetNetworkTimestamp());
            }

And the Server timestamp is provided by : NetworkTransport.GetNetworkTimestamp() + newTimestampDelta;

But the result is that it’s totally not accurate :

Sometime the difference is > to 20 ms … And so the algorithm become to be broken.

Any idea to synchronize the server timestamp ?

Hello, put this script at the player prefab. Then you can use it by: NetworkTimeManager.GetServerTime(); on both client and server. I also suggest to add a boolean which would allow to access to the Instance only after the time is synced for the first time. Cheers.

/*
-------------------------------------------------------
Developer:  Alexander - twitter.com/wobes_1
Date:       28/10/2017 02:38
-------------------------------------------------------
*/

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

namespace Networking.Management
{
    public class NetworkTimeManager : NetworkBehaviour
    {
        public static NetworkTimeManager Instance;

        private int startTime;
        private int receivedTime;

        public override void OnStartLocalPlayer()
        {
            Instance = this;
        }

        private void Start()
        {
            if (isLocalPlayer)
                StartCoroutine(RequestServerTime());
        }

        private IEnumerator RequestServerTime()
        {
            while (true)
            {
                CmdRequestServerTime();
                yield return new WaitForSeconds(1);
            }
        }

        [Command]
        private void CmdRequestServerTime()
        {
            TargetRpcNetworkTimestamp(connectionToClient, NetworkTransport.GetNetworkTimestamp());
        }

        [TargetRpc]
        private void TargetRpcNetworkTimestamp(NetworkConnection conn, int timestamp)
        {
            receivedTime = NetworkTransport.GetNetworkTimestamp();

            int networkTimestampDelayMS = 0;

            if (isServer)
            {
                networkTimestampDelayMS = 0;
            }
            else
            {
                byte error;

                networkTimestampDelayMS = NetworkTransport.GetRemoteDelayTimeMS(
                    NetworkManager.singleton.client.connection.hostId,
                    NetworkManager.singleton.client.connection.connectionId,
                    timestamp,
                    out error);
            }

            startTime = timestamp + networkTimestampDelayMS;
        }

        public static double GetServerTime()
        {
            if (NetworkClient.active)
            {
                return (Instance.startTime + (NetworkTransport.GetNetworkTimestamp() - Instance.receivedTime)) / 1000.0;
            }
            else if (NetworkServer.active)
            {
                return NetworkTransport.GetNetworkTimestamp() / 1000.0;
            }
            else
            {
                return 0;
            }
        }

        public override int GetNetworkChannel()
        {
            return Channels.DefaultUnreliable;
        }
    }
}

Result (In Seconds) the difference is 1-3 ms because of the OnGUI() timing:

EDIT: Test results of sending a command in order to check the time, for example for shooting in order to know when exactly the client shot.

Snip for testing purpose, hit the Space bar on the client and take a look into the server debug log:

        private void Update()
        {
            if (isLocalPlayer)
            {
                if (Input.GetKeyDown(KeyCode.Space))
                {
                    CmdCheckTime(GetServerTime(), NetworkTransport.GetNetworkTimestamp());
                }
            }
        }

        [Command]
        private void CmdCheckTime(double v, int timestamp)
        {
            Debug.Log("Client command time: " + v.ToString("F4"));

            byte error;
            int networkTimestampDelayMS = NetworkTransport.GetRemoteDelayTimeMS(
                 connectionToClient.hostId,
                 connectionToClient.connectionId,
                 timestamp,
                 out error);

            int time = NetworkTransport.GetNetworkTimestamp() - networkTimestampDelayMS;
            double serverTime = time / 1000.0;

            Debug.Log("Server rewind time: " + serverTime.ToString("F4") + " Delay: " + networkTimestampDelayMS + "ms");
            Debug.LogError("Current server time: " + GetServerTime().ToString("F4"));
        }
1 Like

Yeah fine. I also get 3 ms of difference on standalone .exe.

Strange behaviour on Editor i get 20ms …; but ok fine.

No way to get a similar connectionToClient on GameObject not player ? It will be fine if the server timestamp doesn’t have to be sync.

They are actually synced properly. Did you test it? Apparently not. The OnGUI() Screenshot doesn’t count as test.

Strange behaviour with Unet.

Based on your code I totally remote the timestamp sync and calcul the difference with RemotDelayMS.

But client-> server have small delay like :

And server->client higher delay like : 3289857--254749--upload_2017-11-16_15-55-33.png

Why a such difference between client → server and server → client ?

Ok never mind. I fixed it by calling NetworkServer.MaxDelay = 0.01f :slight_smile:

Next time, before calling something “strange” or “not working” check your configuration. Thanks.