feat: hybrid NetcodeConfig defaults - #4144
Conversation
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.
There was a problem hiding this comment.
💡 Harness Review
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? 👍/👎
| changed |= HybridNetcodeDefaults.ApplyTickRate(config, ResolveTickRate(config)); | ||
| } | ||
|
|
||
| if (!changed) |
There was a problem hiding this comment.
When this is the first pass but the config already happens to equal the recommended values, changed is false and this early return leaves HybridDefaultsVersion at zero. For example, a user can configure these values manually before registering their first ghost prefab, then later change one setting; the next domain reload treats it as a first application and overwrites that edit. Persist the version marker on a successful first/recommended pass even when there was no config mutation (while only dirtying/saving the config when it actually changed).
🤖 Helpful? 👍/👎
There was a problem hiding this comment.
@u-pr you can disregard this mechanism because a user applying their own settings before having added a hybrid prefab very likely doesn't realize there are recommended settings in order to yield the best results. Users editing the NetcodeConfig before they have created their 1st hybrid prefab for the 1st time most likely are not aware of this default setting.
There was a problem hiding this comment.
Understood, that makes sense. If the intended design is to prioritize ensuring the NGO hybrid defaults are applied once hybrid mode is first actively used regardless of prior pre-hybrid configuration, leaving the current flow as-is makes total sense.
🤖 Helpful? 👍/👎
There was a problem hiding this comment.
@u-pr can you review all of the areas you pointed out potential issues?
They should all be resolved now.
There was a problem hiding this comment.
Reviewed the updated changes, and everything looks solid and properly resolved:
- Version Marker Persistence (
HybridNetcodeConfigApplier.cs): PersistingHybridDefaultsVersionand saving settings inside theapplyRecommended || isFirstApplyblock ensures domain reloads won't treat an already-matching config as a first apply or overwrite subsequent user modifications. - String Interpolation & Bootstrap Validation (
NetworkManager.cs): The un-interpolated string format issue inUnifiedIsConfiguredCorrectlyis resolved, and validation now properly leveragesHybridNetcodeDefaults.IsMissingRequiredto check both single-world hosting and disabled automatic bootstrapping. - Tick Rate & Scene Loading (
HybridNetcodeConfigApplier.cs): Subscribing toEditorSceneManager.sceneOpenedhandles unopened scenes gracefully to pick up NGONetworkManagertick rates post-initialization. - Test Coverage (
HybridNetcodeDefaultsTests.cs): The added unit tests thoroughly cover the one-shot application behavior, required settings enforcement, tick rate locking, and hybrid project detection.
🤖 Helpful? 👍/👎
There was a problem hiding this comment.
@u-pr Since all of the issues you found are resolved, can you update the status of your review?
(still says "needs changes")
There was a problem hiding this comment.
I cannot directly update or clear the GitHub review status (e.g., changing "Changes requested" to "Approved").
- Why: I do not have the permissions or tooling to submit formal PR review state changes or dismiss existing reviews.
- Alternatives: A repository maintainer or reviewer can manually dismiss the previous review or submit an approving review now that the issues have been addressed.
🤖 Helpful? 👍/👎
| } | ||
|
|
||
| diverged |= found != 0 && found != tickRate; | ||
| found = tickRate; |
There was a problem hiding this comment.
This selects the tick rate from every loaded NetworkManager, rather than from the manager(s) that registered a ghost prefab. With a hybrid manager at 30 Hz and an unrelated conventional manager at 60 Hz that is enumerated later, the global config is set to 60 Hz; starting the hybrid manager then hits the new mismatch warning and its ghost timeline is not aligned with its NGO tick rate. Restrict this selection to managers that actually reference a ghost prefab (and handle conflicting hybrid-manager rates explicitly) instead of taking the last manager encountered.
🤖 Helpful? 👍/👎
| /// </summary> | ||
| internal static bool IsHybridProject() | ||
| { | ||
| foreach (var networkManager in Resources.FindObjectsOfTypeAll<NetworkManager>()) |
There was a problem hiding this comment.
FindObjectsOfTypeAll only sees loaded objects; it does not enumerate NetworkManagers in unopened scene or prefab assets. Thus, if a project has its manager-with-ghost-registration in a closed scene at domain reload, this returns false and no defaults are applied. Opening that scene later does not invoke this initialization hook, and the postprocessor only reacts to imports of ghost GameObjects, so entering Play Mode can still fail the required hybrid configuration validation. Discover persisted manager assets (or trigger a rescan when their registration changes/when scenes open) rather than relying solely on currently loaded managers.
🤖 Helpful? 👍/👎
Fixing some things u-pr caught and adding a test to validate the update.
|
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? |
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.
This would be a change to the NetcodeConfig property drawer in N4E. |
Purpose of this PR
This PR introduces an automated NetcodeConfig default settings feature where NGO will, at a minimum, configure NGO user's NetcodeConfig settings to the recommended settings.
The UI
When there are no hybrid prefabs within a network prefab list used by a NetworkManager, the Multiplayer Netcode for GameObjects UI will display that there are no hybrid prefabs (network prefab with GhostObject) and the default settings do not apply until there is at least one.

Once a hybrid prefab has been detected it will apply the default settings once, log a notification (to the console currently, but we can make this a one time dialog box), and then the UI adjusts to provide users with the ability to re-apply the default settings in the event they tinker with things and want to get back to the recommended default settings:

Jira ticket
MTT-15571
Changelog
Documentation
Testing & QA (How your changes can be verified during release Playtest)
Functional Testing
Manual testing :
Manual testing doneYou can also look at the NetcodeConfig.asset file and spot check (if the snapshot size has been increased to 15000 then the NGO settings were automatically applied).
Automated tests:
Covered by existing automated testsCovered by new automated testsDoes 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
None
Backports
None