The local position (green&black lines) seems to oscillate around the goals (red lines) instead of moving between them smoothly.
Green: Local position when a packet is received (edited for clarity)
On a network with a realistic amount of lag and packet loss, this is the result:

The local position (green&black lines) seems to oscillate around the goals (red lines) instead of moving between them smoothly.
This is how it looks on a perfect network with the object moving right to left. (0 ping, 0 packet loss, etc.)

The code works like this:
Every x ms, receive a packet with a Vector3 position
Every x ms, receive a packet with a Vector3 positionSet the
Set thegoalto that positiongoalto that positionSet the
Set thepositionAtLastPacketto the current local positionpositionAtLastPacketto the current local positionEvery frame, lerp from
positionAtLastPackettogoal, attempting to reach the goal approximately when the next packet should arrive.
Every frame, lerp from// local transform position when the last packet arrived. Will lerp from here to the goal private Vector3 positionAtLastPacket; // location received from last packet private Vector3 goal; // time since the last packet arrived private float currentTime; // estimated time to reach goal (also the expected time of the next packet) private float timeToReachGoal; private void PacketReceived(Vector3 position, float timeBetweenPackets) { positionAtLastPacket = transform.position; goal = position; timeToReachGoal = timeBetweenPackets; currentTime = 0; Debug.DrawRay(transform.position, Vector3.up, Color.cyan, 5); // current local position Debug.DrawLine(transform.position, goal, Color.blue, 5); // path to goal Debug.DrawRay(goal, Vector3.up, Color.red, 5); // received goal position } private void FrameUpdate() { currentTime += Time.deltaTime; float delta = currentTime/timeToReachGoal; transform.position = FreeLerp(positionAtLastPacket, goal, currentTime / timeToReachGoal); // current local position Debug.DrawRay(transform.position, Vector3.up * 0.5f, Color.black, 5); } /// <summary> /// Lerp without being locked to 0-1 /// </summary> Vector3 FreeLerp(Vector3 from, Vector3 to, float t) { return from + (to - from) * t; }positionAtLastPackettogoal, attempting to reach the goal approximately when the next packet should arrive.- If the next packet takes longer than expected, interpolation continues past the goal and becomes extrapolation.
I believe what is happening is the extrapolation overshoots a bit to far. Over several packets, this issue compounds, causing the oscillation.
// local transform position when the last packet arrived. Will lerp from here to the goal
private Vector3 positionAtLastPacket;
// location received from last packet
private Vector3 goal;
// time since the last packet arrived
private float currentTime;
// estimated time to reach goal (also the expected time of the next packet)
private float timeToReachGoal;
private void PacketReceived(Vector3 position, float timeBetweenPackets)
{
positionAtLastPacket = transform.position;
goal = position;
timeToReachGoal = timeBetweenPackets;
currentTime = 0;
Debug.DrawRay(transform.position, Vector3.up, Color.cyan, 5); // current local position
Debug.DrawLine(transform.position, goal, Color.blue, 5); // path to goal
Debug.DrawRay(goal, Vector3.up, Color.red, 5); // received goal position
}
private void FrameUpdate()
{
currentTime += Time.deltaTime;
float delta = currentTime/timeToReachGoal;
transform.position = FreeLerp(positionAtLastPacket, goal, currentTime / timeToReachGoal);
// current local position
Debug.DrawRay(transform.position, Vector3.up * 0.5f, Color.black, 5);
}
/// <summary>
/// Lerp without being locked to 0-1
/// </summary>
Vector3 FreeLerp(Vector3 from, Vector3 to, float t)
{
return from + (to - from) * t;
}