From 60650427ce18c181e142430665694d7693bfe5d3 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Mon, 20 Oct 2025 09:24:35 -0500 Subject: [PATCH 1/9] fix When MULTIPLAYER_TOOLS_1_0_0_PRE_7 is defined there is code within UnityTransport that did not take the ClientIdToTransportId into consideration. This resolves that issue. --- .../Runtime/Transports/UTP/UnityTransport.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index a0ccfc6ed3..8ce1b8ab83 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1107,8 +1107,11 @@ private void ExtractNetworkMetrics() { continue; } - var transportClientId = m_NetworkManager.ConnectionManager.ClientIdToTransportId(ngoConnectionId); - ExtractNetworkMetricsForClient(transportClientId); + var transportClientIdReturn = m_NetworkManager.ConnectionManager.ClientIdToTransportId(ngoConnectionId); + if (transportClientIdReturn.Item2) + { + ExtractNetworkMetricsForClient(transportClientIdReturn.Item1); + } } } else From a4451c8b298b11b1b046a083525c6dc02b73143f Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Mon, 20 Oct 2025 12:22:21 -0500 Subject: [PATCH 2/9] update Updating packages. Adding multiplayer tools to assure nothing that uses an asmdef defined define breaks if changes are made. --- testproject/Packages/manifest.json | 23 ++-- testproject/Packages/packages-lock.json | 145 ++++++++++++++++++------ 2 files changed, 123 insertions(+), 45 deletions(-) diff --git a/testproject/Packages/manifest.json b/testproject/Packages/manifest.json index 1895c93dcc..8817bf5eaf 100644 --- a/testproject/Packages/manifest.json +++ b/testproject/Packages/manifest.json @@ -1,19 +1,20 @@ { "disableProjectUpdate": false, "dependencies": { - "com.unity.addressables": "2.2.2", - "com.unity.ai.navigation": "2.0.5", - "com.unity.collab-proxy": "2.6.0", - "com.unity.ide.rider": "3.0.31", - "com.unity.ide.visualstudio": "2.0.22", - "com.unity.mathematics": "1.3.2", + "com.unity.addressables": "2.7.4", + "com.unity.ai.navigation": "2.0.9", + "com.unity.collab-proxy": "2.9.3", + "com.unity.ide.rider": "3.0.38", + "com.unity.ide.visualstudio": "2.0.25", + "com.unity.mathematics": "1.3.3", + "com.unity.multiplayer.tools": "2.2.6", "com.unity.netcode.gameobjects": "file:../../com.unity.netcode.gameobjects", "com.unity.package-validation-suite": "0.49.0-preview", - "com.unity.services.authentication": "3.4.0", - "com.unity.services.core": "1.14.0", - "com.unity.test-framework": "1.4.6", - "com.unity.test-framework.performance": "3.0.3", - "com.unity.timeline": "1.8.7", + "com.unity.services.authentication": "3.5.2", + "com.unity.services.multiplayer": "1.1.8", + "com.unity.test-framework": "1.6.0", + "com.unity.test-framework.performance": "3.1.0", + "com.unity.timeline": "1.8.9", "com.unity.ugui": "2.0.0", "com.unity.modules.accessibility": "1.0.0", "com.unity.modules.ai": "1.0.0", diff --git a/testproject/Packages/packages-lock.json b/testproject/Packages/packages-lock.json index dd5f6204a3..c87b451b63 100644 --- a/testproject/Packages/packages-lock.json +++ b/testproject/Packages/packages-lock.json @@ -1,22 +1,23 @@ { "dependencies": { "com.unity.addressables": { - "version": "2.2.2", + "version": "2.7.4", "depth": 0, "source": "registry", "dependencies": { "com.unity.profiling.core": "1.0.2", + "com.unity.test-framework": "1.4.5", "com.unity.modules.assetbundle": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", "com.unity.modules.imageconversion": "1.0.0", "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.scriptablebuildpipeline": "2.1.4", + "com.unity.scriptablebuildpipeline": "2.4.3", "com.unity.modules.unitywebrequestassetbundle": "1.0.0" }, "url": "https://packages.unity.com" }, "com.unity.ai.navigation": { - "version": "2.0.5", + "version": "2.0.9", "depth": 0, "source": "registry", "dependencies": { @@ -25,8 +26,8 @@ "url": "https://packages.unity.com" }, "com.unity.burst": { - "version": "1.8.19", - "depth": 2, + "version": "1.8.24", + "depth": 1, "source": "registry", "dependencies": { "com.unity.mathematics": "1.2.1", @@ -35,20 +36,21 @@ "url": "https://packages.unity.com" }, "com.unity.collab-proxy": { - "version": "2.6.0", + "version": "2.9.3", "depth": 0, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, "com.unity.collections": { - "version": "2.5.1", - "depth": 2, + "version": "2.5.7", + "depth": 1, "source": "registry", "dependencies": { - "com.unity.burst": "1.8.17", - "com.unity.test-framework": "1.4.5", - "com.unity.nuget.mono-cecil": "1.11.4", + "com.unity.burst": "1.8.19", + "com.unity.mathematics": "1.3.2", + "com.unity.test-framework": "1.4.6", + "com.unity.nuget.mono-cecil": "1.11.5", "com.unity.test-framework.performance": "3.0.3" }, "url": "https://packages.unity.com" @@ -56,12 +58,11 @@ "com.unity.ext.nunit": { "version": "2.0.5", "depth": 1, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" + "source": "builtin", + "dependencies": {} }, "com.unity.ide.rider": { - "version": "3.0.31", + "version": "3.0.38", "depth": 0, "source": "registry", "dependencies": { @@ -70,21 +71,36 @@ "url": "https://packages.unity.com" }, "com.unity.ide.visualstudio": { - "version": "2.0.22", + "version": "2.0.25", "depth": 0, "source": "registry", "dependencies": { - "com.unity.test-framework": "1.1.9" + "com.unity.test-framework": "1.1.31" }, "url": "https://packages.unity.com" }, "com.unity.mathematics": { - "version": "1.3.2", + "version": "1.3.3", "depth": 0, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.multiplayer.tools": { + "version": "2.2.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.8.18", + "com.unity.collections": "2.5.1", + "com.unity.mathematics": "1.3.2", + "com.unity.profiling.core": "1.0.2", + "com.unity.nuget.mono-cecil": "1.11.4", + "com.unity.modules.uielements": "1.0.0", + "com.unity.nuget.newtonsoft-json": "3.2.1" + }, + "url": "https://packages.unity.com" + }, "com.unity.netcode.gameobjects": { "version": "file:../../com.unity.netcode.gameobjects", "depth": 0, @@ -95,7 +111,7 @@ } }, "com.unity.nuget.mono-cecil": { - "version": "1.11.4", + "version": "1.11.5", "depth": 1, "source": "registry", "dependencies": {}, @@ -125,27 +141,30 @@ "url": "https://packages.unity.com" }, "com.unity.scriptablebuildpipeline": { - "version": "2.1.4", + "version": "2.4.3", "depth": 1, "source": "registry", - "dependencies": {}, + "dependencies": { + "com.unity.test-framework": "1.4.5", + "com.unity.modules.assetbundle": "1.0.0" + }, "url": "https://packages.unity.com" }, "com.unity.services.authentication": { - "version": "3.4.0", + "version": "3.5.2", "depth": 0, "source": "registry", "dependencies": { "com.unity.ugui": "1.0.0", - "com.unity.services.core": "1.14.0", + "com.unity.services.core": "1.15.1", "com.unity.nuget.newtonsoft-json": "3.2.1", "com.unity.modules.unitywebrequest": "1.0.0" }, "url": "https://packages.unity.com" }, "com.unity.services.core": { - "version": "1.14.0", - "depth": 0, + "version": "1.15.1", + "depth": 1, "source": "registry", "dependencies": { "com.unity.modules.androidjni": "1.0.0", @@ -154,29 +173,86 @@ }, "url": "https://packages.unity.com" }, - "com.unity.test-framework": { - "version": "1.4.6", + "com.unity.services.deployment": { + "version": "1.4.1", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.services.core": "1.12.0", + "com.unity.services.deployment.api": "1.1.2" + }, + "url": "https://packages.unity.com" + }, + "com.unity.services.deployment.api": { + "version": "1.1.2", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.services.multiplayer": { + "version": "1.1.8", "depth": 0, "source": "registry", + "dependencies": { + "com.unity.transport": "2.5.0", + "com.unity.collections": "2.2.1", + "com.unity.services.qos": "1.3.0", + "com.unity.services.core": "1.13.0", + "com.unity.services.wire": "1.4.0", + "com.unity.services.deployment": "1.3.0", + "com.unity.nuget.newtonsoft-json": "3.2.1", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.services.authentication": "3.3.3" + }, + "url": "https://packages.unity.com" + }, + "com.unity.services.qos": { + "version": "1.3.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.collections": "1.2.4", + "com.unity.services.core": "1.12.4", + "com.unity.nuget.newtonsoft-json": "3.0.2", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.services.authentication": "2.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.services.wire": { + "version": "1.4.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.services.core": "1.12.5", + "com.unity.nuget.newtonsoft-json": "3.2.1", + "com.unity.services.authentication": "2.7.4" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.6.0", + "depth": 0, + "source": "builtin", "dependencies": { "com.unity.ext.nunit": "2.0.3", "com.unity.modules.imgui": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0" - }, - "url": "https://packages.unity.com" + } }, "com.unity.test-framework.performance": { - "version": "3.0.3", + "version": "3.1.0", "depth": 0, "source": "registry", "dependencies": { - "com.unity.test-framework": "1.1.31", + "com.unity.test-framework": "1.1.33", "com.unity.modules.jsonserialize": "1.0.0" }, "url": "https://packages.unity.com" }, "com.unity.timeline": { - "version": "1.8.7", + "version": "1.8.9", "depth": 0, "source": "registry", "dependencies": { @@ -188,7 +264,7 @@ "url": "https://packages.unity.com" }, "com.unity.transport": { - "version": "2.4.0", + "version": "2.5.3", "depth": 1, "source": "registry", "dependencies": { @@ -355,7 +431,8 @@ "com.unity.modules.ui": "1.0.0", "com.unity.modules.imgui": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.hierarchycore": "1.0.0" + "com.unity.modules.hierarchycore": "1.0.0", + "com.unity.modules.physics": "1.0.0" } }, "com.unity.modules.umbra": { From 237395744746d3779e0cc64d1758ee1bfa9884b0 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Mon, 20 Oct 2025 12:32:28 -0500 Subject: [PATCH 3/9] style Fixing whitespace. --- .../Runtime/Transports/UTP/UnityTransport.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 8ce1b8ab83..2eee476928 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1100,9 +1100,9 @@ private void ExtractNetworkMetrics() { if (m_NetworkManager.IsServer) { - for (int i=0; i Date: Mon, 20 Oct 2025 12:35:36 -0500 Subject: [PATCH 4/9] style More whitespace issues. --- .../Runtime/Transports/UTP/UnityTransport.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 2eee476928..86f6132e52 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -496,14 +496,11 @@ public NetworkSettings GetDefaultNetworkSettings() // Latency, jitter and packet loss will be set by the network simulator in the tools // package. We just need to initialize the settings since otherwise these features will // not be enabled at all in the driver. - settings.WithSimulatorStageParameters( - // Assuming a maximum average latency of 50 ms, and that we're somehow able to flush - // an entire reliable window every tick, then at 60 ticks per second we need to be - // able to store 60 * 0.05 * 64 = 192 packets per connection in the simulator - // pipeline stage. Double that since we handle both directions and round it up, and - // that's how we get 400 here. - maxPacketCount: 400, - randomSeed: DebugSimulatorRandomSeed ?? (uint)System.Diagnostics.Stopwatch.GetTimestamp()); + // Assuming a maximum average latency of 50 ms, and that we're somehow able to flush an entire reliable window every tick, + // then at 60 ticks per second we need to be able to store 60 * 0.05 * 64 = 192 packets per connection in the simulator + // pipeline stage. Double that since we handle both directions and round it up, and + // that's how we get 400 here. + settings.WithSimulatorStageParameters(maxPacketCount: 400, randomSeed: DebugSimulatorRandomSeed ?? (uint)System.Diagnostics.Stopwatch.GetTimestamp()); settings.WithNetworkSimulatorParameters(); #endif From 81dafd947ea17bdf541513c781594068c4aa57aa Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Tue, 21 Oct 2025 11:54:09 -0500 Subject: [PATCH 5/9] update Making adjustment for GetInstanceID being deprecated and replacing with GetEntityId. --- .../Runtime/Transports/UTP/UnityTransport.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 86f6132e52..5b71fcadbe 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -428,8 +428,11 @@ private void InitDriver() out m_UnreliableFragmentedPipeline, out m_UnreliableSequencedFragmentedPipeline, out m_ReliableSequencedPipeline); - +#if UNITY_6000_2_OR_NEWER + TransportInitialized?.Invoke(GetEntityId(), m_Driver); +#else TransportInitialized?.Invoke(GetInstanceID(), m_Driver); +#endif } private void DisposeInternals() @@ -446,7 +449,11 @@ private void DisposeInternals() m_SendQueue.Clear(); +#if UNITY_6000_2_OR_NEWER + TransportDisposed?.Invoke(GetEntityId()); +#else TransportDisposed?.Invoke(GetInstanceID()); +#endif } /// From 5a3528c7de29d2b7a60e7c0a63d6caf99db7ac64 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Tue, 21 Oct 2025 12:16:23 -0500 Subject: [PATCH 6/9] update Missed a few `GetInstanceID` uses and updating to use `GetEntityId`. --- .../Editor/NetworkManagerEditor.cs | 7 ++++++- .../Runtime/Components/RigidbodyContactEventManager.cs | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs index a72c9482e8..69e5de3ee0 100644 --- a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs +++ b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs @@ -285,7 +285,11 @@ private void DisplayNetworkManagerProperties() } } var networkPrefabs = m_NetworkManager.NetworkConfig.MigrateOldNetworkPrefabsToNetworkPrefabsList(); +#if UNITY_6000_2_OR_NEWER + string path = Path.Combine(directory, $"NetworkPrefabs-{m_NetworkManager.GetEntityId()}.asset"); +#else string path = Path.Combine(directory, $"NetworkPrefabs-{m_NetworkManager.GetInstanceID()}.asset"); +#endif Debug.Log("Saving migrated Network Prefabs List to " + path); AssetDatabase.CreateAsset(networkPrefabs, path); EditorUtility.SetDirty(m_NetworkManager); @@ -390,7 +394,8 @@ public override void OnInspectorGUI() #if !MULTIPLAYER_TOOLS DrawInstallMultiplayerToolsTip(); #endif - void SetExpanded(bool expanded) { networkManager.NetworkManagerExpanded = expanded; }; + void SetExpanded(bool expanded) { networkManager.NetworkManagerExpanded = expanded; } + ; DrawFoldOutGroup(networkManager.GetType(), DisplayNetworkManagerProperties, networkManager.NetworkManagerExpanded, SetExpanded); DisplayCallToActionButtons(); base.OnInspectorGUI(); diff --git a/com.unity.netcode.gameobjects/Runtime/Components/RigidbodyContactEventManager.cs b/com.unity.netcode.gameobjects/Runtime/Components/RigidbodyContactEventManager.cs index d5dff7e069..1421372839 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/RigidbodyContactEventManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/RigidbodyContactEventManager.cs @@ -125,7 +125,11 @@ public void RegisterHandler(IContactEventHandler contactEventHandler, bool regis { return; } +#if UNITY_6000_2_OR_NEWER + var instanceId = rigidbody.GetEntityId(); +#else var instanceId = rigidbody.GetInstanceID(); +#endif if (register) { if (!m_RigidbodyMapping.ContainsKey(instanceId)) From 3249887ed9ae8417202944b861fc7b13d4795a65 Mon Sep 17 00:00:00 2001 From: Emma Date: Tue, 21 Oct 2025 17:15:55 -0400 Subject: [PATCH 7/9] In DA if an object has no observers, don't send a ParentSync message --- .../Runtime/Core/NetworkObject.cs | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs index e3cd4b0dd5..1cd5214e93 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs @@ -1171,7 +1171,14 @@ private bool InternalHasAuthority() /// /// Gets if the object is owned by the local player or if the object is the local player object /// - public bool IsOwner => NetworkManager != null && OwnerClientId == NetworkManager.LocalClientId; + public bool IsOwner + { + get + { + Debug.Log($"[Client-{NetworkManager.LocalClientId}][Object-{NetworkObjectId}] Owned by {OwnerClientId}"); + return NetworkManager != null && OwnerClientId == NetworkManager.LocalClientId; + } + } /// /// Gets Whether or not the object is owned by anyone @@ -2222,6 +2229,7 @@ public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true) // If we are shutting down and don't have authority then allow it. if (!isAuthority && !NetworkManager.ShutdownInProgress) { + Debug.LogError("We don't have authority here"); return false; } @@ -2285,6 +2293,7 @@ private void OnTransformParentChanged() // With distributed authority, we need to track "valid authoritative" parenting changes. // So, either the authority or AuthorityAppliedParenting is considered a "valid parenting change". isAuthority = HasAuthority || AuthorityAppliedParenting || (AllowOwnerToParent && IsOwner); + Debug.Log($"[Client-{NetworkManager.LocalClientId}][Object-{NetworkObjectId}] OnTransformParentChanged. HasAuthority={HasAuthority}, AuthorityAppliedParenting={AuthorityAppliedParenting}, AllowOwnerToParent && IsOwner={AllowOwnerToParent && IsOwner}"); var distributedAuthority = NetworkManager.DistributedAuthorityMode; // If we do not have authority and we are spawned @@ -2355,6 +2364,8 @@ private void OnTransformParentChanged() var authorityApplied = AuthorityAppliedParenting; ApplyNetworkParenting(removeParent); + + var message = new ParentSyncMessage { NetworkObjectId = NetworkObjectId, @@ -2376,47 +2387,29 @@ private void OnTransformParentChanged() m_CachedWorldPositionStays = true; } - // If we are connected to a CMB service or we are running a mock CMB service then send to the "server" identifier - if (distributedAuthority || (!distributedAuthority && AllowOwnerToParent && IsOwner && !NetworkManager.IsServer)) + // If we're not the server, we should tell the server about this parent change + if (!NetworkManager.IsServer) { - if (!NetworkManager.DAHost) + // Don't send a message in DA mode if we're the only observers of this object (we're the only authority). + if (distributedAuthority && Observers.Count <= 1) { - NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, 0); return; } - else - { - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) - { - if (clientId == NetworkManager.ServerClientId) - { - continue; - } - NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); - } - } + + NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); + return; } - else + + // Otherwise we are a Server (client-server or DAHost). Send to all observers + foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) { - // Otherwise we are running in client-server =or= this has to be a DAHost instance. - // Send to all connected clients. - unsafe + if (clientId == NetworkManager.ServerClientId) { - var maxCount = NetworkManager.ConnectedClientsIds.Count; - ulong* clientIds = stackalloc ulong[maxCount]; - int idx = 0; - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) - { - if (clientId == NetworkManager.ServerClientId) - { - continue; - } - if (Observers.Contains(clientId)) - { - clientIds[idx++] = clientId; - } - } - NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientIds, idx); + continue; + } + if (Observers.Contains(clientId)) + { + NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); } } } From 7ccb06b703097a6120e2a34bbaa9eb20cc90b8b3 Mon Sep 17 00:00:00 2001 From: Emma Date: Tue, 21 Oct 2025 17:17:33 -0400 Subject: [PATCH 8/9] Fix TransformsMatch check --- .../NetworkTransform/NetworkTransformOrderOfOperations.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs index 0cee832993..f32dc89161 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs @@ -111,6 +111,11 @@ private bool TransformsMatch(StringBuilder errorLog) foreach (var networkManager in m_NetworkManagers) { + if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(m_AuthoritySeqControllerInstance.NetworkObjectId)) + { + hasErrors = true; + continue; + } var nonAuthorityInstance = networkManager.SpawnManager.SpawnedObjects[m_AuthoritySeqControllerInstance.NetworkObjectId].GetComponent(); var nonAuthorityEulerRotation = nonAuthorityInstance.GetSpaceRelativeRotation().eulerAngles; From 825eb360b247ac3244b1d0d874b0e54598aa465c Mon Sep 17 00:00:00 2001 From: Emma Date: Tue, 21 Oct 2025 17:51:15 -0400 Subject: [PATCH 9/9] Fix some tests --- .../Runtime/Core/NetworkObject.cs | 14 ++------ .../NetworkTransformOrderOfOperations.cs | 33 ++++++++++++++++--- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs index 1cd5214e93..74d1a412f0 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs @@ -1171,14 +1171,7 @@ private bool InternalHasAuthority() /// /// Gets if the object is owned by the local player or if the object is the local player object /// - public bool IsOwner - { - get - { - Debug.Log($"[Client-{NetworkManager.LocalClientId}][Object-{NetworkObjectId}] Owned by {OwnerClientId}"); - return NetworkManager != null && OwnerClientId == NetworkManager.LocalClientId; - } - } + public bool IsOwner => NetworkManager != null && OwnerClientId == NetworkManager.LocalClientId; /// /// Gets Whether or not the object is owned by anyone @@ -2224,12 +2217,12 @@ public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true) // DANGO-TODO: Do we want to worry about ownership permissions here? // It wouldn't make sense to not allow parenting, but keeping this note here as a reminder. var isAuthority = HasAuthority || (AllowOwnerToParent && IsOwner); + Debug.Log($"something is broken! isAuthority={isAuthority} | HasAuthority={HasAuthority} | (AllowOwnerToParent && IsOwner)={(AllowOwnerToParent && IsOwner)}"); // If we don't have authority and we are not shutting down, then don't allow any parenting. // If we are shutting down and don't have authority then allow it. if (!isAuthority && !NetworkManager.ShutdownInProgress) { - Debug.LogError("We don't have authority here"); return false; } @@ -2293,7 +2286,6 @@ private void OnTransformParentChanged() // With distributed authority, we need to track "valid authoritative" parenting changes. // So, either the authority or AuthorityAppliedParenting is considered a "valid parenting change". isAuthority = HasAuthority || AuthorityAppliedParenting || (AllowOwnerToParent && IsOwner); - Debug.Log($"[Client-{NetworkManager.LocalClientId}][Object-{NetworkObjectId}] OnTransformParentChanged. HasAuthority={HasAuthority}, AuthorityAppliedParenting={AuthorityAppliedParenting}, AllowOwnerToParent && IsOwner={AllowOwnerToParent && IsOwner}"); var distributedAuthority = NetworkManager.DistributedAuthorityMode; // If we do not have authority and we are spawned @@ -2364,8 +2356,6 @@ private void OnTransformParentChanged() var authorityApplied = AuthorityAppliedParenting; ApplyNetworkParenting(removeParent); - - var message = new ParentSyncMessage { NetworkObjectId = NetworkObjectId, diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs index f32dc89161..20630f0803 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs @@ -178,7 +178,7 @@ public IEnumerator OrderOfOperations() var parent1 = m_AuthorityParentInstances[0]; var parent2 = m_AuthorityParentInstances[1]; - ConfigureSequencesTest1(parent1); + ConfigureSequencesTest1_ClientServerOnly(parent1); yield return RunTestSequences(); ConfigureSequencesTest2(parent1); @@ -293,12 +293,19 @@ private IEnumerator __RunTestSequences(bool spawnWithObservers = true, bool spaw #region Test Sequence Configurations /// + /// Client server only - under da mode only the authority can parent /// Test-1: /// Authority-> Spawn, change ownership, (wait), parent /// - private void ConfigureSequencesTest1(NetworkObject parent) + private void ConfigureSequencesTest1_ClientServerOnly(NetworkObject parent) { - SpawnSequenceController.CurrentTest = "Test1"; + SpawnSequenceController.CurrentTest = "Test1 (Client-Server Only)"; + if (m_AuthorityNetworkManager.DistributedAuthorityMode) + { + SpawnSequenceController.ClientServerOnly = true; + return; + } + var changeOwnershipSequence = new ChangeOwnershipSequence() { Stage = SpawnSequence.SpawnStage.AfterSpawn, @@ -310,6 +317,7 @@ private void ConfigureSequencesTest1(NetworkObject parent) TimeDelayInMS = 200, Stage = SpawnSequence.SpawnStage.AfterSpawn, TargetParent = parent, + InvokeOnlyOnClientId = GetAuthorityNetworkManager().LocalClientId, }; SpawnSequenceController.AddAction(changeOwnershipSequence); @@ -860,6 +868,10 @@ protected override bool OnShouldInvoke(SpawnStage stage) protected override void OnAction() { m_NetworkObject.ChangeOwnership(TargetOwnerClientId); + if (TargetOwnerClientId != m_NetworkObject.OwnerClientId) + { + Debug.LogError($"[{m_NetworkObject.name}] Failed to change ownership!"); + } base.OnAction(); } } @@ -871,7 +883,20 @@ internal class ParentSequence : SpawnSequence protected override bool OnShouldInvoke(SpawnStage stage) { - return base.OnShouldInvoke(stage) && (m_NetworkObject.HasAuthority || (m_NetworkObject.IsOwner && m_NetworkObject.AllowOwnerToParent)); + // Don't invoke if the base says no + if (!base.OnShouldInvoke(stage)) + { + return false; + } + + // If sequence is configured to specifically invoke on this client + if (InvokeOnlyOnClientId.HasValue && m_NetworkObject.NetworkManager.LocalClientId == InvokeOnlyOnClientId.Value) + { + return true; + } + + // Otherwise we should invoke if we have the authority to invoke + return m_NetworkObject.HasAuthority || (m_NetworkObject.IsOwner && m_NetworkObject.AllowOwnerToParent); } protected override void OnAction()