Skip to content

fix: reset static fields for Fast Enter Play Mode#3956

Open
noellie-velez wants to merge 12 commits into
develop-2.0.0from
chore/fast-enter-playmode
Open

fix: reset static fields for Fast Enter Play Mode#3956
noellie-velez wants to merge 12 commits into
develop-2.0.0from
chore/fast-enter-playmode

Conversation

@noellie-velez
Copy link
Copy Markdown
Collaborator

@noellie-velez noellie-velez commented Apr 24, 2026

Purpose of this PR

Ensure com.unity.netcode.gameobjects package supports Fast Enter Play Mode

Jira ticket

MTT-14665

Changelog

  • Fixed: Netcode for Game Objects now supports Fast Enter Play Mode

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.

Backports

N/A

}

internal static bool LogSerializationOrder = false;
internal static bool LogSerializationOrder;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is only used to perform some logging but it is never set to true and it is internal, should we keep it? Is this something that should go in the new logging system instead?

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.

If you can figure out a way to handle it via the new logging system that would be great.
Otherwise, you could get rid of the static and just wrap that code in a define (i.e. LOG_SERIALIZATION_ORDER or the like).

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.

Let's just move this setting into NetworkLog.Config We can change the log logic later

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

When is m_ParentedChildren updated? I had a warning about this in my IDE and didn't find the info myself 🫠

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

To delete

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.

Yeah... that was evidently a legacy merge issue that kept the old way of handling this.
As an example:

                    // Synchronize any nested NetworkTransforms with the parent's  <<---- The new "correct" way
                    foreach (var childNetworkTransform in NetworkObject.NetworkTransforms)
                    {
                        // Don't update the same instance or any nested NetworkTransform with a different authority mode
                        if (childNetworkTransform == this || childNetworkTransform.AuthorityMode != AuthorityMode)
                        {
                            continue;
                        }
                        if (childNetworkTransform.CanCommitToTransform)
                        {
                            childNetworkTransform.OnNetworkTick(true);
                        }
                    }

                    // Synchronize any parented children with the parent's motion <<---- The legacy "old way" (remove)
                    foreach (var child in m_ParentedChildren)
                    {
                        // Synchronize any nested NetworkTransforms of the child with the parent's
                        foreach (var childNetworkTransform in child.NetworkTransforms)
                        {
                            if (childNetworkTransform.CanCommitToTransform)
                            {
                                childNetworkTransform.OnNetworkTick(true);
                            }
                        }
                    }

Everywhere you see m_ParentedChildren (merge artifact) there is going to be a duplicate for loop using NetworkObject.NetworkTransforms (correct).

@noellie-velez noellie-velez marked this pull request as ready for review April 24, 2026 15:06
@noellie-velez noellie-velez requested review from a team as code owners April 24, 2026 15:06
Copy link
Copy Markdown
Contributor

@simon-lemay-unity simon-lemay-unity left a comment

Choose a reason for hiding this comment

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

Changes to UnityTransport look good to me.


#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStaticsOnLoad()
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Move this at the top

@@ -44,6 +44,10 @@ public static class QuaternionCompressor

// Used to store the absolute value of the 4 quaternion elements
private static Quaternion s_QuatAbsValues = Quaternion.identity;
Copy link
Copy Markdown
Collaborator Author

@noellie-velez noellie-velez May 11, 2026

Choose a reason for hiding this comment

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

Replace quaternion by 4 ints

Comment on lines +3 to +5
#if UNITY_EDITOR
using UnityEngine;
#endif
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Remove this, add UnityEngine.Runtime...

internal delegate void ResetNetworkManagerDelegate(NetworkManager manager);

internal static ResetNetworkManagerDelegate OnNetworkManagerReset;
//We already are in an #if UNITY_ENGINE def
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Remove this comment

DisableNotOptimizedSerializedType = false;
}

private void Reset()
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Add xml doc with:
Used by cref... NetworkManagerHeper this is called by the reset button of the Unity Editor

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Initialize()
{
#if UNITY_EDITOR
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

add comment //Reset Statics

using System.Collections.Generic;
using Unity.Collections;
#if UNITY_EDITOR
using UnityEngine;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Move it down to use UnityEngine.Runtime...

@@ -1,3 +1,6 @@
#if UNITY_6000_6_OR_NEWER
using Unity.Scripting.LifecycleManagement;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Add it down Unity.Scripting.LifecycleManagement.Auto...

s_SceneEventTypeNames[(uint)type] = type.ToString();
}
s_FrameDispatch = new ProfilerMarker($"{nameof(NetworkMetrics)}.DispatchFrame");
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Remove this reset, not needed here

@@ -13,6 +16,18 @@ internal class NetworkMetrics : INetworkMetrics
private const ulong k_MaxMetricsPerFrame = 1000L;
private static Dictionary<uint, string> s_SceneEventTypeNames;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this can be made readonly

using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
#if UNITY_6000_6_OR_NEWER
using Unity.Scripting.LifecycleManagement;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Put this with AutoStaticsCleanup

@@ -1,4 +1,7 @@
using System;
#if UNITY_6000_6_OR_NEWER
using Unity.Scripting.LifecycleManagement;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same here

public static class NetworkVariableSerializationTypedInitializers
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Do not change this one

internal static bool IgnoreInitializeWarning;
#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStaticsOnLoad() => IgnoreInitializeWarning = false;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The test lifecycle cleans itself up, we can remove this one

Comment on lines +1582 to +1584
#if UNITY_EDITOR
internal static void ResetInstances() => s_Instances = new Dictionary<NetworkManager, List<SceneUnloadEventHandler>>();
#endif
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.

Because we're not using the attribute, a conditional define works here

Suggested change
#if UNITY_EDITOR
internal static void ResetInstances() => s_Instances = new Dictionary<NetworkManager, List<SceneUnloadEventHandler>>();
#endif
[Conditional("UNITY_EDITOR")]
internal static void ResetInstances() => s_Instances = new Dictionary<NetworkManager, List<SceneUnloadEventHandler>>();

@@ -636,7 +641,7 @@ internal void WriteSceneSynchronizationData(FastBufferWriter writer)
}
if (EnableSerializationLogs)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Move this one too to the NetworkLog LogConfiguration struct

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Add a code comment showing where it is used

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.

4 participants