diff --git a/Assets/Mirror/Runtime/NetworkIdentity.cs b/Assets/Mirror/Runtime/NetworkIdentity.cs index 302f608af..4a64c9424 100644 --- a/Assets/Mirror/Runtime/NetworkIdentity.cs +++ b/Assets/Mirror/Runtime/NetworkIdentity.cs @@ -1230,8 +1230,14 @@ internal void MirrorUpdate() NetworkServer.SendToReady(this, varsMessage, false); } - // only clear bits if we sent something - ClearAllComponentsDirtyBits(); + // clear dirty bits only for the components that we serialized + // DO NOT clean 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. + // (we serialized only the IsDirty() components, or all of + // them if initialState. clearing the dirty ones is enough.) + ClearDirtyComponentsDirtyBits(); } NetworkWriterPool.Recycle(ownerWriter); NetworkWriterPool.Recycle(observersWriter); @@ -1251,5 +1257,18 @@ internal void ClearAllComponentsDirtyBits() comp.ClearAllDirtyBits(); } } + + // clear only dirty component's dirty bits. ignores components which + // may be dirty but not ready to be synced yet (because of syncInterval) + internal void ClearDirtyComponentsDirtyBits() + { + foreach (NetworkBehaviour comp in NetworkBehaviours) + { + if (comp.IsDirty()) + { + comp.ClearAllDirtyBits(); + } + } + } } } diff --git a/Assets/Mirror/Tests/SyncVarTest.cs b/Assets/Mirror/Tests/SyncVarTest.cs index 733c0dc7d..c08b2cbe8 100644 --- a/Assets/Mirror/Tests/SyncVarTest.cs +++ b/Assets/Mirror/Tests/SyncVarTest.cs @@ -51,6 +51,35 @@ public void TestSettingStruct() Assert.That(player.IsDirty(), "Clearing struct should mark object as dirty"); } + [Test] + public void TestSyncIntervalAndClearDirtyComponents() + { + + GameObject gameObject = new GameObject(); + + MockPlayer player = gameObject.AddComponent(); + player.lastSyncTime = Time.time; + // 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 = Time.time - player.syncInterval; + + // should be dirty now + Assert.That(player.IsDirty(), Is.True, "Sync interval met, should be dirty"); + } + [Test] public void TestSyncIntervalAndClearAllComponents() {