diff --git a/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs index 4ee3eabff..129b138b7 100644 --- a/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs +++ b/Assets/Mirror/Components/Experimental/NetworkLerpRigidbody.cs @@ -64,7 +64,7 @@ void SendToServer() double now = NetworkTime.localTime; // Unity 2019 doesn't have Time.timeAsDouble yet if (now > nextSyncTime) { - nextSyncTime = now + syncInterval; + nextSyncTime = now + NetworkClient.sendInterval; CmdSendState(target.velocity, target.position); } } diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs index ce1f89a29..e3e425e3c 100644 --- a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs @@ -232,7 +232,7 @@ void SendVelocity() // only update syncTime if either has changed if (angularVelocityChanged || velocityChanged) { - previousValue.nextSyncTime = now + syncInterval; + previousValue.nextSyncTime = now + NetworkClient.sendInterval; } } diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs index a50611c6f..87a3bea21 100644 --- a/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody2D.cs @@ -231,7 +231,7 @@ void SendVelocity() // only update syncTime if either has changed if (angularVelocityChanged || velocityChanged) { - previousValue.nextSyncTime = now + syncInterval; + previousValue.nextSyncTime = now + NetworkClient.sendInterval; } } diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs index 9d36e4611..b3d03e195 100644 --- a/Assets/Mirror/Components/NetworkAnimator.cs +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -189,9 +189,9 @@ bool CheckAnimStateChanged(out int stateHash, out float normalizedTime, int laye void CheckSendRate() { double now = NetworkTime.localTime; - if (SendMessagesAllowed && syncInterval >= 0 && now > nextSendTime) + if (SendMessagesAllowed && NetworkServer.sendInterval >= 0 && now > nextSendTime) { - nextSendTime = now + syncInterval; + nextSendTime = now + NetworkServer.sendInterval; using (NetworkWriterPooled writer = NetworkWriterPool.Get()) { diff --git a/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs b/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs index ea2851077..72860032d 100644 --- a/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs +++ b/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs @@ -94,13 +94,6 @@ protected virtual void OnValidate() { // set target to self if none yet if (target == null) target = transform; - - // time snapshot interpolation happens globally. - // value (transform) happens in here. - // both always need to be on the same send interval. - // force the setting to '0' in OnValidate to make it obvious that we - // actually use NetworkServer.sendInterval. - syncInterval = 0; } // snapshot functions ////////////////////////////////////////////////// diff --git a/Assets/Mirror/Components/NetworkTransformUnreliable/NetworkTransform.cs b/Assets/Mirror/Components/NetworkTransformUnreliable/NetworkTransform.cs index dea1761ab..23471ea69 100644 --- a/Assets/Mirror/Components/NetworkTransformUnreliable/NetworkTransform.cs +++ b/Assets/Mirror/Components/NetworkTransformUnreliable/NetworkTransform.cs @@ -94,13 +94,6 @@ protected virtual void OnValidate() // set target to self if none yet if (target == null) target = transform; - // time snapshot interpolation happens globally. - // value (transform) happens in here. - // both always need to be on the same send interval. - // force the setting to '0' in OnValidate to make it obvious that we - // actually use NetworkServer.sendInterval. - syncInterval = 0; - // obsolete clientAuthority compatibility: // if it was used, then set the new SyncDirection automatically. // if it wasn't used, then don't touch syncDirection. diff --git a/Assets/Mirror/Core/NetworkBehaviour.cs b/Assets/Mirror/Core/NetworkBehaviour.cs index 9b0fcebfd..9202c4842 100644 --- a/Assets/Mirror/Core/NetworkBehaviour.cs +++ b/Assets/Mirror/Core/NetworkBehaviour.cs @@ -36,10 +36,10 @@ public abstract class NetworkBehaviour : MonoBehaviour /// sync interval for OnSerialize (in seconds) // hidden because NetworkBehaviourInspector shows it only if has OnSerialize. // [0,2] should be enough. anything >2s is too laggy anyway. - [Tooltip("Time in seconds until next change is synchronized to the client. '0' means send immediately if changed. '0.5' means only send changes every 500ms.\n(This is for state synchronization like SyncVars, SyncLists, OnSerialize. Not for Cmds, Rpcs, etc.)")] + // DEPRECATED 2022-11-11 + [Obsolete("NetworkBehaviour.syncInterval is not used anymore. Please configure the NetworkManager's send/tickRate globally instead. This has two advantages: snapshot interpolation is easier (no overlapping intervals), and it allows for a noticeable performance improvements because OnSerialize doesn't need to check dirty components anymore.")] [Range(0, 2)] [HideInInspector] public float syncInterval = 0.1f; - internal double lastSyncTime; /// True if this object is on the server and has been spawned. // This is different from NetworkServer.active, which is true if the @@ -172,21 +172,16 @@ public void SetSyncVarDirtyBit(ulong dirtyBit) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetDirty() => SetSyncVarDirtyBit(ulong.MaxValue); - // true if syncInterval elapsed and any SyncVar or SyncObject is dirty + // true if any SyncVar or SyncObject is dirty. // OR both bitmasks. != 0 if either was dirty. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool IsDirty() => - // check bits first. this is basically free. - (syncVarDirtyBits | syncObjectDirtyBits) != 0UL && - // only check time if bits were dirty. this is more expensive. - NetworkTime.localTime - lastSyncTime >= syncInterval; + public bool IsDirty() => (syncVarDirtyBits | syncObjectDirtyBits) != 0UL; /// Clears all the dirty bits that were set by SetDirtyBits() // automatically invoked when an update is sent for this object, but can // be called manually as well. public void ClearAllDirtyBits() { - lastSyncTime = NetworkTime.localTime; syncVarDirtyBits = 0L; syncObjectDirtyBits = 0L; diff --git a/Assets/Mirror/Core/NetworkClient.cs b/Assets/Mirror/Core/NetworkClient.cs index 6fbf3be43..699fcae97 100644 --- a/Assets/Mirror/Core/NetworkClient.cs +++ b/Assets/Mirror/Core/NetworkClient.cs @@ -1467,7 +1467,7 @@ static void Broadcast() // nothing to do in host mode. server already knows the state. if (NetworkServer.active) return; - // send time snapshot every sendInterval. + // send time snapshot every sendInterval BroadcastTimeSnapshot(); // for each entity that the client owns @@ -1495,7 +1495,7 @@ static void Broadcast() Send(message); // reset dirty bits so it's not resent next time. - identity.ClearDirtyComponentsDirtyBits(); + identity.ClearAllComponentsDirtyBits(); } } } diff --git a/Assets/Mirror/Core/NetworkIdentity.cs b/Assets/Mirror/Core/NetworkIdentity.cs index b4157b398..3977454ba 100644 --- a/Assets/Mirror/Core/NetworkIdentity.cs +++ b/Assets/Mirror/Core/NetworkIdentity.cs @@ -1114,16 +1114,10 @@ internal NetworkIdentitySerialization GetServerSerializationAtTick(int tick) // NOTE: not in Serializell as that should only do one // thing: serialize data. // - // - // NOTE: DO NOT clear ALL component's dirty bits, because - // components can have different syncIntervals and we - // don't want to reset dirty bits for the ones that were - // not synced yet. - // // NOTE: this used to be very important to avoid ever growing // SyncList changes if they had no observers, but we've // added SyncObject.isRecording since. - ClearDirtyComponentsDirtyBits(); + ClearAllComponentsDirtyBits(); // set tick lastSerialization.tick = tick; @@ -1337,23 +1331,6 @@ internal void ClearAllComponentsDirtyBits() } } - // Clear only dirty component's dirty bits. ignores components which - // may be dirty but not ready to be synced yet (because of syncInterval) - // - // NOTE: this used to be very important to avoid ever - // growing SyncList changes if they had no observers, - // but we've added SyncObject.isRecording since. - internal void ClearDirtyComponentsDirtyBits() - { - foreach (NetworkBehaviour comp in NetworkBehaviours) - { - if (comp.IsDirty()) - { - comp.ClearAllDirtyBits(); - } - } - } - void ResetSyncObjects() { // ResetSyncObjects is called by Reset, which is called by Unity. diff --git a/Assets/Mirror/Editor/NetworkBehaviourInspector.cs b/Assets/Mirror/Editor/NetworkBehaviourInspector.cs index 7cae54f6e..143c7ef23 100644 --- a/Assets/Mirror/Editor/NetworkBehaviourInspector.cs +++ b/Assets/Mirror/Editor/NetworkBehaviourInspector.cs @@ -93,9 +93,6 @@ protected void DrawDefaultSyncSettings() if (syncDirection.enumValueIndex == (int)SyncDirection.ServerToClient) EditorGUILayout.PropertyField(serializedObject.FindProperty("syncMode")); - // sync interval - EditorGUILayout.PropertyField(serializedObject.FindProperty("syncInterval")); - // apply serializedObject.ApplyModifiedProperties(); } diff --git a/Assets/Mirror/Tests/Common/MirrorTest.cs b/Assets/Mirror/Tests/Common/MirrorTest.cs index 16f7098af..47fb2c73c 100644 --- a/Assets/Mirror/Tests/Common/MirrorTest.cs +++ b/Assets/Mirror/Tests/Common/MirrorTest.cs @@ -28,6 +28,11 @@ public virtual void SetUp() // need a transport to send & receive Transport.active = transport = holder.AddComponent(); + + // always set send interval to 'immediately' for easier testing + NetworkServer.tickRate = 0; + // NetworkServer.sendRate := tickRate + // NetworkClient.sendRate := NetworkServer.sendRate } public virtual void TearDown() @@ -89,8 +94,6 @@ protected void CreateNetworked(out GameObject go, out NetworkIdentity identit go = new GameObject(); identity = go.AddComponent(); component = go.AddComponent(); - // always set syncinterval = 0 for immediate testing - component.syncInterval = 0; // Awake is only called in play mode. // call manually for initialization. identity.Awake(); @@ -108,9 +111,6 @@ protected void CreateNetworked(out GameObject go, out NetworkIdentity iden identity = go.AddComponent(); componentA = go.AddComponent(); componentB = go.AddComponent(); - // always set syncinterval = 0 for immediate testing - componentA.syncInterval = 0; - componentB.syncInterval = 0; // Awake is only called in play mode. // call manually for initialization. identity.Awake(); @@ -130,10 +130,6 @@ protected void CreateNetworked(out GameObject go, out NetworkIdentity i componentA = go.AddComponent(); componentB = go.AddComponent(); componentC = go.AddComponent(); - // always set syncinterval = 0 for immediate testing - componentA.syncInterval = 0; - componentB.syncInterval = 0; - componentC.syncInterval = 0; // Awake is only called in play mode. // call manually for initialization. identity.Awake(); diff --git a/Assets/Mirror/Tests/Editor/NetworkBehaviourDirtyBitsTests.cs b/Assets/Mirror/Tests/Editor/NetworkBehaviourDirtyBitsTests.cs index ae14b1449..abc0d2d1e 100644 --- a/Assets/Mirror/Tests/Editor/NetworkBehaviourDirtyBitsTests.cs +++ b/Assets/Mirror/Tests/Editor/NetworkBehaviourDirtyBitsTests.cs @@ -94,10 +94,6 @@ public void IsDirty() comp.list.Add(42); Assert.That(comp.IsDirty(), Is.True); comp.ClearAllDirtyBits(); - - // it should only be dirty after syncInterval elapsed - comp.syncInterval = float.MaxValue; - Assert.That(comp.IsDirty(), Is.False); } [Test] @@ -106,8 +102,6 @@ public void ClearAllDirtyBitsClearsSyncVarDirtyBits() CreateNetworkedAndSpawn(out _, out _, out EmptyBehaviour emptyBehaviour, out _, out _, out _); - // set syncinterval so dirtybit works fine - emptyBehaviour.syncInterval = 0; Assert.That(emptyBehaviour.IsDirty(), Is.False); // set one syncvar dirty bit @@ -125,8 +119,6 @@ public void ClearAllDirtyBitsClearsSyncObjectsDirtyBits() CreateNetworkedAndSpawn(out _, out _, out NetworkBehaviourWithSyncVarsAndCollections comp, out _, out _, out _); - // set syncinterval so dirtybit works fine - comp.syncInterval = 0; Assert.That(comp.IsDirty(), Is.False); // dirty the synclist @@ -162,7 +154,6 @@ public void DirtyBitsAreClearedForSpawnedWithoutObservers() Assert.That(monster.observers.Count, Is.EqualTo(0)); // modify something in the monster so that dirty bit is set - monsterComp.syncInterval = 0; ++monsterComp.health; Assert.That(monsterComp.IsDirty(), Is.True); diff --git a/Assets/Mirror/Tests/Editor/NetworkIdentitySerializationTests.cs b/Assets/Mirror/Tests/Editor/NetworkIdentitySerializationTests.cs index 7a2711580..d9546d0d5 100644 --- a/Assets/Mirror/Tests/Editor/NetworkIdentitySerializationTests.cs +++ b/Assets/Mirror/Tests/Editor/NetworkIdentitySerializationTests.cs @@ -276,7 +276,6 @@ public void SerializeServer_OwnerMode_ClientToServer() // pretend to be owned identity.isOwned = true; comp.syncMode = SyncMode.Owner; - comp.syncInterval = 0; // set to CLIENT with some unique values // and set connection to server to pretend we are the owner. @@ -312,7 +311,6 @@ public void SerializeServer_ObserversMode_ClientToServer() // pretend to be owned identity.isOwned = true; comp.syncMode = SyncMode.Observers; - comp.syncInterval = 0; // set to CLIENT with some unique values // and set connection to server to pretend we are the owner. diff --git a/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs b/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs index f1b0b9d49..a9885fa69 100644 --- a/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs +++ b/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs @@ -832,38 +832,6 @@ public void ClearObservers() Assert.That(identity.observers.Count, Is.EqualTo(0)); } - [Test] - public void ClearDirtyComponentsDirtyBits() - { - CreateNetworked(out GameObject _, out NetworkIdentity identity, - out OnStartClientTestNetworkBehaviour compA, - out OnStartClientTestNetworkBehaviour compB); - - // set syncintervals so one is always dirty, one is never dirty - compA.syncInterval = 0; - compB.syncInterval = Mathf.Infinity; - - // set components dirty bits - compA.SetSyncVarDirtyBit(0x0001); - compB.SetSyncVarDirtyBit(0x1001); - // dirty because interval reached and mask != 0 - Assert.That(compA.IsDirty(), Is.True); - // not dirty because syncinterval not reached - Assert.That(compB.IsDirty(), Is.False); - - // call identity.ClearDirtyComponentsDirtyBits - identity.ClearDirtyComponentsDirtyBits(); - // should be cleared now - Assert.That(compA.IsDirty(), Is.False); - // should be untouched - Assert.That(compB.IsDirty(), Is.False); - - // set compB syncinterval to 0 to check if the masks were untouched - // (if they weren't, then it should be dirty now) - compB.syncInterval = 0; - Assert.That(compB.IsDirty(), Is.True); - } - [Test] public void ClearAllComponentsDirtyBits() { @@ -871,17 +839,13 @@ public void ClearAllComponentsDirtyBits() out OnStartClientTestNetworkBehaviour compA, out OnStartClientTestNetworkBehaviour compB); - // set syncintervals so one is always dirty, one is never dirty - compA.syncInterval = 0; - compB.syncInterval = Mathf.Infinity; - // set components dirty bits compA.SetSyncVarDirtyBit(0x0001); compB.SetSyncVarDirtyBit(0x1001); // dirty because interval reached and mask != 0 Assert.That(compA.IsDirty(), Is.True); - // not dirty because syncinterval not reached - Assert.That(compB.IsDirty(), Is.False); + // dirty because interval reached and mask != 0 + Assert.That(compB.IsDirty(), Is.True); // call identity.ClearAllComponentsDirtyBits identity.ClearAllComponentsDirtyBits(); @@ -889,11 +853,6 @@ public void ClearAllComponentsDirtyBits() Assert.That(compA.IsDirty(), Is.False); // should be cleared now Assert.That(compB.IsDirty(), Is.False); - - // set compB syncinterval to 0 to check if the masks were cleared - // (if they weren't, then it would still be dirty now) - compB.syncInterval = 0; - Assert.That(compB.IsDirty(), Is.False); } [Test] diff --git a/Assets/Mirror/Tests/Editor/NetworkTransform2kTests.cs b/Assets/Mirror/Tests/Editor/NetworkTransform2kTests.cs index 8190765f7..7f408d949 100644 --- a/Assets/Mirror/Tests/Editor/NetworkTransform2kTests.cs +++ b/Assets/Mirror/Tests/Editor/NetworkTransform2kTests.cs @@ -40,8 +40,6 @@ public override void SetUp() // create a networked object with NetworkTransform CreateNetworkedAndSpawn(out GameObject go, out NetworkIdentity _, out component, connectionToClient); - // sync immediately - component.syncInterval = 0; // remember transform for convenience transform = go.transform; } diff --git a/Assets/Mirror/Tests/Editor/SyncVarAttributeTest.cs b/Assets/Mirror/Tests/Editor/SyncVarAttributeTest.cs index 96b00e760..adece33c1 100644 --- a/Assets/Mirror/Tests/Editor/SyncVarAttributeTest.cs +++ b/Assets/Mirror/Tests/Editor/SyncVarAttributeTest.cs @@ -84,9 +84,6 @@ public void TestSettingStruct() { CreateNetworked(out _, out _, out MockPlayer player); - // synchronize immediately - player.syncInterval = 0f; - Assert.That(player.IsDirty(), Is.False, "First time object should not be dirty"); MockPlayer.Guild myGuild = new MockPlayer.Guild @@ -105,58 +102,6 @@ public void TestSettingStruct() Assert.That(player.IsDirty(), "Clearing struct should mark object as dirty"); } - [Test] - public void TestSyncIntervalAndClearDirtyComponents() - { - CreateNetworked(out _, out _, out MockPlayer player); - player.lastSyncTime = NetworkTime.localTime; - // synchronize immediately - player.syncInterval = 1f; - - player.guild = new MockPlayer.Guild - { - name = "Back street boys" - }; - - Assert.That(player.IsDirty(), Is.False, "Sync interval not met, so not dirty yet"); - - // ClearDirtyComponents should do nothing since syncInterval is not - // elapsed yet - player.netIdentity.ClearDirtyComponentsDirtyBits(); - - // set lastSyncTime far enough back to be ready for syncing - player.lastSyncTime = NetworkTime.localTime - player.syncInterval; - - // should be dirty now - Assert.That(player.IsDirty(), Is.True, "Sync interval met, should be dirty"); - } - - [Test] - public void TestSyncIntervalAndClearAllComponents() - { - CreateNetworked(out _, out _, out MockPlayer player); - player.lastSyncTime = NetworkTime.localTime; - // synchronize immediately - player.syncInterval = 1f; - - player.guild = new MockPlayer.Guild - { - name = "Back street boys" - }; - - Assert.That(player.IsDirty(), Is.False, "Sync interval not met, so not dirty yet"); - - // ClearAllComponents should clear dirty even if syncInterval not - // elapsed yet - player.netIdentity.ClearAllComponentsDirtyBits(); - - // set lastSyncTime far enough back to be ready for syncing - player.lastSyncTime = NetworkTime.localTime - player.syncInterval; - - // should be dirty now - Assert.That(player.IsDirty(), Is.False, "Sync interval met, should still not be dirty"); - } - [Test] public void SyncsGameobject() {