My “slippery tail” interpolation worked well for rotation. Rotation has no inertia (start and stop immediately). The magic number to lag behind is half your ping to the server. This definitely wasn’t obvious why and it took me an hour of thinking to really see it.
It doesn’t work for position. Theoretically it should work, but in practice small errors in timing, ping variances, and high latency all cause failure. On the front side, when I am finishing a prior interpolation, if my new extrapolated position doesn’t match exactly, I get a position warp. This happens easily from ping variance. On the back side, with very high pings the extrapolated position differences are so large it just ends up looking like a warp.
For position I’m trying what I call trajectory intercept interpolation. When the datagram arrives I store the current visual position and physics velocity. The start interpolation position is where you would normally be (visual position + original velocity * elapsed interp time). The end interpolation is the intercept when we stop interpolating (real position + real velocity * remaining interp time).
This method doesn’t jerk (jerk is a change in acceleration) which I do get if I were to not count original velocity. It also gives me an accurate visual position. Hopefully it will work.
Other problems fixed:
PhysX jitters using fixed timesteps. Fixed by changing to variable.
Stopped using per-datagram timestamps. Just use half the average ping. This also removes a potential cheat.
I was previously allowing you to accelerate past your maximum velocity, then clamping the next tick. This caused inaccuracy. Now I have to duplicate the physics calculations and determine the force to apply to make you reach your maximum velocity exactly.
Previously network packets were processed after the tick update, so clearing acceleration didn’t take until one tick too late, resulting in slightly too high velocity.
These bugs were massively difficult to find. This has been a very painful day.