-
Notifications
You must be signed in to change notification settings - Fork 463
feat: hybrid NetcodeConfig defaults #4144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop-3.x.x
Are you sure you want to change the base?
Changes from all commits
69a99a9
49e605e
3474768
19556af
2c82988
0239d3b
392159f
9c7fb1a
f12c046
edb3404
a2894d2
1571094
c4fd5b2
54375dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| #if UNIFIED_NETCODE | ||
| using Unity.NetCode; | ||
| using UnityEditor; | ||
| using UnityEngine; | ||
|
|
||
| namespace Unity.Netcode.GameObjects.Editor.Configuration | ||
| { | ||
| /// <summary> | ||
| /// Writes the <see cref="NetCodeConfig"/> values NGO recommends for hybrid mode, once, the first time a | ||
| /// <see cref="NetCodeConfig"/> is available. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// This does not create <see cref="NetCodeConfig"/>. This finds the one N4E created and modifies it. | ||
| /// Nothing tracks the project after that write. The defaults are inert in a project with no hybrid prefabs, and | ||
| /// <see cref="NetworkManager"/> re-aligns the tick rate at start-up in a project that has them, so there is no | ||
| /// reason to scan for ghost prefabs from the editor. | ||
| /// </remarks> | ||
| internal static class HybridNetcodeConfigApplier | ||
| { | ||
| /// <summary> | ||
| /// Whether the user has to opt into the experimental unified netcode API before NGO writes anything. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// TODO-RELEASE: Set this to true before the 6000.7.0 release manifest submission if Netcode for Entities | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a list of those somewhere? Otherwise I will remember to do a check around tomorrow/friday
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it going to be shipped as experimental in 6000.7? |
||
| /// ships the unified API as experimental and its scripting defines. | ||
| /// Note: This is deliberately not a const: IDE0035 (remove unreachable code) is an error in this repository, so a | ||
| /// const would fail the standards job as soon as it was set to false. | ||
|
Comment on lines
+24
to
+27
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to be tracked somewhere |
||
| /// </remarks> | ||
| internal static readonly bool RequiresExperimentalOptIn = false; | ||
|
|
||
| private static NetCodeConfig s_ScannedConfig; | ||
| private static bool s_ConfigScanned; | ||
|
|
||
| [InitializeOnLoadMethod] | ||
| private static void OnApplicationStart() | ||
| { | ||
| // Cross-assembly ordering between the two is not a documented contract. | ||
| // Defer rather than racing it. | ||
| EditorApplication.delayCall += OnDelayCall; | ||
| } | ||
|
|
||
| private static void OnDelayCall() | ||
| { | ||
| EditorApplication.delayCall -= OnDelayCall; | ||
| ApplyDefaults(false); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Writes the NGO hybrid mode defaults into the project's <see cref="NetCodeConfig"/>. | ||
| /// </summary> | ||
| /// <param name="force"> | ||
| /// Driven by the button in Project Settings: | ||
| /// - When true: re-applies the full tuned set even though this project has already had it applied once. | ||
| /// - When false: writes only if this project has never had them written. From that point forward, the user's | ||
| /// edits are not overwritten. | ||
| /// </param> | ||
| internal static void ApplyDefaults(bool force) | ||
| { | ||
| if (EditorApplication.isPlayingOrWillChangePlaymode) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| var settings = NetcodeForGameObjectsProjectSettings.instance; | ||
| if (RequiresExperimentalOptIn && !settings.EnableUnifiedNetcodeApi) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (!force && settings.HybridDefaultsVersion >= HybridNetcodeDefaults.Version) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // A project with no config yet leaves the marker unrecorded so that the next domain reload tries again. | ||
| // N4E creates one on any domain reload that finds none. | ||
| var config = ResolveGlobalConfig(); | ||
| if (config == null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (HybridNetcodeDefaults.ApplyRecommended(config, HybridNetcodeDefaults.DefaultTickRate)) | ||
|
EmandM marked this conversation as resolved.
|
||
| { | ||
| EditorUtility.SetDirty(config); | ||
| AssetDatabase.SaveAssetIfDirty(config); | ||
| Debug.Log($"[Netcode] Applied the NGO hybrid mode defaults to '{config.name}'. These are tuned for NGO and can be changed freely; they will not be re-applied automatically. Use Project Settings > Multiplayer > Netcode for GameObjects to restore them.", config); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should use the new logger. Maybe this log should be at |
||
| } | ||
|
|
||
| // Recorded even when the config already matched and nothing was written. Leaving it unrecorded would make | ||
| // the next domain reload a first application again, which would revert the user's next edit. | ||
| settings.HybridDefaultsVersion = HybridNetcodeDefaults.Version; | ||
| settings.SaveSettings(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Resolves the config N4E considers global, falling back to a project scan when N4E has not assigned one yet. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// The scan is done at most once per domain reload, including when it finds nothing, because this is also | ||
| /// reached from OnGUI and <see cref="AssetDatabase.FindAssets"/> walks the entire project. A config created | ||
| /// after the scan is picked up on the next domain reload. | ||
| /// </remarks> | ||
| /// <returns>The config to adjust or null if no config exists.</returns> | ||
| internal static NetCodeConfig ResolveGlobalConfig() | ||
| { | ||
| if (NetCodeConfig.Global != null) | ||
| { | ||
| return NetCodeConfig.Global; | ||
| } | ||
|
|
||
| if (!s_ConfigScanned) | ||
| { | ||
| s_ConfigScanned = true; | ||
| var guids = AssetDatabase.FindAssets($"t:{nameof(NetCodeConfig)}"); | ||
| s_ScannedConfig = guids.Length == 1 ? AssetDatabase.LoadAssetAtPath<NetCodeConfig>(AssetDatabase.GUIDToAssetPath(guids[0])) : null; | ||
| } | ||
|
Comment on lines
+112
to
+117
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't need this logic, N4E has their own logic to find a NetcodeConfig file and assign it as the global file. That logic is run on NGO should trust the contract that the Global field is always set. If there are situations where the Global field isn't set we file it as a bug and fix it in N4E. |
||
|
|
||
| return s_ScannedConfig; | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,29 @@ private void OnEnable() | |
| [SerializeField] | ||
| public bool GenerateDefaultNetworkPrefabs = true; | ||
|
|
||
| #if UNIFIED_NETCODE | ||
| /// <summary> | ||
| /// Whether the user has opted into the experimental unified netcode API. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Only consulted while <see cref="HybridNetcodeConfigApplier.RequiresExperimentalOptIn"/> holds. Turning it | ||
| /// off again hides the hybrid section and leaves the NetCodeConfig exactly as it is; the marker below is what | ||
| /// keeps turning it back on from overwriting anything. | ||
| /// </remarks> | ||
| [SerializeField] | ||
| public bool EnableUnifiedNetcodeApi; | ||
|
|
||
| /// <summary> | ||
| /// The hybrid mode default values already applied to this project's NetCodeConfig. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment implies that the field caches values, but the field is an int, not a struct.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The field is written to when loading NGO v3.x.x for the 1st time. It signifies the default settings have been applied.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it an int rather than a bool? |
||
| /// </summary> | ||
| /// <remarks> | ||
| /// Zero means they have never been applied. Persisting this value is what keeps the tuned values a one-shot. | ||
| /// For users who deliberately change them, they are not overwritten on the next domain reload. | ||
| /// </remarks> | ||
| [SerializeField] | ||
| public int HybridDefaultsVersion; | ||
|
EmandM marked this conversation as resolved.
|
||
| #endif | ||
|
|
||
| internal void SaveSettings() | ||
| { | ||
| Save(true); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.