Skip to content

feat: hybrid NetcodeConfig defaults - #4144

Merged
NoelStephensUnity merged 37 commits into
develop-3.x.xfrom
feat/hybrid-netcodeconfig-defaults
Oct 8, 2026
Merged

NoelStephensUnity merged 37 commits into
develop-3.x.xfrom
feat/hybrid-netcodeconfig-defaults

Conversation

@NoelStephensUnity

@NoelStephensUnity NoelStephensUnity commented Aug 25, 2026 •

Copy link
Copy Markdown
Member

Purpose of this PR

This PR addresses Netcode for GameObjects' hybrid mode operation requirements for the two NetcodeConfig settings, disabling auto bootstrap and tick rate frquency, while also providing users with an optional snapshot size configuration of 4096 bytes (more info about these below).

Jira ticket

MTT-15571

PR Scope:

Required runtime NetcodeConfig adjustments:

Tick rates follow NetworkConfig.TickRate. Netcode for GameObjects' own send queues are flushed by a system in Netcode for Entities' SimulationSystemGroup, so a simulation rate below NetworkConfig.TickRate starves outbound traffic. Netcode for Entities defaults to 60 and Netcode for GameObjects to 30.

UnifiedBootstrap no longer delegates to base.Initialize. Entities selects the most derived ICustomBootstrap, so this type is the only one it instantiates under UNIFIED_NETCODE and Netcode for Entities' own Initialize is never reached on its own. Calling it only gave Netcode for Entities a chance to create worlds this bootstrap would then reject, which is why EnableClientServerBootstrap had to be configured at all. It no longer does.

Optional runtime NetcodeConfig adjustments:

Snapshot packet size, behind the new NetworkConfig.AutoConfigureSnapshotSize. Netcode for Entities defaults to a single MTU, which round-robins above roughly 230 GhostObjects. Measured at 512 instances against a 30Hz tick rate:

Snapshot packet size GhostObjects per snapshot Effective update rate
MTU (the Netcode for Entities default) 230.6 13.51Hz
4096 512.0 30.00Hz

Below that count the cap is never reached, so it costs nothing. Users can disable this option and configure it themselves in their project's NetcodeConfig.

This property is placed into its own section within the NetworkManager inspector view for easier discoverability:
image

Test harness fix (blocks #4186):

m_AllPrefabsAsHybrid is restored after every test case. A fixture that takes its HostOrServer as a method parameter sets the flag from the test body, but SetUp runs before that. After any Unified* case the flag stayed set, so the next case created a hybrid prefab nobody asked for and the server start sweep rejected it as an unregistered NetworkObject. The flag is captured when the fixture is constructed and restored in TearDown (restored, not cleared: a [TestFixture(HostOrServer.UnifiedHost)] sets it in its constructor and needs it for every case in the fixture).

This only reproduces where UNIFIED_NETCODE is compiled and the ordinary suite runs, which is why CI has not shown it until now. It accounts for the 96 NetworkVariableTests failures on #4186.

Out of scope:

  • The editor applier, the Project Settings section and the applied-defaults version marker are removed (nothing writes the asset, so there is nothing to track or to restore).
  • The interpolation, despawn reservation and transport queue values are removed (tuned against a 2000 instance stress test; they are either inside Netcode for Entities' own recommended ranges or inert below the snapshot packet size).
  • UnifiedSnapshotPacketSizeMeasurement is removed (an [Explicit] measurement harness that CI never selects, so it only added review surface; it moves to the NGO Examples project).
  • testproject's NetcodeConfig is left in place (every value in it is now overwritten at session start or already equal to the Netcode for Entities default. The asset itself is removed in chore: enable unified netcode from N4E 7.2.0, only for hybrid prefab sessions #4186).

Issues found, but were not fixed for this pass and require a follow-up PR

The server schedules its disconnect reason into Netcode for Entities' outgoing RPC buffer and then tears the connection down in the same call, before RpcSystem transmits it, so the client never receives the reason.

The FailValidation and ClientDoesNotRequest hybrid prefab test cases are excluded until that is fixed.

Changelog

  • Added: Alignment of the Netcode for Entities tick rates with NetworkConfig.TickRate when a session carrying GhostObject prefabs is started.
  • Added: NetworkConfig.AutoConfigureSnapshotSize, enabled by default, which sets the Netcode for Entities snapshot packet size to 4096 bytes when a session carrying GhostObject prefabs is started.
  • Fixed: Issue where the hybrid mode NetcodeConfig validation messages were not interpolated.
  • Fixed: Issue where a hybrid mode session failed to start unless NetcodeConfig.EnableClientServerBootstrap was set to DisableAutomaticBootstrap.

Documentation

  • Includes documentation (wip)

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

Functional Testing

Manual testing :

  • Manual testing done
    • Open a project with Netcode for GameObjects and Netcode for Entities installed and a prefab carrying a GhostObject.
    • Start a session and inspect the NetcodeConfig asset: it is unchanged on disk.
    • The running session uses the NetworkManager tick rate for the Netcode for Entities tick rates, and a snapshot packet size of 4096 unless NetworkConfig.AutoConfigureSnapshotSize is disabled.

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?

Up-port

None

Backports

None

When Netcode for Entities is installed and a registered network prefab
carries a GhostObject, the project's NetCodeConfig is now aligned with
what NGO needs rather than leaving it to the user to discover.

The two settings hybrid mode cannot run without (single world hosting,
and automatic bootstrapping disabled since NetworkManager owns world
creation) are corrected whenever they drift. The Netcode for Entities
tick rates are driven from NetworkConfig.TickRate so that ghost
transform updates land on the same interval as everything else. The
snapshot, interpolation and transport values tuned against the 2000
instance stress test are applied once and then left alone, so a user's
own edits survive; Project Settings > Multiplayer > Netcode for
GameObjects can restore them.

The config is never created here. Netcode for Entities already creates
one unconditionally from its own InitializeOnLoadMethod, and creating a
second lands the project in its multiple-config error path.

Also:
- UnifiedIsConfiguredCorrectly now validates EnableClientServerBootstrap
  and warns when the two tick rates diverge. Its two log messages were
  missing their string interpolation prefixes.
- m_TempStreamSize returns to the Netcode for Entities default of 8192.
  GhostSendSystem takes max(TempStreamInitialSize, dataStream.Capacity),
  and capacity is DefaultSnapshotPacketSize, so 4192 had no effect.
- Unity.Netcode.Editor.Tests gains the UNIFIED_NETCODE version define.
  Without it any hybrid editor test compiles away and reports zero cases
  rather than failing.
- Adds a measurement fixture for sizing DefaultSnapshotPacketSize. It is
  marked Explicit so its 24 cases stay out of the suites.
Some comment clean up.
@NoelStephensUnity
NoelStephensUnity requested review from a team and EmandM as code owners August 25, 2026 15:08

@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 new hybrid configuration flow establishes the intended defaults and exposes them in settings, but several reachable editor states prevent it from preserving or aligning those defaults correctly.

Reviewed commit 49e605e

🤖 Helpful? 👍/👎

Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Fixing some things u-pr caught and adding a test to validate the update.
@danni-lu

Copy link
Copy Markdown

Is it possible to add a call to action to the console log that the user can click on the directly open the relevant page?
networkConfigParamter foldout content is a bit too much to the right, can shift 1 level to the left
If I press the apply recommended hybrid defaults button, are settings above it be changed?

@NoelStephensUnity

Copy link
Copy Markdown
Member Author

Is it possible to add a call to action to the console log that the user can click on the directly open the relevant page? networkConfigParamter foldout content is a bit too much to the right, can shift 1 level to the left If I press the apply recommended hybrid defaults button, are settings above it be changed?

I was actually thinking that we should make that a dialog box that explains what was updated and where to reset back to the defaults. The console log could easily be missed.

Is it possible to add a call to action to the console log that the user can click on the directly open the relevant page? networkConfigParamter foldout content is a bit too much to the right, can shift 1 level to the left If I press the apply recommended hybrid defaults button, are settings above it be changed?

This would be a change to the NetcodeConfig property drawer in N4E.
Would you like me to open a ticket for that UI adjustment?

@codecov-github-com

codecov-github-com Bot commented Aug 25, 2026 •

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

@@                Coverage Diff                @@
##           develop-3.x.x    #4144      +/-   ##
=================================================
+ Coverage          78.26%   78.36%   +0.09%     
=================================================
  Files                153      154       +1     
  Lines              26359    26630     +271     
=================================================
+ Hits               20631    20868     +237     
- Misses              5728     5762      +34     
Flag Coverage Δ
NGOv2_project_testproject_ubuntu 77.29% <ø> (ø)

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

Files with missing lines Coverage Δ
...gameobjects/Runtime/Configuration/NetworkConfig.cs 63.12% <ø> (ø)
...netcode.gameobjects/Runtime/Core/NetworkManager.cs 79.97% <ø> (ø)

... and 5 files with indirect coverage changes

Components Coverage Δ
com.unity.netcode.gameobjects 78.36% <ø> (+0.09%) ⬆️

ℹ️ Need help interpreting these results?

@danni-lu

Copy link
Copy Markdown

Is it possible to add a call to action to the console log that the user can click on the directly open the relevant page? networkConfigParamter foldout content is a bit too much to the right, can shift 1 level to the left If I press the apply recommended hybrid defaults button, are settings above it be changed?

I was actually thinking that we should make that a dialog box that explains what was updated and where to reset back to the defaults. The console log could easily be missed.

Ah ok ok! Yea, a helpbox with some Call-to-action would make more sense.

Is it possible to add a call to action to the console log that the user can click on the directly open the relevant page? networkConfigParamter foldout content is a bit too much to the right, can shift 1 level to the left If I press the apply recommended hybrid defaults button, are settings above it be changed?

This would be a change to the NetcodeConfig property drawer in N4E. Would you like me to open a ticket for that UI adjustment?

Yea, we could look at the workflow a bit closer

@NoelStephensUnity
NoelStephensUnity enabled auto-merge (squash) August 27, 2026 15:22

@EmandM EmandM 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.

Big concern here with using AssetDatabase.FindAssets.

  1. It's very slow
  2. The pattern will change and/or go away as the editor moves towards importing on demand.

Relevant assets should register themselves in OnEnable, that way behaviour will be automatically triggered when relevant rather than doing an expensive search over many irrelevant things.

Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/NetcodeSettingsProvider.cs Outdated
Comment thread com.unity.netcode.gameobjects/Editor/Configuration/NetcodeSettingsProvider.cs Outdated
/// snapshot metrics singleton for a fixed sample window. Results are emitted as "PKTSZ|" log lines.
/// </summary>
[TestFixture(HostOrServer.UnifiedHost)]
[Explicit("Measurement harness, not a regression test. The 24 auto-expanded cases take ~162s, so it only runs when selected by name: -testFilter \".*UnifiedSnapshotPacketSizeMeasurement.*\"")]

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.

Can we not add tests that we have to explictly run. We're going to forget they exist and never run them

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The explicit attribute:
Measurement harness, not a regression test.

It is just a tool for measurement purposes. If you would like me to remove this tool I can do that.
(I can keep a copy of this somewhere else so I can run this to verify the snapshot sizes)

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.

What is it measuring? When do we need to be measuring? Might be worth writing some internal docs explaining that the tool exists and what it does?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Measurement harness (not a pass/fail behaviour test) used to determine bandwidth consumption based on the NetCode.GhostSendSystemData.DefaultSnapshotPacketSize when running in hybrid mode.

It measures what the total size of the snapshot that is consumed by hybrid prefab transform synchronization. It is a metric that can be used against non-hybrid instances to determine the bandwidth savings.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@EmandM
Removed this test.

Comment thread com.unity.netcode.gameobjects/Tests/Editor/HybridNetcodeDefaultsTests.cs Outdated
@NoelStephensUnity
NoelStephensUnity marked this pull request as draft August 31, 2026 13:31
auto-merge was automatically disabled August 31, 2026 13:31

Pull request was converted to draft

Refactoring when the NetcodeConfig default settings are written.
Assuring that the NetcodeConfig tick rate is always the currently set tick rate when starting a session.
@NoelStephensUnity
NoelStephensUnity marked this pull request as ready for review August 31, 2026 17:00

@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 one-shot defaults flow and runtime tick alignment are coherent for hybrid sessions, but the editor initialization also changes the shared Netcode for Entities configuration in projects that never use hybrid prefabs.

Reviewed commit f12c046

🤖 Helpful? 👍/👎

Comment thread com.unity.netcode.gameobjects/Editor/Configuration/HybridNetcodeConfigApplier.cs Outdated
Updating to use a more NGO like testing pattern.
Some comment clean up is included.
@NoelStephensUnity

NoelStephensUnity commented Aug 31, 2026 •

Copy link
Copy Markdown
Member Author

Big concern here with using AssetDatabase.FindAssets.

  1. It's very slow
  2. The pattern will change and/or go away as the editor moves towards importing on demand.

Relevant assets should register themselves in OnEnable, that way behaviour will be automatically triggered when relevant rather than doing an expensive search over many irrelevant things.

None of this script exists anymore.

resolving concern over the .EndVertical();
removing white space.
Netcode for GameObjects no longer writes anything into the NetcodeConfig asset. NetworkManager writes the
in-memory global config immediately before the world is created from it, and Netcode for Entities seeds its
world singletons from that.

Two values are driven, both measured rather than assumed:

- The tick rates. NGO's own send queues are flushed by a system in N4E's SimulationSystemGroup, so a
  simulation rate below NetworkConfig.TickRate starves NGO's outbound traffic. N4E defaults to 60 and NGO
  to 30.
- The snapshot packet size, behind the new NetworkConfig.AutoConfigureSnapshotSize. N4E's default of one
  MTU round-robins above roughly 230 GhostObjects: at 512 instances it holds a 13.51Hz effective update
  rate against a 30Hz tick, where 4096 holds 30.00Hz with no saturated snapshots. Below that count the cap
  is never reached, so it costs nothing.

UnifiedBootstrap no longer delegates to base.Initialize. Entities selects the most derived ICustomBootstrap,
so this type is the only one it instantiates under UNIFIED_NETCODE and N4E's own Initialize is never reached
on its own. Calling it only gave N4E a chance to create worlds this bootstrap would then reject, which is why
EnableClientServerBootstrap had to be configured at all. It no longer does.

Removed with it: the editor applier, the Project Settings section, the applied-defaults version marker, and
the interpolation, despawn reservation and transport queue values. Those were tuned against a 2000 instance
stress test and are either inside N4E's own recommended ranges or inert below the snapshot cap.

The FailValidation and ClientDoesNotRequest hybrid test cases are removed pending a separate fix: the server
schedules its disconnect reason into N4E's outgoing RPC buffer and then tears the connection down in the same
call, before RpcSystem transmits it.
The polled disconnect reason check belongs with the fix for the defect it found, not with the
NetcodeConfig changes. Only the removal of the FailValidation hybrid fixture stays here.
Drops a stray blank line that was the only remaining change in NetcodeForGameObjectsProjectSettings, so
that file leaves the diff. Trims the comments that carried mechanism or measurements the PR description
already covers, keeping the reason each value or omission exists.
return true;
}

// NetworkManager owns world creation here, so base.Initialize is deliberately not called: it would

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Context for the removed base.Initialize call, since the reason is not visible from the diff.

Entities selects the most derived ICustomBootstrap (DefaultWorldInitialization.CreateBootStrap), so UnifiedBootstrap is the only one it instantiates whenever UNIFIED_NETCODE is set, and Netcode for Entities' own ClientServerBootstrap.Initialize is never reached on its own. That method's entire body is:

if (!DetermineIfBootstrappingEnabled())
    return false;
CreateDefaultClientServerWorlds();
return true;

DetermineIfBootstrappingEnabled() is the only reader of EnableClientServerBootstrap. So calling the base was Netcode for GameObjects asking Netcode for Entities to create worlds and then rejecting them when it did — which is the only reason that setting had to be configured at all. Not calling it removes the requirement rather than working around it.

Verified with a control: with EnableAutomaticBootstrap set (the Netcode for Entities default), the UnifiedHost case passes without the base call and fails with it.

The body is identical in 7.0.0 and 7.1.0.

@NoelStephensUnity

Copy link
Copy Markdown
Member Author

@u-pr please review again

@u-pr

u-pr Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Summary

This updated revision is a significant improvement over earlier iterations. By eliminating the editor-time asset searching (AssetDatabase.FindAssets), project settings version tracking, and asset disk modifications in favor of configuring NetcodeConfig.Global purely in memory right before world creation at session start, the implementation is much cleaner, faster, and completely sidesteps earlier asset-import and domain-reload concerns.


Highlights

  1. Session Start Configuration (NetworkManager.cs & HybridNetcodeDefaults.cs):

    • Mutating NetcodeConfig.Global in memory right before InitializeNetcodeWorld() in StartServer(), StartClient(), and StartHost() ensures that Netcode for Entities seeds its world singletons with the synchronized tick rate and tuned snapshot packet size without touching on-disk asset files.
    • Idempotency in ApplyTickRate and ApplySnapshotPacketSize ensures restarts or re-initializations within the same domain reload do not cause unnecessary updates or repeated log spam.
  2. Decoupling Bootstrap World Creation (UnifiedBootstrap.cs):

    • Omitting base.Initialize(defaultWorldName) prevents Netcode for Entities from attempting default world creation that NGO then has to reject.
    • This cleanly removes the constraint requiring developers to manually set EnableClientServerBootstrap = DisableAutomaticBootstrap.
  3. Validation & Logging:

    • String interpolation in UnifiedIsConfiguredCorrectly is fixed, correctly surfacing descriptive error reasons from HybridNetcodeDefaults.IsMissingRequired.
  4. Testing:

    • HybridNetcodeDefaultsTests provides targeted coverage for tick rate locking, snapshot packet size setting, required single-world mode enforcement, and verification that automatic bootstrap is no longer required to be disabled.
    • Marking UnifiedSnapshotPacketSizeMeasurement with [Explicit] ensures the heavy measurement sweep remains accessible for future benchmarking without inflating CI runtimes.

Suggestions

  • CHANGELOG Entry for Bootstrap Setting:
    Consider adding a bullet point under Changed or Fixed in CHANGELOG.md noting that EnableClientServerBootstrap no longer needs to be set to DisableAutomaticBootstrap in hybrid mode, as users upgrading from earlier builds may still expect this requirement.

🤖 Helpful? 👍/👎

@NoelStephensUnity
NoelStephensUnity enabled auto-merge (squash) October 7, 2026 02:46
NoelStephensUnity and others added 13 commits October 7, 2026 08:59
…netcodeconfig-defaults

# Conflicts:
#	com.unity.netcode.gameobjects/CHANGELOG.md
#	com.unity.netcode.gameobjects/Tests/Runtime/Unified.meta
…ts' into feat/hybrid-netcodeconfig-defaults

# Conflicts:
#	com.unity.netcode.gameobjects/CHANGELOG.md
…netcodeconfig-defaults

# Conflicts:
#	com.unity.netcode.gameobjects/CHANGELOG.md
Moving the AutoConfigureSnapshotSizeProperty into its own section within the NetworkManager inspector view for easier discoverability.
Updated comments for clarity and accuracy regarding hybrid mode settings and tick rate application in HybridNetcodeDefaults.
Updated summary and remarks in UnifiedApplyNetcodeConfig method to clarify the application of NetcodeConfig settings during runtime.

@EmandM EmandM 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.

I'd love to make that default snapshot size configurable rather than a constant, but this is a great first step!

Removing whitespace.
Adjusting tooltip.
@NoelStephensUnity
NoelStephensUnity merged commit ca1608f into develop-3.x.x Oct 8, 2026
26 checks passed
@NoelStephensUnity
NoelStephensUnity deleted the feat/hybrid-netcodeconfig-defaults branch October 8, 2026 21:31
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.

5 participants