diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs index 0baf5caa8..903ebe046 100644 --- a/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformBase.cs @@ -153,13 +153,17 @@ protected void AddSnapshot(SortedList snapshots, doub if (!scale.HasValue) scale = snapshots.Count > 0 ? snapshots.Values[snapshots.Count - 1].scale : target.localScale; // insert transform snapshot - SnapshotInterpolation.InsertIfNotExists(snapshots, new TransformSnapshot( - timeStamp, // arrival remote timestamp. NOT remote time. - NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet - position.Value, - rotation.Value, - scale.Value - )); + SnapshotInterpolation.InsertIfNotExists( + snapshots, + NetworkClient.snapshotSettings.bufferLimit, + new TransformSnapshot( + timeStamp, // arrival remote timestamp. NOT remote time. + NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet + position.Value, + rotation.Value, + scale.Value + ) + ); } // apply a snapshot to the Transform. diff --git a/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs b/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs index 855652581..86a8cf4d0 100644 --- a/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs +++ b/Assets/Mirror/Components/NetworkTransform/NetworkTransformReliable.cs @@ -392,13 +392,17 @@ static void RewriteHistory( // insert a fake one at where we used to be, // 'sendInterval' behind the new one. - SnapshotInterpolation.InsertIfNotExists(snapshots, new TransformSnapshot( - remoteTimeStamp - sendInterval, // arrival remote timestamp. NOT remote time. - localTime - sendInterval, // Unity 2019 doesn't have timeAsDouble yet - position, - rotation, - scale - )); + SnapshotInterpolation.InsertIfNotExists( + snapshots, + NetworkClient.snapshotSettings.bufferLimit, + new TransformSnapshot( + remoteTimeStamp - sendInterval, // arrival remote timestamp. NOT remote time. + localTime - sendInterval, // Unity 2019 doesn't have timeAsDouble yet + position, + rotation, + scale + ) + ); } public override void Reset() diff --git a/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs index 177d30e5b..963ec2b8a 100644 --- a/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs +++ b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs @@ -143,6 +143,7 @@ public static void OnTimeSnapshot(TimeSnapshot snap) // insert into the buffer & initialize / adjust / catchup SnapshotInterpolation.InsertAndAdjust( snapshots, + snapshotSettings.bufferLimit, snap, ref localTimeline, ref localTimescale, diff --git a/Assets/Mirror/Core/NetworkConnectionToClient.cs b/Assets/Mirror/Core/NetworkConnectionToClient.cs index fa7e3b1b6..6e1f5904b 100644 --- a/Assets/Mirror/Core/NetworkConnectionToClient.cs +++ b/Assets/Mirror/Core/NetworkConnectionToClient.cs @@ -80,6 +80,7 @@ public void OnTimeSnapshot(TimeSnapshot snapshot) // insert into the server buffer & initialize / adjust / catchup SnapshotInterpolation.InsertAndAdjust( snapshots, + NetworkClient.snapshotSettings.bufferLimit, snapshot, ref remoteTimeline, ref remoteTimescale, diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs index 0fbe095ce..519f9b19c 100644 --- a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs @@ -91,9 +91,16 @@ public static double DynamicAdjustment( [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool InsertIfNotExists( SortedList buffer, // snapshot buffer + int bufferLimit, // don't grow infinitely T snapshot) // the newly received snapshot where T : Snapshot { + // slow clients may not be able to process incoming snapshots fast enough. + // infinitely growing snapshots would make it even worse. + // for example, run NetworkRigidbodyBenchmark while deep profiling client. + // the client just grows and reallocates the buffer forever. + if (buffer.Count >= bufferLimit) return false; + // SortedList does not allow duplicates. // we don't need to check ContainsKey (which is expensive). // simply add and compare count before/after for the return value. @@ -136,6 +143,7 @@ public static double TimelineClamp( // adds / inserts it to the list & initializes local time if needed. public static void InsertAndAdjust( SortedList buffer, // snapshot buffer + int bufferLimit, // don't grow infinitely T snapshot, // the newly received snapshot ref double localTimeline, // local interpolation time based on server time ref double localTimescale, // timeline multiplier to apply catchup / slowdown over time @@ -167,7 +175,7 @@ public static void InsertAndAdjust( // note that insert may be called twice for the same key. // by default, this would throw. // need to handle it silently. - if (InsertIfNotExists(buffer, snapshot)) + if (InsertIfNotExists(buffer, bufferLimit, snapshot)) { // dynamic buffer adjustment needs delivery interval jitter if (buffer.Count >= 2) diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs index 2424eec31..74feae40c 100644 --- a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolationSettings.cs @@ -16,6 +16,9 @@ public class SnapshotInterpolationSettings [Tooltip("Local simulation is behind by sendInterval * multiplier seconds.\n\nThis guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter.\n\nIncrease this if the simulation isn't smooth. By default, it should be around 2.")] public double bufferTimeMultiplier = 2; + [Tooltip("If a client can't process snapshots fast enough, don't store too many.")] + public int bufferLimit = 32; + // catchup ///////////////////////////////////////////////////////////// // catchup thresholds in 'frames'. // half a frame might be too aggressive. @@ -63,6 +66,5 @@ public class SnapshotInterpolationSettings [Tooltip("Dynamic adjustment is computed over n-second exponential moving average standard deviation.")] public int deliveryTimeEmaDuration = 2; // 1-2s recommended to capture average delivery time - } } diff --git a/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs b/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs index 696f101c2..bdf0d00da 100644 --- a/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs +++ b/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs @@ -87,6 +87,7 @@ public void OnMessage(Snapshot3D snap) // insert into the buffer & initialize / adjust / catchup SnapshotInterpolation.InsertAndAdjust( snapshots, + snapshotSettings.bufferLimit, snap, ref localTimeline, ref localTimescale, diff --git a/Assets/Mirror/Tests/Editor/SnapshotInterpolation/SnapshotInterpolationTests.cs b/Assets/Mirror/Tests/Editor/SnapshotInterpolation/SnapshotInterpolationTests.cs index a323ed3ae..83d1182c1 100644 --- a/Assets/Mirror/Tests/Editor/SnapshotInterpolation/SnapshotInterpolationTests.cs +++ b/Assets/Mirror/Tests/Editor/SnapshotInterpolation/SnapshotInterpolationTests.cs @@ -36,6 +36,7 @@ public class SnapshotInterpolationTests const double slowdownSpeed = 0.04; const double negativeThresh = -0.10; // in seconds const double positiveThresh = 0.10; // in seconds + const int bufferLimit = 32; [SetUp] public void SetUp() @@ -132,28 +133,40 @@ public void InsertIfNotExists() SimpleSnapshot b = new SimpleSnapshot(3, 0, 43); // add a - Assert.True(SnapshotInterpolation.InsertIfNotExists(buffer, a)); + Assert.True(SnapshotInterpolation.InsertIfNotExists(buffer, bufferLimit, a)); Assert.That(buffer.Count, Is.EqualTo(1)); Assert.That(buffer.Values[0], Is.EqualTo(a)); // add a again - shouldn't do anything - Assert.False(SnapshotInterpolation.InsertIfNotExists(buffer, a)); + Assert.False(SnapshotInterpolation.InsertIfNotExists(buffer, bufferLimit, a)); Assert.That(buffer.Count, Is.EqualTo(1)); Assert.That(buffer.Values[0], Is.EqualTo(a)); // add b - Assert.True(SnapshotInterpolation.InsertIfNotExists(buffer, b)); + Assert.True(SnapshotInterpolation.InsertIfNotExists(buffer, bufferLimit, b)); Assert.That(buffer.Count, Is.EqualTo(2)); Assert.That(buffer.Values[0], Is.EqualTo(a)); Assert.That(buffer.Values[1], Is.EqualTo(b)); // add b again - shouldn't do anything - Assert.False(SnapshotInterpolation.InsertIfNotExists(buffer, b)); + Assert.False(SnapshotInterpolation.InsertIfNotExists(buffer, bufferLimit, b)); Assert.That(buffer.Count, Is.EqualTo(2)); Assert.That(buffer.Values[0], Is.EqualTo(a)); Assert.That(buffer.Values[1], Is.EqualTo(b)); } + [Test] + public void InsertIfNotExists_RespectsBufferLimit() + { + // guarantee that we can never insert more than buffer limit + for (int i = 0; i < bufferLimit * 2; ++i) + { + SimpleSnapshot snap = new SimpleSnapshot(i, i, i); + SnapshotInterpolation.InsertIfNotExists(buffer, bufferLimit, snap); + } + Assert.That(buffer.Count, Is.EqualTo(bufferLimit)); + } + // UDP packets may arrive twice with the same snapshot. // inserting twice needs to be handled without throwing exceptions. [Test] @@ -168,8 +181,8 @@ public void InsertTwice() double localTimescale = 0; // insert twice - SnapshotInterpolation.InsertAndAdjust(buffer, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); // should only be inserted once Assert.That(buffer.Count, Is.EqualTo(1)); @@ -190,8 +203,8 @@ public void Insert_Sorts() SimpleSnapshot b = new SimpleSnapshot(3, 0, 43); // insert in reverse order - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); // should be in sorted order Assert.That(buffer.Count, Is.EqualTo(2)); @@ -215,11 +228,11 @@ public void Insert_InitializesLocalTimeline() SimpleSnapshot b = new SimpleSnapshot(3, 0, 43); // first insertion should initialize the local timeline to remote time - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time // second insertion should not modify the timeline again - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time } @@ -240,13 +253,13 @@ public void Insert_ComputesAverageDrift() SimpleSnapshot c = new SimpleSnapshot(5, 0, 43); // insert in order - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time // first insertion initializes localTime to '2'. @@ -272,13 +285,13 @@ public void Insert_ComputesAverageDrift_Scrambled() SimpleSnapshot c = new SimpleSnapshot(5, 0, 43); // insert scrambled (not in order) - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time // first insertion initializes localTime to '2'. @@ -309,13 +322,13 @@ public void Insert_ComputesAverageDeliveryInterval() SimpleSnapshot c = new SimpleSnapshot(5, 6, 43); // insert in order - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2 - bufferTime)); // initial snapshot - buffer time // first insertion doesn't compute delivery interval because we need 2 snaps. @@ -345,13 +358,13 @@ public void Insert_ComputesAverageDeliveryInterval_Scrambled() SimpleSnapshot c = new SimpleSnapshot(5, 6, 43); // insert in order - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2)); // detect wrong timeline immediately - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2)); // detect wrong timeline immediately - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2)); // detect wrong timeline immediately @@ -380,13 +393,13 @@ public void Sample() SimpleSnapshot b = new SimpleSnapshot(20, 0, 43); SimpleSnapshot c = new SimpleSnapshot(30, 0, 44); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time // sample at a time before the first snapshot @@ -424,13 +437,13 @@ public void Step() SimpleSnapshot b = new SimpleSnapshot(20, 0, 43); SimpleSnapshot c = new SimpleSnapshot(30, 0, 44); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time // step half way to the next snapshot @@ -455,13 +468,13 @@ public void Step_RemovesOld() SimpleSnapshot c = new SimpleSnapshot(30, 0, 44); double bufferTime = 30; // don't move timeline until all 3 inserted - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, a, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, b, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, bufferLimit, c, ref localTimeline, ref localTimescale, 0, bufferTime, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(10-bufferTime)); // initial snapshot - buffer time // step 1.5 snapshots worth, so way past the first one