Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Network Time

Discussion in 'NetCode for ECS' started by MrEastwood, Sep 1, 2021.

  1. MrEastwood

    MrEastwood

    Joined:
    Dec 9, 2013
    Posts:
    19
    I'd like to have access to a timestamp that is the same on the server and client. The manual on time synchronization suggests the NetworkTimeSystem should be able to provide me with one. The documentation is lacking but from the names I would think TimestampMS would be the field I want. Except it isn't: it returns different times on different instances.

    I'd like such a timestamp because I have items moving on rails. If I spawn such an item I'd only have to synchronize its starting point and starting time, and I'd be able to predict and interpolate it without further data until it detaches or reaches the end of the rail.

    Does such a timestamp currently exist? Or should I be looking for ticks instead of times? If so, are there different ticks (server/prediction/interpolation) and how would I access them?
     
  2. Dan-Foster

    Dan-Foster

    Joined:
    Aug 7, 2019
    Posts:
    48
    Something that I've used in a similar situation is the server tick. I've got this value like this.

    Code (CSharp):
    1.         uint tick = 0;
    2.         if( isClient )
    3.             tick = clientSimulationSystemGroup.ServerTick;
    4.         else
    5.             tick = serverSimulationSystemGroup.ServerTick;
     
    MrEastwood likes this.
  3. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    You should use the tick for this, there is no synchronized time - only ticks.

    On the server use ServerSimulationSystemGroup.ServerTick.

    On the client user ClientSimulationSystemGroup.ServerTick for predicted time and ClientSimulationSystemGroup.InterpolationTick for interpolated time.

    There is also ClientSimulationSystemGroup.ServerTickFraction and ClientSimulationSystemGroup.InterpolationTickFraction on the client. If ServerTickFraction is less than 1 you are at tick ServerTick, but you are only part way through that tick - not at the end of it. So if ServerTick is 10 and ServerTickFraction 0.5 your current time in ticks would be 9.5 because tick 10 is not completely done yet. This only happens on the client because it is using dynamic timestep.

    If you're inside the GhostPredictionSystemGroup and updating a system used for prediction you should look at GhostPredictionSystemGroup.PredictingTick on both the client and server. The prediction group does not expose the tick fraction, so you have to look at the delta time to deal correctly with dynamic timestep on the client.
     
    Dan-Foster and MrEastwood like this.
  4. MrEastwood

    MrEastwood

    Joined:
    Dec 9, 2013
    Posts:
    19
    Well, I was using ServerSimulationSystemGroup.ServerTick and ClientSimulationSystemGroup.ServerTick and for a while it looked good. But on closer inspection they seem to start out at the same value and then they diverge. I didn't notice it at first because I was running only short tests.

    In my case the client's tick count goes up faster than the server. I don't think it has to do with prediction because as I said, the ticks start out the same. The client won't just go ahead a few ticks, they actually keep adding up until the client is 100s of ticks ahead. Mind you this is still ClientSimulationSystemGroup.ServerTick I'm talking about getting ahead of ServerSimulationSystemGroup.ServerTick. For good measure I tried switching to ClientSimulationSystemGroup.InterpolationTick but it does the same thing. InterpolationTick is a handful of ticks behind ServerTick, but they both end up being far greater than ServerSimulationSystemGroup.ServerTick is.

    Is there anything I need to do to get the actual tick number the server is on? I don't mind lagging behind, I'll settle for an interpolation tick. Do I need to set and/or retrieve it from a system in a certain group?
     
  5. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    774
    Clients are always try to have a ServerTick that is ahead of the server of about 2 ticks. To do so, the value of the server tick on client is WAY greater than 2, approx (RTT/2)*ServerTickRate + slack ticks at the very least from what the server will be at that point in time. The server always give a feed back to the client about how is behaving and the client try to stay in that range.

    So if the perceived latency is for ex 100ms the client predicted ServerTick (in its own time frame) will be ServerTick* + 6 + 2, so about 8 ticks greater.
    We support up to 500ms latency (so 1s RTT), in which case the client should be ahead at most about 30-32 ticks.
    InterpolationTick are always in the past and can't be greater than the server either, because they we are actually interpolating in between two received snapshot in time (so the server is surely far ahead at that point)
     
    bb8_1 likes this.
  6. MrEastwood

    MrEastwood

    Joined:
    Dec 9, 2013
    Posts:
    19
    Thanks for the explanation! However, this would only explain differences up to about 32 ticks. As I described my tick difference gets much higher. The longer I let it run the higher the difference gets, eventually resulting in differences of 100s or even 1000s of ticks. It's pretty reliably 10% ahead, so if my server says it's at tick 9800 then my client will think the server is at tick 10780. And this is running on either on the same machine (host and client) or on a LAN where there really isn't a large or unreliable RTT.

    Since the server obviously is in charge of the simulation I'm guessing the client's estimate of the server tick is just plain wrong here. Is there any test I can run or entity to inspect to find out what's happening here?
     
  7. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    The client tries to match the server time by scaling time with up to 10%, it sounds like in your case it for some reason always runs the client 10% faster which indicates that it is getting the wrong command age from the server.
    The first step is to check the time graphs in NetDbg (you can open it from the menu under `Multiplayer > Open NetDbg`). The most relevant graphs for your case is `Show time scale` which should stay close to 1 with some slight variance, and `Show command age` which should stay close to -2 with some slight variance. You can see the raw values in the text blob under the graphs if you select a frame.