Summary
With PreferredTickingPolicy=Fixed and SimulatedProxyNetworkLOD=Interpolated, the interpolation frame used for simulated proxies is set once, at LatestRecvFrame - FixedTickInterpolationBufferedMS / step (6 frames at 60 Hz). Afterwards it only advances with real time, or stops when it reaches the latest received frame. Nothing ever makes it advance faster. As a result, every late arrival (a long frame, packet loss, jitter, a server frame with several fixed steps) permanently increases the delay between the latest received frame and the displayed frame. The delay never goes back down for the rest of the session.
What Type of Bug are you experiencing?
Networking
Steps to Reproduce
- Project with a Mover character replicated through Network Prediction (we used the Game Animation Sample pawn with the Mover component).
- Config/DefaultNetworkPrediction.ini:
PreferredTickingPolicy=Fixed
FixedTickFrameRate=60
SimulatedProxyNetworkLOD=Interpolated
FixedTickInterpolationBufferedMS=100 (default) - PIE, Run Under One Process, 2 players (dedicated or listen server). Network emulation on clients: 50-75 ms each way, 2% loss.
- On each client, once per second, log the gap between the latest received frame and the interpolation ToFrame, read from UNetworkPredictionWorldManager::GetFixedTickState() (Public/NetworkPredictionWorldManager.h:95). The Network Prediction trace does not record these values, so they must be read from code.
- Either let the session run for several minutes (jitter and loss alone make the gap grow slowly), or produce any frame longer than about 2 s.
Expected Result
After a late arrival or a long frame, the interpolation delay returns to about FixedTickInterpolationBufferedMS (6 frames at 60 Hz), for example by interpolating slightly faster or by restarting the interpolation timeline.
Observed Result
The delay stays at its new value until the end of the session. Our measurements (median per 30 s):
- dedicated, 50-75 ms: 9 → 52 frames (about 870 ms) after a 2.1 s frame (cause not identified), never recovered;
- dedicated, 100-150 ms, 5% loss: 4 → 11 frames;
- listen server, 100-150 ms: 4 → 12 frames after a 0.48 s frame;
- listen server, 50-75 ms: 5 → 8 → 18 frames with no frame longer than 0.25 s (jitter and loss alone).
Remote characters are displayed farther and farther in the past during a match. This affects what the player sees: aiming at remote characters and client-predicted contact with them. In our project hits are evaluated by the server on its own positions, so server-side hit evaluation is not affected; projects that evaluate hits on the client would be.
Affects Versions
5.8
Platform(s)
Windows
Additional Notes
Relevant code (paths relative to Engine/Plugins/Runtime/NetworkPrediction/Source/NetworkPrediction/)
- Interpolation start, set once: Private/NetworkPredictionWorldManager.cpp, UNetworkPredictionWorldManager::BeginNewSimulationFrame_Internal, line 405 (block 389-413)
- The only updates of the interpolation frame (advance with real time, or stop at the latest received frame), with no catch-up branch: same function, lines 424-426 and 435-439 (blocks 417-427 and 431-447)
- The state is private, with a const-only getter: Public/NetworkPredictionWorldManager.h, lines 95-102. No setting, CVar or public function can resync it.
- np.Interpolation.Disable only shows the latest received state, without smoothing: NetworkPredictionService_Interpolate.inl, lines 204-214