Tutorial: Networked Physics - Fundamentals

Learn to understand the fundamentals of networked physics to be able to develop and design within the limitations. Understanding also means you can debug better.

https://dev.epicgames.com/community/learning/tutorials/5E4w/unreal-engine-networked-physics-fundamentals

Hey there, thank you so much for putting out these tutorials! They’re super helpful. I’m excited for the next part, but take your time—no hurry. Have a wonderful summer! Thanks again and all the best.

Hi @MBobbo, first of all — we migrated our Early Access title from 5.7 to 5.8 last week and can confirm the Predictive Interpolation post-resim restore fix works great in practice: in 5.7, PI sim proxies visibly jittered back and forth whenever the local player collided with them; in 5.8 the same interaction is down to occasional minor hitches. Thank you for that, it alone justified the upgrade for us.

Some context: our game is a physics party game (soap-bar pawns sliding on surfaces), listen server, up to 8 players, 30Hz async physics. Every pawn runs a TSimCallbackObject + UNetworkPhysicsComponent with the Iris flow (TNetworkPhysicsInputState_Internal, CreateDataHistory), autonomous proxy on Resimulation. We have three topics after a full day of structured 5.8 testing.

1. Sim proxy replication mode — the symmetric tradeoff between Resim and PI

We tested sim proxy pawns in both modes (via the Sim Proxy Rep Mode override on the NetworkPhysicsSettingsDataAsset), with ~100–200ms simulated latency:

  • Sim proxies on Resimulation: the local player hitting others feels great — the collision happens locally in the predicted timeline, corrections are small. But being hit shows what we call “contactless knockback”: the attacker’s forward-predicted image relies on late-arriving inputs plus input decay, so when they accelerate toward us their predicted position lags behind their real approach. The server’s collision correction then arrives while the attacker visually hasn’t reached us — we get knocked back before any visible contact. Tuning np2.Resim.InputDecayReferenceLagMs up (100 → 200 at 200ms latency) noticeably improved our own hit registration, but the being-hit gap persists — which makes sense, since no decay value can predict an opponent’s sudden acceleration.
  • Sim proxies on Predictive Interpolation: the exact mirror image. Being hit is clean — the attacker’s interpolated image and the server’s knockback correction are delayed by roughly the same amount, so the impulse lands visually on contact. Hitting others shows small hitches on the target instead (acceptable in 5.8 thanks to the fix above).

For a party game we’ve provisionally picked PI for sim proxies (consistent “being hit” feel matters more to us). Two questions:

  • Is there any setting or technique we’re missing that softens the prediction starvation for an approaching attacker in Resim mode — or is PI for sim proxies simply the pragmatic choice until Physics Replication LOD matures enough to handle the transition per-object?
  • Is the LOD + Bubble Resim combination in 5.8 far enough along that you’d recommend a project like ours (small arenas, everything is always near the player) invest in tuning it, or is close-quarters gameplay exactly the case where LOD’s distance bands don’t help?

2. Is the bool + edge-consume + state-mirror pattern the correct shape for one-shots (pre-Actions)?

Since 5.7 our one-shot events (jump, launch impulse, grapple pull, two ability triggers) ride the networked input as a bool + payload vector, with three rules we learned the hard way:

  • MergeData ORs the bool (a plain assignment silently drops the event when two input frames merge);
  • the PT edge-consume flag is mirrored into the networked state via BuildState_Internal / ApplyState_Internal, so a resimulation rewind restores the un-consumed flag and the impulse is re-applied during replay (we shipped a bug where three channels were missing the mirror — resims ended in states the original simulation never reached);
  • only the bool participates in CompareData; vectors stay out. We keep np2.Resim.CompareStateToTriggerRewind / CompareInputToTriggerRewind off per your recommendation, so resims are transform-threshold-driven only.

Is this the canonical shape for one-shots in 5.7/5.8 absent the Actions system, or is there a known better pattern? The remaining cost we observe: the impulse lands on different physics frames on server vs. client, so effectively every fire costs the client a resimulation, and the correction magnitude scales with latency.

3. Actions — timeline and expected benefits of migrating

We’ve mapped the 5.8 Actions API from the public headers (FNetworkPhysicsActionPayload, SetActionHandler / ApplyAction_Internal, the EnqueueAction / EnqueueScheduledAction(AtFrame) families, EActionAuthorStyle including the Proposed styles) and read ChaosMover’s usage as the reference implementation. We’re holding off on migrating until the Gameplay Tutorial lands. Questions:

  • Any estimate on when the Gameplay Tutorial will be published?
  • Is migrating one-shots from bool-inputs to Actions the intended direction? Our expected benefits: same-ServerFrame application on every machine (eliminating the per-fire resim above), built-in re-application bookkeeping during resimulation replacing our hand-rolled state mirror, and the Proposed author style replacing hand-rolled tolerance checks. Is that the right mental model, or are there benefits/costs we’re missing?
  • For latency-sensitive instant actions (jump on button press), is the Immediate (non-scheduled) enqueue path viable, or is scheduling with the min-delay setting (Event Scheduling Min Delay Seconds) the intended use for everything?
  • Would you consider the Actions API stable enough in 5.8 to adopt in a shipping Early Access title now, or would you advise waiting for the tutorial and possibly 5.9?

Thanks again for the tutorials and the continued support in this thread — the Fundamentals write-up answered questions we didn’t know we had.