Skip to content

Commit 861dbf1

Browse files
update
Simplifying the new direction and getting all tests to pass. (still needs a smoother transition between buffered items when not finished interpolating from a previous one)
1 parent 6eadea1 commit 861dbf1

1 file changed

Lines changed: 36 additions & 63 deletions

File tree

com.unity.netcode.gameobjects/Runtime/Components/Interpolator/BufferedLinearInterpolator.cs

Lines changed: 36 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,7 @@ public BufferedItem(T item, double timeSent)
6666
private int m_NbItemsReceivedThisFrame;
6767

6868
protected internal T m_CurrentInterpValue;
69-
private int m_LifetimeConsumedCount;
70-
71-
private bool InvalidState => m_Buffer.Count == 0 && m_LifetimeConsumedCount == 0;
72-
69+
private double m_LastMeasurementAddedTime = 0.0f;
7370
internal bool EndOfBuffer => m_Buffer.Count == 0;
7471

7572
internal bool InLocalSpace;
@@ -92,11 +89,8 @@ public void Clear()
9289
{
9390
m_Buffer.Clear();
9491
m_CurrentInterpValue = default;
95-
InterpolateState = new CurrentState()
96-
{
97-
CurrentValue = default,
98-
LerpT = 0.0000001f,
99-
};
92+
m_LastMeasurementAddedTime = 0.0;
93+
InterpolateState.Reset(default);
10094
}
10195

10296
/// <summary>
@@ -106,16 +100,13 @@ public void Clear()
106100
/// <param name="serverTime">The current server time</param>
107101
public void ResetTo(T targetValue, double serverTime)
108102
{
109-
m_LifetimeConsumedCount = 1;
110-
m_Buffer.Clear();
111103
m_Name = GetType().Name;
104+
// Clear everything first
105+
Clear();
106+
// Set our initial value
107+
InterpolateState.Reset(targetValue);
108+
// TODO: If we get single lerping working, then m_CurrentInterpValue is no longer needed.
112109
m_CurrentInterpValue = targetValue;
113-
InterpolateState = new CurrentState()
114-
{
115-
CurrentValue = targetValue,
116-
LerpT = 0.0000001f,
117-
};
118-
Update(0, serverTime, serverTime);
119110
}
120111

121112
// todo if I have value 1, 2, 3 and I'm treating 1 to 3, I shouldn't interpolate between 1 and 3, I should interpolate from 1 to 2, then from 2 to 3 to get the best path
@@ -183,15 +174,21 @@ private void TryConsumeFromBufferLDK(double renderTime, double serverTime)
183174

184175
internal struct CurrentState
185176
{
186-
public BufferedItem? Start;
187-
188-
public BufferedItem? End;
177+
public BufferedItem? Target;
189178

190179
public double RelativeTime;
191180

192181
public T CurrentValue;
193182

194183
public float LerpT;
184+
185+
public void Reset(T currentValue)
186+
{
187+
CurrentValue = currentValue;
188+
// When reset, we consider ourselves to have already arrived at the target (even if no target is set)
189+
LerpT = 1.0f;
190+
RelativeTime = 0.0;
191+
}
195192
}
196193

197194
internal CurrentState InterpolateState;
@@ -200,42 +197,27 @@ private void TryConsumeFromBuffer(double renderTime, double serverTime)
200197
{
201198
// If we don't have our initial buffered item/starting point or our end point or the end point's time sent is less than the
202199
// render time
203-
if (!InterpolateState.Start.HasValue || !InterpolateState.End.HasValue || InterpolateState.End.Value.TimeSent < renderTime)
200+
if (!InterpolateState.Target.HasValue || InterpolateState.Target.Value.TimeSent < renderTime)
204201
{
205202
BufferedItem? previousItem = null;
206203
while (m_Buffer.TryPeek(out BufferedItem potentialItem))
207204
{
205+
// If we are still on the same buffered item (FIFO Queue), then exit early as there is nothing
206+
// to consume.
208207
if (previousItem.HasValue && previousItem.Value.TimeSent == potentialItem.TimeSent)
209208
{
210209
break;
211210
}
212211

212+
// At a minimum, the next item should be equal to or less than the server time
213213
if (potentialItem.TimeSent <= serverTime)
214214
{
215-
// We want to initialize and then always set the end
216-
if (!InterpolateState.Start.HasValue)
215+
if (!InterpolateState.Target.HasValue || InterpolateState.Target.Value.TimeSent < potentialItem.TimeSent)
217216
{
218-
if (m_Buffer.TryDequeue(out BufferedItem start))
217+
if (m_Buffer.TryDequeue(out BufferedItem target))
219218
{
220-
InterpolateState.Start = start;
221-
InterpolateState.RelativeTime = InterpolateState.Start.Value.TimeSent;
222-
InterpolateState.CurrentValue = start.Item;
219+
InterpolateState.Target = target;
223220
InterpolateState.LerpT = 0.0f;
224-
InterpolateState.Start = start;
225-
}
226-
}
227-
else if (!InterpolateState.End.HasValue || InterpolateState.End.Value.TimeSent < potentialItem.TimeSent)
228-
{
229-
if (m_Buffer.TryDequeue(out BufferedItem end))
230-
{
231-
if (InterpolateState.End.HasValue)
232-
{
233-
InterpolateState.Start = InterpolateState.End;
234-
//m_CurrentState.RelativeTime = m_CurrentState.End.Value.TimeSent;
235-
}
236-
InterpolateState.End = end;
237-
InterpolateState.LerpT = 0.0f;
238-
m_LifetimeConsumedCount++;
239221
break;
240222
}
241223
}
@@ -244,7 +226,7 @@ private void TryConsumeFromBuffer(double renderTime, double serverTime)
244226
break;
245227
}
246228
}
247-
if (!InterpolateState.Start.HasValue)
229+
if (!InterpolateState.Target.HasValue)
248230
{
249231
break;
250232
}
@@ -277,21 +259,16 @@ public T Update(float deltaTime, double renderTime, double serverTime)
277259
{
278260
TryConsumeFromBuffer(renderTime, serverTime);
279261

280-
if (InvalidState)
281-
{
282-
throw new InvalidOperationException("trying to update interpolator when no data has been added to it yet");
283-
}
284-
285262
// Only interpolate when there is a start and end point and we have not already reached the end value
286-
if (InterpolateState.Start.HasValue && InterpolateState.End.HasValue)
263+
if (InterpolateState.Target.HasValue)
287264
{
288265
if (InterpolateState.LerpT < 1.0f)
289266
{
290-
InterpolateState.RelativeTime = Math.Clamp(InterpolateState.RelativeTime + deltaTime, 0.000001f, InterpolateState.End.Value.TimeSent);
267+
InterpolateState.RelativeTime = Math.Clamp(InterpolateState.RelativeTime + deltaTime, 0.000001f, InterpolateState.Target.Value.TimeSent);
291268
//var t = 1.0f - Mathf.Clamp((float)((m_EndTimeConsumed - renderTime) * rangeFactor), 0.0f, 1.0f);
292269
//var alt_t = 1.0f - Mathf.Clamp((float)((renderTime - m_StartTimeConsumed) * rangeFactor), 0.0f, 1.0f);
293-
InterpolateState.LerpT = (float)(InterpolateState.RelativeTime / InterpolateState.End.Value.TimeSent);
294-
InterpolateState.CurrentValue = Interpolate(InterpolateState.CurrentValue, InterpolateState.End.Value.Item, InterpolateState.LerpT);
270+
InterpolateState.LerpT = (float)(InterpolateState.RelativeTime / InterpolateState.Target.Value.TimeSent);
271+
InterpolateState.CurrentValue = Interpolate(InterpolateState.CurrentValue, InterpolateState.Target.Value.Item, InterpolateState.LerpT);
295272
if (InterpolateState.LerpT < 1.0f)
296273
{
297274
m_CurrentInterpValue = Interpolate(m_CurrentInterpValue, InterpolateState.CurrentValue, 0.5f);
@@ -307,8 +284,6 @@ public T Update(float deltaTime, double renderTime, double serverTime)
307284
return m_CurrentInterpValue;
308285
}
309286

310-
311-
private double m_LastSentTime = 0.0f;
312287
/// <summary>
313288
/// Add measurements to be used during interpolation. These will be buffered before being made available to be displayed as "latest value".
314289
/// </summary>
@@ -333,17 +308,15 @@ public void AddMeasurement(T newMeasurement, double sentTime)
333308
return;
334309
}
335310

336-
// Part the of reason for disabling extrapolation is how we add and use measurements over time.
337-
// TODO: Add detailed description of this area in Jira ticket
338-
if (sentTime > m_LastSentTime || m_LifetimeConsumedCount == 0) // treat only if value is newer than the one being interpolated to right now
311+
if (sentTime > m_LastMeasurementAddedTime)
339312
{
340313
m_LastBufferedItemReceived = new BufferedItem(newMeasurement, sentTime);
341314
m_Buffer.Enqueue(m_LastBufferedItemReceived);
342-
m_LastSentTime = sentTime;
315+
m_LastMeasurementAddedTime = sentTime;
343316
}
344317
else
345318
{
346-
Debug.Log($"[{m_Name}] Dropping measurement -- Time: {sentTime} Value: {newMeasurement}");
319+
Debug.Log($"[{m_Name}] Dropping measurement -- Time: {sentTime} Value: {newMeasurement} | Last measurement -- Time: {m_LastMeasurementAddedTime} Value: {m_LastBufferedItemReceived.Item}");
347320
}
348321
}
349322

@@ -465,9 +438,9 @@ protected internal override void OnConvertTransformSpace(Transform transform, bo
465438
}
466439
InterpolateState.CurrentValue = ConvertToNewTransformSpace(transform, InterpolateState.CurrentValue, inLocalSpace);
467440
m_CurrentInterpValue = ConvertToNewTransformSpace(transform, m_CurrentInterpValue, inLocalSpace);
468-
var end = InterpolateState.End.Value;
441+
var end = InterpolateState.Target.Value;
469442
end.Item = ConvertToNewTransformSpace(transform, end.Item, inLocalSpace);
470-
InterpolateState.End = end;
443+
InterpolateState.Target = end;
471444

472445
base.OnConvertTransformSpace(transform, inLocalSpace);
473446
}
@@ -535,9 +508,9 @@ protected internal override void OnConvertTransformSpace(Transform transform, bo
535508

536509
InterpolateState.CurrentValue = ConvertToNewTransformSpace(transform, InterpolateState.CurrentValue, inLocalSpace);
537510
m_CurrentInterpValue = ConvertToNewTransformSpace(transform, m_CurrentInterpValue, inLocalSpace);
538-
var end = InterpolateState.End.Value;
511+
var end = InterpolateState.Target.Value;
539512
end.Item = ConvertToNewTransformSpace(transform, end.Item, inLocalSpace);
540-
InterpolateState.End = end;
513+
InterpolateState.Target = end;
541514

542515
base.OnConvertTransformSpace(transform, inLocalSpace);
543516
}

0 commit comments

Comments
 (0)