Skip to content

Commit 5fe98da

Browse files
fix: set the ghost owner before OnNetworkSpawn
- The ghost owner is now assigned right after SetupOnSpawn, so OnNetworkSpawn sees the same owner on the NetworkObject and its ghost. The interop test records the ghost owner in OnNetworkSpawn and asserts it. - NetworkVariableReadDuringPredictionIsNotTickAligned asserts that a re-simulated tick reads a different value than its first prediction, rather than counting reads before the stamp tick. - NetworkShowThenClientDisconnects is only ignored for UnifiedServer, the fixture where the scene migration failure occurs.
1 parent f6fee1d commit 5fe98da

3 files changed

Lines changed: 18 additions & 7 deletions

File tree

‎com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,6 @@ internal bool AuthorityLocalSpawn([NotNull] NetworkObject networkObject, ulong n
11831183
if (networkObject.HasGhost)
11841184
{
11851185
networkObject.NetworkObjectBridge.NetworkObjectId.Value = networkObject.NetworkObjectId;
1186-
networkObject.NetworkObjectBridge.UpdateGhostOwner(NetworkManager, networkObject.OwnerClientId);
11871186
}
11881187
#endif
11891188

@@ -1309,6 +1308,13 @@ internal bool SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
13091308
}
13101309

13111310
networkObject.SetupOnSpawn(networkId, playerObject, ownerClientId, destroyWithScene);
1311+
#if UNIFIED_NETCODE
1312+
// Before OnNetworkSpawn, so owner-specific initialization sees the ghost owner too.
1313+
if (networkObject.HasGhost)
1314+
{
1315+
networkObject.NetworkObjectBridge.UpdateGhostOwner(NetworkManager, ownerClientId);
1316+
}
1317+
#endif
13121318

13131319
SpawnedObjects.Add(networkObject.NetworkObjectId, networkObject);
13141320
SpawnedObjectsList.Add(networkObject);

‎com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public IEnumerator DontDestroyWithOwnerTest([Values] ParentedPass parentedPass)
290290
public IEnumerator NetworkShowThenClientDisconnects()
291291
{
292292
#if UNIFIED_NETCODE
293-
if (m_AllPrefabsAsHybrid)
293+
if (m_AllPrefabsAsHybrid && !m_UseHost)
294294
{
295295
Assert.Ignore("A scene migration update can reach a client before the hybrid object's ghost has spawned there.");
296296
}

‎com.unity.netcode.gameobjects/Tests/Runtime/Unified/HybridInteropTests.cs‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,13 @@ internal class HybridInteropNetworkBehaviour : NetworkBehaviour
155155
public int OwnerWrittenTickChanges;
156156
public int OwnerWrittenTickDecreases;
157157
public bool GhostWasPredictedOnSpawn;
158+
public NetworkId GhostOwnerOnSpawn;
158159

159160
public override void OnNetworkSpawn()
160161
{
161-
GhostWasPredictedOnSpawn = GetComponent<GhostObject>().IsPredictedGhost;
162+
var ghost = GetComponent<GhostObject>();
163+
GhostWasPredictedOnSpawn = ghost.IsPredictedGhost;
164+
GhostOwnerOnSpawn = ghost.OwnerNetworkId;
162165
OwnerWrittenTick.OnValueChanged += OnOwnerWrittenTickChanged;
163166
}
164167

@@ -242,8 +245,10 @@ protected override IEnumerator OnServerAndClientsConnected()
242245
{
243246
var client = m_ClientNetworkManagers[0];
244247
m_ServerInstance = SpawnObject(m_InteropPrefab, client).GetComponent<NetworkObject>();
245-
Assert.AreEqual(client.NetcodeWorld.LocalConnection.NetworkId, m_ServerInstance.GetComponent<GhostObject>().OwnerNetworkId,
246-
"Spawning with an NGO owner did not set the ghost owner!");
248+
var clientNetworkId = client.NetcodeWorld.LocalConnection.NetworkId;
249+
Assert.AreEqual(clientNetworkId, m_ServerInstance.GetComponent<GhostObject>().OwnerNetworkId, "Spawning with an NGO owner did not set the ghost owner!");
250+
Assert.AreEqual(clientNetworkId, m_ServerInstance.GetComponent<HybridInteropNetworkBehaviour>().GhostOwnerOnSpawn,
251+
"The ghost owner was not set yet when OnNetworkSpawn was invoked!");
247252
yield return WaitForSpawnedOnAllOrTimeOut(m_ServerInstance);
248253
AssertOnTimeout($"Timed out waiting for {m_ServerInstance.name} to spawn on all clients!");
249254
m_ClientInstance = client.SpawnManager.SpawnedObjects[m_ServerInstance.NetworkObjectId];
@@ -300,14 +305,14 @@ public IEnumerator NgoRpcToUnifiedRemoteToNgoRpc()
300305
}
301306

302307
/// <summary>
303-
/// A NetworkVariable is not rolled back: prediction of a tick before the value's stamp still reads the new value.
308+
/// A NetworkVariable is not rolled back: re-simulating a tick can read a different value than its first prediction did.
304309
/// </summary>
305310
[UnityTest]
306311
public IEnumerator NetworkVariableReadDuringPredictionIsNotTickAligned()
307312
{
308313
yield return RecordAcrossStampedValueChange();
309314
var clientGhost = m_ClientInstance.GetComponent<HybridInteropGhost>();
310-
Assert.Greater(clientGhost.EarlyReadsOfNewValue, 0, "Expected prediction of ticks before the stamp to read the new value.");
315+
Assert.Greater(clientGhost.InconsistentRawTicks, 0, "Expected a re-simulated tick to read a different value than its first prediction.");
311316
}
312317

313318
/// <summary>

0 commit comments

Comments
 (0)