|
| 1 | +using System; |
| 2 | +using UnityEngine; |
| 3 | + |
| 4 | +namespace MLAPI |
| 5 | +{ |
| 6 | + // todo: This is a pretty minimal tick system. It will be improved in the future |
| 7 | + // It currently relies on Time.unscaledTime and, as such, will start suffering |
| 8 | + // numerical precision issues after 2^23 ticks have passed (float have 23 bits mantissa) |
| 9 | + // For future releases, we'll need to improve on this, probably by leveraging FixedUpdate |
| 10 | + |
| 11 | + public class NetworkTickSystem : INetworkUpdateSystem, IDisposable |
| 12 | + { |
| 13 | + private const float k_DefaultTickIntervalSec = 1/60f; // Defaults to 60 ticks second |
| 14 | + private float m_TickIntervalSec; // Duration of a tick in seconds |
| 15 | + private int m_NetworkTickCount; // How many network ticks have passed? |
| 16 | + |
| 17 | + private static NetworkTickSystem m_Instance = null; |
| 18 | + |
| 19 | + // special value to indicate "No tick information" |
| 20 | + public const ushort k_NoTick = ushort.MaxValue; |
| 21 | + // Number of ticks over which the tick number wraps back to 0 |
| 22 | + public const ushort k_TickPeriod = k_NoTick - 1; |
| 23 | + |
| 24 | + /// <summary> |
| 25 | + /// Constructor |
| 26 | + /// Defaults to k_DefaultTickIntervalSec if no tick duration is specified |
| 27 | + /// </summary> |
| 28 | + /// <param name="tickIntervalSec">Duration of a network tick</param> |
| 29 | + public NetworkTickSystem(float tickIntervalSec = k_DefaultTickIntervalSec) |
| 30 | + { |
| 31 | + this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); |
| 32 | + |
| 33 | + //Assure we don't specify a value less than or equal to zero for tick frequency |
| 34 | + m_TickIntervalSec = (tickIntervalSec <= 0f) ? k_DefaultTickIntervalSec : tickIntervalSec; |
| 35 | + |
| 36 | + // ticks might not start at 0, so let's update right away at construction |
| 37 | + UpdateNetworkTick(); |
| 38 | + } |
| 39 | + |
| 40 | + public void Dispose() |
| 41 | + { |
| 42 | + this.UnregisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); |
| 43 | + } |
| 44 | + |
| 45 | + /// <summary> |
| 46 | + /// GetTick |
| 47 | + /// Gets the current network tick (non-fractional, wrapping around) |
| 48 | + /// </summary> |
| 49 | + /// <returns></returns> |
| 50 | + public ushort GetTick() |
| 51 | + { |
| 52 | + return (ushort)(m_NetworkTickCount % k_TickPeriod); |
| 53 | + } |
| 54 | + |
| 55 | + /// <summary> |
| 56 | + /// GetNetworkTime |
| 57 | + /// Network time is calculated from m_NetworkTickCount and m_TickIntervalSec (tick frequency) |
| 58 | + /// </summary> |
| 59 | + /// <returns>Network Time</returns> |
| 60 | + public float GetNetworkTime() |
| 61 | + { |
| 62 | + return m_NetworkTickCount * m_TickIntervalSec; |
| 63 | + } |
| 64 | + |
| 65 | + /// <summary> |
| 66 | + /// UpdateNetworkTick |
| 67 | + /// Called each network loop update during the PreUpdate stage |
| 68 | + /// </summary> |
| 69 | + private void UpdateNetworkTick() |
| 70 | + { |
| 71 | + m_NetworkTickCount = (int)(Time.unscaledTime / m_TickIntervalSec); |
| 72 | + } |
| 73 | + |
| 74 | + public void NetworkUpdate(NetworkUpdateStage updateStage) |
| 75 | + { |
| 76 | + switch (updateStage) |
| 77 | + { |
| 78 | + case NetworkUpdateStage.EarlyUpdate: |
| 79 | + UpdateNetworkTick(); |
| 80 | + break; |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | +} |
0 commit comments