My interpolation renders x frames in the past, when a packet comes in I buffer up the state with the current time. I think my issue is caused by network jitter, when packets come in late or early, current time isn't good enough. I implemented a queue for packets which arrive early or at the same time. With a fixed send rate (30 times per second), I assume clients have a stable enough connection so that if a packet comes in early, I can dequeue it 1/30th of a second after the last packet came in. I'm still getting visual jitters from what I believe is packets coming in late.
I'm trying to figure out how to assign interpolation times to reduce visual jitters as much as possible. Been struggling with this for a while, and thought it was time to ask for help. The attached video shows these jitters at the very beginning.
Entity update, this executes when packets come in and the interval can vary:
protected override void OnEntityUpdated(NetEntity entity, double remoteTime)
{
var nextFrame = new EntityFrame()
{
PacketTime = remoteTime,
CurTime = Time.time,
Position = entity.Origin,
Angles = entity.Angles,
Velocity = entity.Velocity
};
_history[unlag].TryAddFrame(nextFrame);
}
TryAddFrame:
public void TryAddFrame(EntityFrame frame)
{
var diff = frame.CurTime - _frames[0].CurTime;
var updateRate = 1f / FSLog.GetVariable<int>("net.entityrate");
if (diff < updateRate)
{
_insertDelay = updateRate - (float)diff;
}
else if(diff > updateRate * 1.25f)
{
Debug.Log("JITTER");
}
if (_insertDelay > 0
|| _jitterBuffer.Count > 0)
{
_jitterBuffer.Enqueue(frame);
return;
}
AddFrame(frame);
}
Interpolation loop, executed each frame:
double latency = frameBuffer * updateRate;
var renderTimestamp = Time.time - latency;
if(interp[0].CurTime > renderTimestamp)
{
for (int i = 0; i < interp.FrameCount; i++)
{
if (interp[i].CurTime <= renderTimestamp)
{
var toFrame = interp[Mathf.Max(i - 1, 0)];
var fromFrame = interp[i];
var t = (renderTimestamp - fromFrame.CurTime) / (toFrame.CurTime - fromFrame.CurTime);
var lerpedPos = Vector3.Lerp(fromFrame.Position, toFrame.Position, (float)t);
var lerpedAngle = Quaternion.Lerp(Quaternion.Euler(fromFrame.Angles), Quaternion.Euler(toFrame.Angles), (float)t);
unlag.Model.Set(lerpedPos, lerpedAngle.eulerAngles);
break;
}
}
}
else
{
// extrapolate?
}
2019-03-24_01-03-20.mp4