diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs
index cff87f3f67d..4478ff87aa8 100644
--- a/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs
+++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs
@@ -439,6 +439,8 @@ 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;
}
@@ -446,6 +448,7 @@ public virtual void Reset()
protected virtual void OnEnable()
{
ResetState();
+ NetworkTime.highPingComponents++;
if (NetworkServer.active)
NetworkIdentity.clientAuthorityCallback += OnClientAuthorityChanged;
@@ -455,6 +458,9 @@ protected virtual void OnDisable()
{
ResetState();
+ if (NetworkTime.highPingComponents > 0UL)
+ NetworkTime.highPingComponents--;
+
if (NetworkServer.active)
NetworkIdentity.clientAuthorityCallback -= OnClientAuthorityChanged;
}
diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs
index 02abda30781..d3a61e6d975 100644
--- a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs
+++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs
@@ -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.
diff --git a/Assets/Mirror/Core/NetworkClient.cs b/Assets/Mirror/Core/NetworkClient.cs
index ab160c155e8..294d5fdf203 100644
--- a/Assets/Mirror/Core/NetworkClient.cs
+++ b/Assets/Mirror/Core/NetworkClient.cs
@@ -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);
diff --git a/Assets/Mirror/Core/NetworkConnectionToClient.cs b/Assets/Mirror/Core/NetworkConnectionToClient.cs
index d80749c13ed..8e04cf9671c 100644
--- a/Assets/Mirror/Core/NetworkConnectionToClient.cs
+++ b/Assets/Mirror/Core/NetworkConnectionToClient.cs
@@ -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.
diff --git a/Assets/Mirror/Core/NetworkServer.cs b/Assets/Mirror/Core/NetworkServer.cs
index 554851e452a..91849c49560 100644
--- a/Assets/Mirror/Core/NetworkServer.cs
+++ b/Assets/Mirror/Core/NetworkServer.cs
@@ -2276,7 +2276,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);
diff --git a/Assets/Mirror/Core/NetworkTime.cs b/Assets/Mirror/Core/NetworkTime.cs
index 6319970c45b..02de2609095 100644
--- a/Assets/Mirror/Core/NetworkTime.cs
+++ b/Assets/Mirror/Core/NetworkTime.cs
@@ -16,11 +16,17 @@ namespace Mirror
/// Synchronizes server time to clients.
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;
+
/// Ping message interval, used to calculate latency / RTT and predicted time.
- // 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;
/// Average out the last few results from Ping
// const because it's used immediately in _rtt constructor.
@@ -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
@@ -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
diff --git a/Assets/Mirror/Tests/Editor/NetworkConnection/NetworkConnectionToClientTests.cs b/Assets/Mirror/Tests/Editor/NetworkConnection/NetworkConnectionToClientTests.cs
index 75b349c92e3..1b6c59ed86f 100644
--- a/Assets/Mirror/Tests/Editor/NetworkConnection/NetworkConnectionToClientTests.cs
+++ b/Assets/Mirror/Tests/Editor/NetworkConnection/NetworkConnectionToClientTests.cs
@@ -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(message));
@@ -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};
diff --git a/Assets/Mirror/Tests/Runtime/NetworkServerRuntimeTest.cs b/Assets/Mirror/Tests/Runtime/NetworkServerRuntimeTest.cs
index 3587003a640..0fcca35a9e0 100644
--- a/Assets/Mirror/Tests/Runtime/NetworkServerRuntimeTest.cs
+++ b/Assets/Mirror/Tests/Runtime/NetworkServerRuntimeTest.cs
@@ -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;