Skip to content

fix: [UpPort] NetworkList changes pending during client synchronization are applied twice - #4216

Merged
EmandM merged 9 commits into
develop-3.x.xfrom
up-port/fix/networklist-pending-sync-duplicates
Oct 30, 2026
Merged

EmandM merged 9 commits into
develop-3.x.xfrom
up-port/fix/networklist-pending-sync-duplicates

Conversation

@EmandM

@EmandM EmandM commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Requires #4236 to land before this PR can pass the unified tests.

Purpose of this PR

Override WriteFieldSynchronization in NetworkList so a client synchronized while local changes are still pending receives the list as of the last sent delta, mirroring NetworkVariable. The pending events are then applied exactly once with the next delta.

Fixes #4179

Jira ticket

n/a

Changelog

  • Fixed: Issue where a client synchronized while a NetworkList<T> still had unsent changes applied those changes twice, resulting in duplicate entries and index-based events landing on the wrong elements on that client.

Documentation

  • No documentation changes or additions were necessary.

Testing & QA (How your changes can be verified during release Playtest)

Functional Testing

Manual testing :

  • Manual testing done

Automated tests:

  • Covered by existing automated tests
  • Covered by new automated tests

Does the change require QA team to:

  • Review automated tests?
  • Execute manual tests?
  • Provide feedback about the PR?

If any boxes above are checked the QA team will be automatically added as a PR reviewer.

Up-port

n/a

Backports

2.x.x PR: #4215

…plied twice

Override WriteFieldSynchronization in NetworkList<T> so a client synchronized while local changes are still pending receives the list as of the last sent delta, mirroring NetworkVariable<T>. The pending events are then applied exactly once with the next delta.

Fixes #4179
@EmandM
EmandM requested a review from a team as a code owner October 23, 2026 21:21
@EmandM EmandM changed the title [UpPort] fix: NetworkList changes pending during client synchronization are applied twice fix: [UpPort] NetworkList changes pending during client synchronization are applied twice Oct 23, 2026

@u-pr u-pr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Harness Review

Needs changes

The change addresses the tested late-join scenario, but the captured snapshot relies on delta delivery that other synchronization paths do not guarantee.

Reviewed commit c112f59

🤖 Helpful? 👍/👎

{
if (m_DirtyEvents.Length == 0)
{
m_LastSentList.CopyFrom(m_List);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1

An initially empty list populated with Add before SpawnWithOwnership(clientId) now spawns empty on that owner when write permission is Owner. CannotWrite() permits pre-initialization edits, so CaptureLastSentList records the empty list. InternalOnSpawned leaves those events pending because the spawning server lacks owner write permission. WriteFieldSynchronization therefore sends the empty snapshot. NetworkVariableDeltaMessage.Serialize suppresses owner-write deltas to the owner, so the initial values never arrive. Treat pre-initialization edits as initial state rather than a pending-delta snapshot. Add a regression test for prepopulating a list before spawning with remote ownership.

🤖 Helpful? 👍/👎

{
// The pending events are sent to the synchronizing client with the next delta, so it must
// receive the list they apply to. Otherwise it would apply them twice.
if (m_HasLastSentList && m_DirtyEvents.Length > 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1

A client shown a list through NetworkShow while updates are throttled can remain permanently on the pre-change contents. NetworkShow calls ForceSendIfDirtyOnNetworkShow before serializing the spawn. CanSend() blocks sending and resetting the pending events, but ForceSendIfDirtyOnNetworkShow still removes the object from both updater sets. WriteFieldSynchronization now sends m_LastSentList, although the assumed next delta is no longer scheduled. Without another mutation, expiration of the update interval does not correct the client. Keep unsent objects queued after ForceSendIfDirtyOnNetworkShow. Add a throttled NetworkShow regression test with no subsequent mutations.

🤖 Helpful? 👍/👎

@NoelStephensUnity
NoelStephensUnity marked this pull request as draft October 23, 2026 21:35
@NoelStephensUnity
NoelStephensUnity marked this pull request as ready for review October 23, 2026 21:35

@u-pr u-pr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Harness Review

Ship it

The change adds a pending-state snapshot for list synchronization and a late-join regression test. I examined mutation capture, snapshot cleanup, serialization, and delta delivery paths and found no additional actionable issues beyond those already reported.

Reviewed commit 2d19f42

⚠️ Earlier blocking findings with unresolved threads: 2. The rating above does not cover them; resolve each thread after addressing it.

🤖 Helpful? 👍/👎

@NoelStephensUnity
NoelStephensUnity marked this pull request as draft October 23, 2026 21:51
@NoelStephensUnity
NoelStephensUnity marked this pull request as ready for review October 23, 2026 21:51

@u-pr u-pr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Harness Review

Ship it

The change adds a pre-delta list snapshot for client synchronization and a late-join regression test. I examined mutation coverage, snapshot cleanup, delta forwarding, and ownership transitions; I found no additional issues beyond those already reported.

Reviewed commit 2d19f42

⚠️ Earlier blocking findings with unresolved threads: 2. The rating above does not cover them; resolve each thread after addressing it.

🤖 Helpful? 👍/👎

@codecov-github-com

codecov-github-com Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

@@                Coverage Diff                @@
##           develop-3.x.x    #4216      +/-   ##
=================================================
- Coverage          76.91%   76.88%   -0.03%     
=================================================
  Files                159      159              
  Lines              27603    27665      +62     
=================================================
+ Hits               21230    21271      +41     
- Misses              6373     6394      +21     
Flag Coverage Δ
NGOv2_project_testproject_ubuntu 75.96% <100.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ameobjects/Runtime/Core/NetworkBehaviourUpdater.cs 98.19% <100.00%> (+0.17%) ⬆️
...Runtime/NetworkVariable/Collections/NetworkList.cs 81.49% <100.00%> (+1.73%) ⬆️
Components Coverage Δ
com.unity.netcode.gameobjects 76.88% <66.66%> (-0.03%) ⬇️

ℹ️ Need help interpreting these results?

NoelStephensUnity and others added 2 commits October 23, 2026 18:18
…d updates

ForceSendIfDirtyOnNetworkShow removed the NetworkObject from the updater even when NetworkVariableUpdateTraits held back its dirty variables, so those changes were not sent until the variable was modified again. Re-queue the object when anything is still dirty after the forced flush, and add a regression test for showing an object while NetworkList updates are throttled.

@NoelStephensUnity NoelStephensUnity left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@EmandM
EmandM enabled auto-merge (squash) October 26, 2026 21:53
@cla-assistant-unity

cla-assistant-unity Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@EmandM
EmandM merged commit b6c8608 into develop-3.x.x Oct 30, 2026
27 checks passed
@EmandM
EmandM deleted the up-port/fix/networklist-pending-sync-duplicates branch October 30, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NetworkList changes made since the last tick are applied twice on a newly synchronized client

4 participants