Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -449,13 +449,16 @@ public virtual void Reset()
// default to ClientToServer so this works immediately for users
syncDirection = SyncDirection.ClientToServer;

NetworkTime.highPingComponents = 0UL;

// default to 20Hz, 20 sends per second if data has changed.
syncInterval = 0.05f;
}

protected virtual void OnEnable()
{
ResetState();
NetworkTime.highPingComponents++;

if (NetworkServer.active)
NetworkIdentity.clientAuthorityCallback += OnClientAuthorityChanged;
Expand All @@ -465,6 +468,9 @@ protected virtual void OnDisable()
{
ResetState();

if (NetworkTime.highPingComponents > 0UL)
NetworkTime.highPingComponents--;

if (NetworkServer.active)
NetworkIdentity.clientAuthorityCallback -= OnClientAuthorityChanged;
}
Expand Down
11 changes: 11 additions & 0 deletions Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ protected virtual void Awake()
positionCorrectionThresholdSqr = positionCorrectionThreshold * positionCorrectionThreshold;
}

protected virtual void OnEnable()
{
NetworkTime.highPingComponents++;
}

protected virtual void OnDisable()
{
if (NetworkTime.highPingComponents > 0UL)
NetworkTime.highPingComponents--;
}

protected virtual void CopyRenderersAsGhost(GameObject destination, Material material)
{
// find the MeshRenderer component, which sometimes is on a child.
Expand Down
3 changes: 2 additions & 1 deletion Assets/Mirror/Core/NetworkClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,8 @@ static void Broadcast(bool unreliableBaselineElapsed)
if (NetworkServer.active) return;

// send time snapshot every sendInterval.
Send(new TimeSnapshotMessage(), Channels.Unreliable);
if (NetworkTime.highPingComponents > 0UL)
Send(new TimeSnapshotMessage(), Channels.Unreliable);

// broadcast client state to server
BroadcastToServer(unreliableBaselineElapsed);
Expand Down
2 changes: 2 additions & 0 deletions Assets/Mirror/Core/NetworkConnectionToClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ protected virtual void UpdatePing()
// localTime (double) instead of Time.time for accuracy over days
if (NetworkTime.localTime >= lastPingTime + NetworkTime.PingInterval)
{
//Debug.Log("NetworkConnectionToClient SendPing");

// TODO it would be safer for the server to store the last N
// messages' timestamp and only send a message number.
// This way client's can't just modify the timestamp.
Expand Down
3 changes: 2 additions & 1 deletion Assets/Mirror/Core/NetworkServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2278,7 +2278,8 @@ static void Broadcast(bool unreliableBaselineElapsed)
// make sure Broadcast() is only called every sendInterval,
// even if targetFrameRate isn't set in host mode (!)
// (done via AccurateInterval)
connection.Send(new TimeSnapshotMessage(), Channels.Unreliable);
if (NetworkTime.highPingComponents > 0UL)
connection.Send(new TimeSnapshotMessage(), Channels.Unreliable);

// broadcast world state to this connection
BroadcastToConnection(connection, unreliableBaselineElapsed);
Expand Down
19 changes: 14 additions & 5 deletions Assets/Mirror/Core/NetworkTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ namespace Mirror
/// <summary>Synchronizes server time to clients.</summary>
public static class NetworkTime
{
// Incremented / decremented by components that need higher ping frequency.
// Also used to determine if we need to send TimeSnapshotMessage by
// NetworkServer and NetworkClient.
internal static ulong highPingComponents = 0UL;
const float highPingInterval = 0.1f;

/// <summary>Ping message interval, used to calculate latency / RTT and predicted time.</summary>
// 2s was enough to get a good average RTT.
// for prediction, we want to react to latency changes more rapidly.
const float DefaultPingInterval = 0.1f; // for resets
public static float PingInterval = DefaultPingInterval;
// 2s is enough to get a good average RTT.
// For snapshot interpolation and prediction, we need to react to latency changes more rapidly.
internal static float defaultPingInterval = 2.0f; // internal for tests
public static float PingInterval => highPingComponents > 0UL ? highPingInterval : defaultPingInterval;

/// <summary>Average out the last few results from Ping</summary>
// const because it's used immediately in _rtt constructor.
Expand Down Expand Up @@ -129,7 +135,8 @@ public static double predictedTime
[RuntimeInitializeOnLoadMethod]
public static void ResetStatics()
{
PingInterval = DefaultPingInterval;
defaultPingInterval = 2.0f;
highPingComponents = 0UL;
lastPingTime = 0;
_rtt = new ExponentialMovingAverage(PingWindowSize);
#if !UNITY_2020_3_OR_NEWER
Expand All @@ -147,6 +154,8 @@ internal static void UpdateClient()
// Separate method so we can call it from NetworkClient directly.
internal static void SendPing()
{
//Debug.Log("NetworkTime SendPing");

// send raw predicted time without the offset applied yet.
// we then apply the offset to it after.
NetworkPingMessage pingMessage = new NetworkPingMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void Send_BatchesUntilUpdate()
{
// create connection and send
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
NetworkTime.PingInterval = float.MaxValue; // disable ping for this test
NetworkTime.defaultPingInterval = float.MaxValue; // disable ping for this test
byte[] message = {0x01, 0x02};
connection.Send(new ArraySegment<byte>(message));

Expand Down Expand Up @@ -64,7 +64,7 @@ public void SendBatchingResetsPreviousWriter()

// create connection
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
NetworkTime.PingInterval = float.MaxValue; // disable ping for this test
NetworkTime.defaultPingInterval = float.MaxValue; // disable ping for this test

// send and update big message
byte[] message = {0x01, 0x02};
Expand Down
3 changes: 1 addition & 2 deletions Assets/Mirror/Tests/Runtime/NetworkServerRuntimeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ NetworkIdentity SpawnPrefab(GameObject prefab)
[UnityTest]
public IEnumerator DisconnectTimeoutTest()
{
// Set low ping frequency so no NetworkPingMessage is generated
NetworkTime.PingInterval = 5f;
NetworkTime.defaultPingInterval = float.MaxValue; // disable ping for this test

// Set a short timeout for this test and enable disconnectInactiveConnections
NetworkServer.disconnectInactiveConnections = true;
Expand Down