Search Unity

UNET Network.time

Discussion in 'UNet' started by Deleted User, Aug 11, 2017.

  1. Deleted User

    Deleted User

    Guest

    Hi there, any ideas how to proper get Network.time on UNET?

    This is what I got but it's not accurate. P.S Modified code from that post: https://forum.unity3d.com/threads/how-to-sync-network-time.395809/

    Code (CSharp):
    1.  
    2. /*
    3. -------------------------------------------------------
    4.  Developer:  Alexander - twitter.com/wobes_1
    5.  Date:       10/08/2017 21:15
    6. -------------------------------------------------------
    7. */
    8.  
    9. using System;
    10. using System.Collections;
    11. using System.Collections.Generic;
    12. using UnityEngine;
    13. using UnityEngine.Networking;
    14.  
    15. public class NetworkedPlayer : NetworkBehaviour
    16. {
    17.     public bool isNetworkTimeSynced = false;
    18.  
    19.     // timestamp received from server
    20.     private float networkTime;
    21.  
    22.     // server to client delay
    23.     private int networkTimestampDelayMS;
    24.  
    25.     // when did we receive timestamp from server
    26.     private float timeReceived;
    27.  
    28.     protected virtual void Start()
    29.     {
    30.         if (isLocalPlayer)
    31.         {
    32.             CmdRequestTime();
    33.         }
    34.     }
    35.  
    36.     [Server]
    37.     private void Update()
    38.     {
    39.         if (Input.GetKeyDown(KeyCode.Space))
    40.         {
    41.             int timestamp = NetworkTransport.GetNetworkTimestamp();
    42.             TargetRpcCheck(connectionToClient, Time.time, timestamp);
    43.         }
    44.     }
    45.  
    46.     [TargetRpc]
    47.     void TargetRpcCheck(NetworkConnection conn, float time, int timestamp)
    48.     {
    49.         byte error;
    50.         var delay = NetworkTransport.GetRemoteDelayTimeMS(
    51.             NetworkManager.singleton.client.connection.hostId,
    52.             NetworkManager.singleton.client.connection.connectionId,
    53.             timestamp,
    54.             out error);
    55.  
    56.         Debug.Log(delay);
    57.         float actualTime = time + (delay / 1000f);
    58.  
    59.         Debug.Log("Server time " + actualTime);
    60.         Debug.Log("Client time " + GetServerTime());
    61.     }
    62.  
    63.     [Command]
    64.     private void CmdRequestTime()
    65.     {
    66.         int timestamp = NetworkTransport.GetNetworkTimestamp();
    67.         RpcNetworkTimestamp(Time.time, timestamp);
    68.     }
    69.  
    70.     [ClientRpc]
    71.     private void RpcNetworkTimestamp(float time, int timestamp)
    72.     {
    73.         isNetworkTimeSynced = true;
    74.         networkTime = time;
    75.         timeReceived = Time.time;
    76.  
    77.         // if client is a host, assume that there is 0 delay
    78.         if (isServer)
    79.         {
    80.             networkTimestampDelayMS = 0;
    81.         }
    82.         else
    83.         {
    84.             byte error;
    85.             networkTimestampDelayMS = NetworkTransport.GetRemoteDelayTimeMS(
    86.                 NetworkManager.singleton.client.connection.hostId,
    87.                 NetworkManager.singleton.client.connection.connectionId,
    88.                 timestamp,
    89.                 out error);
    90.         }
    91.     }
    92.  
    93.     public float GetServerTime()
    94.     {
    95.         return networkTime + (networkTimestampDelayMS / 1000f) + (Time.time - timeReceived);
    96.     }
    97. }
    98.  


     
    Last edited by a moderator: Aug 11, 2017
  2. Deleted User

    Deleted User

    Guest

    Update: possible reason is NetworkTransport.GetRemoteDelayTimeMS() which is returned strange results.

    Code (CSharp):
    1.  
    2. /*
    3. -------------------------------------------------------
    4.  Developer:  Alexander - twitter.com/wobes_1
    5.  Date:       10/08/2017 21:15
    6. -------------------------------------------------------
    7. */
    8.  
    9. using System;
    10. using System.Collections;
    11. using System.Collections.Generic;
    12. using UnityEngine;
    13. using UnityEngine.Networking;
    14.  
    15. public class NetworkedPlayer : NetworkBehaviour
    16. {
    17.     public const short SimpleMessageId = MsgType.Highest + 1;
    18.     public class SimpleMessage : MessageBase
    19.     {
    20.         public int timestamp;
    21.     }
    22.  
    23.     public override void OnStartLocalPlayer()
    24.     {
    25.         NetworkManager.singleton.client.RegisterHandler(SimpleMessageId, OnMessageReceived);
    26.     }
    27.  
    28.     [ServerCallback]
    29.     private void Update()
    30.     {
    31.         if (Input.GetKeyDown(KeyCode.Space))
    32.         {
    33.             SimpleMessage msg = new SimpleMessage();
    34.  
    35.             msg.timestamp = NetworkTransport.GetNetworkTimestamp();
    36.             connectionToClient.Send(SimpleMessageId, msg);
    37.         }
    38.     }
    39.  
    40.     private void OnMessageReceived(NetworkMessage netMsg)
    41.     {
    42.         var msg = netMsg.ReadMessage<SimpleMessage>();
    43.  
    44.         byte error;
    45.         Debug.Log(NetworkTransport.GetRemoteDelayTimeMS(netMsg.conn.hostId, netMsg.conn.connectionId, msg.timestamp, out error).ToString() + " MS Delay");
    46.     }
    47. }
    48.  
    0 ms local network



    100 ms NetworkSimulator

     
    Last edited by a moderator: Aug 11, 2017
  3. Deleted User

    Deleted User

    Guest

    Update: tested on both Unity 5.6 and 2017.1, still the same results.

    I think I'm just doing something stupid)
     
    Last edited by a moderator: Aug 11, 2017
  4. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Well, this should be correct. Here is why;

    When you call GetTimestamp. You create a timstamp AT THAT VERY MOMENT.
    When you then call GetRemoteMs. You calculate the difference AT THAT VERY MOMENT.

    This means that when you are totally local. You still have the NetworkTransport buffer. So if you are local player. It takes about 20ms for the packet to be sent and processed after the GetTimestamp. This makes sense due to the MinSendInterval being 0.1 by default. And there also some time for the reciever to actually invoke the callback etc.

    Basically, the timestamp stuff doesn't interact with the Network Library AFAIK. It's more of a utility method.


    Here is probably the easiest way to solve it that I can think of:
    "On Client connect. Send them a message with the servers Time.time and a timestamp. Then the clients will set their networkTime to the serversTime + the delay when that is recieved. That way every client has the servers Time which can be refered to as NetworkTime. They just have to increase it with Time.DeltaTime every frame. But it really depends on the problem you want to solve. For time sync, this would work great I think"
     
    Deleted User likes this.
  5. Deleted User

    Deleted User

    Guest

    What about FPS difference while calculating that time?
     
  6. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Well, once the time is synced. If you increase it with Time.detlaTime. it will go up by 1 every second. Which is what it does on the server automatically.
     
  7. Deleted User

    Deleted User

    Guest

    yeah but should I it increased in Update function? I guess yes, so that where is de-synchronization happens.
     
  8. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Don't quite understand what you mean.
     
  9. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I would grab the server time and delay and then calculate an offset to the machine's local time. Then write a server time method that just applies that offset to local time to return the current server time. Then there would be no need to add Time.deltaTime to the pulled down server time on every update.
     
  10. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    good point lol. Just make a getter called NetworkTime which is offset + Time.time.
     
  11. Deleted User

    Deleted User

    Guest

    For example: Server time is 5000ms, Client join after the main menu, so Time.time now is more than 0ms, you should take into account the current received Time too. so Time.time - timeReceived would return you the actual time since you joined the server.

    Code (CSharp):
    1. return networkTime + (networkTimestampDelayMS / 1000f) + (Time.time - timeReceived);
    The current code works but it's not accurate, anyway I abandoned my idea, so now I'm currently working only with NetworkTransport.GetNetworkTimestamp();
     
  12. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Yea, it's usually easier than keeping a clock in sync