Skip to content

NetworkTransform: half-float base update dropped as out of order when UseUnreliableDeltas is on, so later deltas decode ~2 m off #4248

Open

Description

@zchristensen01

Description

With UseHalfFloatPrecision and UseUnreliableDeltas both on, a non-authority NetworkTransform can lose a half-float base update and then decode every following delta against the old base. The object is drawn about 2 m off (one MaxDeltaBeforeAdjustment step) until the next unreliable frame sync, up to a second later.

How it happens (line numbers from 2.13.3; the same code is in develop-3.x.x today):

  1. When an axis's delta reaches NetworkDeltaPosition.MaxDeltaBeforeAdjustment (2 m), the delta collapses into a new base. That state is flagged SynchronizeBaseHalfFloat and sent reliably (NetworkTransformState.NetworkSerialize, NetworkTransform.cs:739-747: UseHalfFloatPrecision && NetworkDeltaPosition.CollapsedDeltaIntoBase → ReliableSequenced = true).
  2. The deltas that follow go unreliably. Under jitter or a lost packet, a newer unreliable delta can arrive before the reliable base update.
  3. When the base update then arrives, it has an older tick than the state already applied. OnNetworkStateChanged drops it (NetworkTransform.cs:3326):
    if (UseUnreliableDeltas && oldState.NetworkTick > newState.NetworkTick && !newState.FlagStates.IsTeleportingNextFrame && !newState.FlagStates.UnreliableFrameSync)
    {
        return;
    }
    Teleports and frame syncs are exempt, but a base sync isn't.
  4. The non-authority's NetworkDeltaPosition keeps the old base, so every later half-float delta decodes about 2 m off until a frame sync corrects it.

Reproduce Steps

  1. A player prefab with an owner-authoritative NetworkTransform: UseHalfFloatPrecision on, UseUnreliableDeltas on, position synced on all axes, interpolation on.
  2. Host + 1 client (client-server). Simulate a poor connection on the host: about 75 ms delay with ±20 ms jitter and 2% packet loss (Unity Transport's simulator pipeline, or the Multiplayer Tools network simulator).
  3. The client walks in a straight line at about 4.5 m/s for 20–30 s.
  4. On the host, compare its copy of the client's player with the client's real position (log both every frame).

Actual Outcome

The host's copy usually trails by about 0.6 m, but every few seconds it jumps 2 m or more off for up to a second. In our measurements it was 2.5–4.6 m behind during those stretches. Logging NetworkDeltaPosition on both sides during one of them: the host's base on the walking axis was 4.17 m while the client's was 6.25 m (one 2 m step plus the delta).

Expected Outcome

A late base update is still applied (at least its base), so later deltas decode against the right base. Two possible fixes:

  • exempt SynchronizeBaseHalfFloat states from the out-of-order rule, as teleports and frame syncs are;
  • or apply the base of a dropped state to NetworkDeltaPosition even when its position is ignored.

Screenshots

None. The numbers above come from per-frame logs.

Environment

  • OS: Windows 11 Pro
  • Unity Version: 6000.3.27f1
  • Netcode Version: 2.13.3 (also present in develop-3.x.x and 3.2.0: the same check is at NetworkTransform.cs:3345 there)
  • Netcode Commit: the v2.13.3 release
  • Netcode Topology: Client-Server (host)

Additional Context

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions