Skip to content

Commit bebbc3a

Browse files
fix: serialize the scene placed field and fix DA scene migration (#4086)
* fix - Adjusted the `InScenePlaced` property to internally set or publicly get the serialized `m_InScenePlaced` field. - `NetworkObject` now implements `ISerializationCallbackReceiver` to assure `m_InScenePlaced` is always properly set for in-scene placed objects. - Removed legacy define for UNITY_2021_2_OR_NEWER since v2.x.x+ is only for Unity v6. * test - Adding `NetworkSceneManagerStartupTests` which validates this PR. - Adding the assets and script needed to validate this PR. - Updated scenes in build list to include the new scene: InSceneNetworkObjectMovesToDDOL. * update Adding change log entry. * fix Fixing issue with marking things as in-scene placed during runtime. * update Commenting out the addressable scene test. Adding back the check for InScenePlaced when shutting down. * revert and update - `ISerializationCallbackReceiver` implementation as that does not accomplish what we need. - Setting InScenePlaced within OnValidate instead. * fix Only reset things that have been spawned are in-scene placed, and is assigned to the relative NetworkManager (for integration testing purposes) * update Removing the addressable scene. We will revisit this when this is supported. * fix and style Fixing several issues with NetworkObjectSceneMigrationTests. Fixing several formatting issues. * style brackets adjustment. * style Adding white spaces between foreach and if * style Fixing some out of alignment if statements. * style Didn't save the change... adding last standards check issue fix. * fix Fixing issue where we were sending scene migration notifications when migrating into the DDOL. Fixing issue where if a client detected a changed scene but had no scene change to send (later) it would throw and exception and cause a memory leak. * update Remove the legacy multiprocess scene that is no longer used and has references to scripts that no longer exist. * fix Issue where distributed authority would throw an exception during scene migration due to the fact that we would throw an exception if the 1st scene in the scene migration table didn't contain the client that has authority over the NetworkObject that migrated into a new scene. Now we count how many entries were written and if that count is zero upon parsing known loaded scenes then it throws an exception. Reverting the exclusion of DDOL synchronization (that was a red herring). * test - fix Removing the ValidateSceneOnAllClients portion as that doesn't assure that all clients have loaded the scene and fully synchronized the scene which could lead to edge case issues during this test. * update Adding and updating the change log entries for this PR.
1 parent 6d6e249 commit bebbc3a

30 files changed

Lines changed: 815 additions & 1351 deletions

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ Additional documentation and release notes are available at [Multiplayer Documen
2222

2323
### Fixed
2424

25-
- Fixed AnticipatedNetworkTransform not respecting the InLocalSpace flag (#3995)
25+
- Issue where scene migration in a distributed authority session would throw an exception on clients migrating their owned `NetworkObject` instances to a different scene.(#4086)
26+
- Issue where migrating a dynamically spawned or in-scene placed `NetworkObject` into a different scene during awake could result in that spawned instance to not be synchronized. (#4086)
2627
- Issue where a NullReferenceException was thrown when a non-authority failed to spawn a NetworkObject. (#4067)
2728
- Issue where the active scene was not being serialized as the 1st scene which could result in various errors including a soft synchronization error if, on the client-side, other synchronized scenes had already been loaded prior to the active scene, which is always loaded as `LoadSceneMode.SingleMode` when client synchronization is set to `LoadSceneMode.SingleMode`, resulting in the previously loaded scene(s) to be unloaded. (#4065)
2829
- Issue when FastBufferReader is attempting to read a string and all or a portion of the character count has already been read by user script, it could read a character length that results in a negative byte length which could result in an editor crash. (#4052)
2930
- Issue where NetworkRigidbodyBase was not applying rotation correctly when using Rigidbody2D. (#4012)
3031
- Issue where NetworkRigidbodyBase was always checking the 3D rigid body's interpolation mode when determining if it is kinematic and needs to put the rigid body to sleep and then switch to interpolation. (#4012)
32+
- Fixed AnticipatedNetworkTransform not respecting the InLocalSpace flag. (#3995)
3133

3234
### Security
3335

com.unity.netcode.gameobjects/Editor/NetworkManagerHelper.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ public bool NotifyUserOfNestedNetworkManager(NetworkManager networkManager, bool
195195
{
196196
return isParented;
197197
}
198-
else // If we are no longer a child, then we can remove ourself from this list
199-
if (transform.root == gameObject.transform)
200-
{
201-
s_LastKnownNetworkManagerParents.Remove(networkManager);
202-
}
198+
else if (transform.root == gameObject.transform)
199+
{
200+
// If we are no longer a child, then we can remove ourself from this list
201+
s_LastKnownNetworkManagerParents.Remove(networkManager);
202+
}
203203
}
204204
if (!EditorApplication.isUpdating && isParented)
205205
{

com.unity.netcode.gameobjects/Runtime/Components/Interpolator/BufferedLinearInterpolator.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -467,20 +467,20 @@ internal T Update(float deltaTime, double tickLatencyAsTime, double minDeltaTime
467467
InterpolateState.CurrentValue = InterpolateState.NextValue;
468468
}
469469
}
470-
else // If the target is reached and we have no more state updates, we want to check to see if we need to reset.
471-
if (m_BufferQueue.Count == 0)
470+
// If the target is reached and we have no more state updates, we want to check to see if we need to reset.
471+
else if (m_BufferQueue.Count == 0)
472+
{
473+
// When the delta between the time sent and the current tick latency time-window is greater than the max delta time
474+
// plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero),
475+
// we will want to reset the interpolator with the current known value. This prevents the next received state update's
476+
// time to be calculated against the last calculated time which if there is an extended period of time between the two
477+
// it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then
478+
// starts moving again).
479+
if ((tickLatencyAsTime - InterpolateState.Target.Value.TimeSent) > InterpolateState.MaxDeltaTime + minDeltaTime)
472480
{
473-
// When the delta between the time sent and the current tick latency time-window is greater than the max delta time
474-
// plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero),
475-
// we will want to reset the interpolator with the current known value. This prevents the next received state update's
476-
// time to be calculated against the last calculated time which if there is an extended period of time between the two
477-
// it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then
478-
// starts moving again).
479-
if ((tickLatencyAsTime - InterpolateState.Target.Value.TimeSent) > InterpolateState.MaxDeltaTime + minDeltaTime)
480-
{
481-
InterpolateState.Reset(InterpolateState.CurrentValue);
482-
}
481+
InterpolateState.Reset(InterpolateState.CurrentValue);
483482
}
483+
}
484484
}
485485
m_NbItemsReceivedThisFrame = 0;
486486
return InterpolateState.CurrentValue;
@@ -593,20 +593,20 @@ public T Update(float deltaTime, double renderTime, double serverTime)
593593
// Determine if we have reached our target
594594
InterpolateState.TargetReached = IsApproximately(InterpolateState.CurrentValue, InterpolateState.Target.Value.Item, GetPrecision());
595595
}
596-
else // If the target is reached and we have no more state updates, we want to check to see if we need to reset.
597-
if (InterpolateState.TargetReached && m_BufferQueue.Count == 0)
596+
// If the target is reached and we have no more state updates, we want to check to see if we need to reset.
597+
else if (InterpolateState.TargetReached && m_BufferQueue.Count == 0)
598+
{
599+
// When the delta between the time sent and the current tick latency time-window is greater than the max delta time
600+
// plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero),
601+
// we will want to reset the interpolator with the current known value. This prevents the next received state update's
602+
// time to be calculated against the last calculated time which if there is an extended period of time between the two
603+
// it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then
604+
// starts moving again).
605+
if ((renderTime - InterpolateState.Target.Value.TimeSent) > 0.3f) // If we haven't recevied anything within 300ms, assume we stopped motion.
598606
{
599-
// When the delta between the time sent and the current tick latency time-window is greater than the max delta time
600-
// plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero),
601-
// we will want to reset the interpolator with the current known value. This prevents the next received state update's
602-
// time to be calculated against the last calculated time which if there is an extended period of time between the two
603-
// it would cause a large delta time period between the two states (i.e. it stops moving for a second or two and then
604-
// starts moving again).
605-
if ((renderTime - InterpolateState.Target.Value.TimeSent) > 0.3f) // If we haven't recevied anything within 300ms, assume we stopped motion.
606-
{
607-
InterpolateState.Reset(InterpolateState.CurrentValue);
608-
}
607+
InterpolateState.Reset(InterpolateState.CurrentValue);
609608
}
609+
}
610610
m_NbItemsReceivedThisFrame = 0;
611611
return InterpolateState.CurrentValue;
612612
}

com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,26 +1180,25 @@ internal void CheckForAnimatorChanges()
11801180
{
11811181
SendAnimStateRpc(m_AnimationMessage);
11821182
}
1183+
else if (!IsServer && IsOwner)
1184+
{
1185+
SendServerAnimStateRpc(m_AnimationMessage);
1186+
}
11831187
else
1184-
if (!IsServer && IsOwner)
1185-
{
1186-
SendServerAnimStateRpc(m_AnimationMessage);
1187-
}
1188-
else
1188+
{
1189+
// Just notify all remote clients and not the local server
1190+
m_TargetGroup.Clear();
1191+
foreach (var clientId in LocalNetworkManager.ConnectionManager.ConnectedClientIds)
11891192
{
1190-
// Just notify all remote clients and not the local server
1191-
m_TargetGroup.Clear();
1192-
foreach (var clientId in LocalNetworkManager.ConnectionManager.ConnectedClientIds)
1193+
if (clientId == LocalNetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId))
11931194
{
1194-
if (clientId == LocalNetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId))
1195-
{
1196-
continue;
1197-
}
1198-
m_TargetGroup.Add(clientId);
1195+
continue;
11991196
}
1200-
m_RpcParams.Send.Target = m_TargetGroup.Target;
1201-
SendClientAnimStateRpc(m_AnimationMessage, m_RpcParams);
1197+
m_TargetGroup.Add(clientId);
12021198
}
1199+
m_RpcParams.Send.Target = m_TargetGroup.Target;
1200+
SendClientAnimStateRpc(m_AnimationMessage, m_RpcParams);
1201+
}
12031202
}
12041203
}
12051204

@@ -1346,25 +1345,24 @@ private unsafe void WriteParameters(ref FastBufferWriter writer)
13461345
BytePacker.WriteValuePacked(writer, (uint)valueInt);
13471346
}
13481347
}
1349-
else
1350-
if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterBool)
1348+
else if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterBool)
1349+
{
1350+
var valueBool = m_Animator.GetBool(hash);
1351+
fixed (void* value = cacheValue.Value)
13511352
{
1352-
var valueBool = m_Animator.GetBool(hash);
1353-
fixed (void* value = cacheValue.Value)
1354-
{
1355-
UnsafeUtility.WriteArrayElement(value, 0, valueBool);
1356-
BytePacker.WriteValuePacked(writer, valueBool);
1357-
}
1353+
UnsafeUtility.WriteArrayElement(value, 0, valueBool);
1354+
BytePacker.WriteValuePacked(writer, valueBool);
13581355
}
1359-
else if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterFloat)
1356+
}
1357+
else if (cacheValue.Type == AnimationParamEnumWrapper.AnimatorControllerParameterFloat)
1358+
{
1359+
var valueFloat = m_Animator.GetFloat(hash);
1360+
fixed (void* value = cacheValue.Value)
13601361
{
1361-
var valueFloat = m_Animator.GetFloat(hash);
1362-
fixed (void* value = cacheValue.Value)
1363-
{
1364-
UnsafeUtility.WriteArrayElement(value, 0, valueFloat);
1365-
BytePacker.WriteValuePacked(writer, valueFloat);
1366-
}
1362+
UnsafeUtility.WriteArrayElement(value, 0, valueFloat);
1363+
BytePacker.WriteValuePacked(writer, valueFloat);
13671364
}
1365+
}
13681366
}
13691367
}
13701368

com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,24 +2515,24 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, bool is
25152515
}
25162516
}
25172517
}
2518-
else // Just apply the full local scale when synchronizing
2519-
if (SynchronizeScale)
2518+
// Just apply the full local scale when synchronizing
2519+
else if (SynchronizeScale)
2520+
{
2521+
var localScale = CachedTransform.localScale;
2522+
if (!UseHalfFloatPrecision)
25202523
{
2521-
var localScale = CachedTransform.localScale;
2522-
if (!UseHalfFloatPrecision)
2523-
{
25242524

2525-
networkState.ScaleX = localScale.x;
2526-
networkState.ScaleY = localScale.y;
2527-
networkState.ScaleZ = localScale.z;
2528-
}
2529-
else
2530-
{
2531-
networkState.Scale = localScale;
2532-
}
2533-
flagStates.MarkChanged(AxialType.Scale, true);
2534-
isScaleDirty = true;
2525+
networkState.ScaleX = localScale.x;
2526+
networkState.ScaleY = localScale.y;
2527+
networkState.ScaleZ = localScale.z;
25352528
}
2529+
else
2530+
{
2531+
networkState.Scale = localScale;
2532+
}
2533+
flagStates.MarkChanged(AxialType.Scale, true);
2534+
isScaleDirty = true;
2535+
}
25362536
isDirty |= isPositionDirty || isRotationDirty || isScaleDirty;
25372537

25382538
if (isDirty)
@@ -3488,12 +3488,12 @@ private void NonAuthorityFinalizeSynchronization()
34883488
child.InternalInitialization();
34893489
}
34903490
}
3491-
else // Otherwise, just run through standard synchronization of this instance
3492-
if (!CanCommitToTransform)
3493-
{
3494-
ApplySynchronization();
3495-
InternalInitialization();
3496-
}
3491+
// Otherwise, just run through standard synchronization of this instance
3492+
else if (!CanCommitToTransform)
3493+
{
3494+
ApplySynchronization();
3495+
InternalInitialization();
3496+
}
34973497
}
34983498
}
34993499

com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -967,19 +967,18 @@ internal void ProcessClientsToDisconnect()
967967
{
968968
return (true, playerPrefabHash.Value);
969969
}
970-
else
971-
if (NetworkManager.NetworkConfig.PlayerPrefab != null)
970+
else if (NetworkManager.NetworkConfig.PlayerPrefab != null)
971+
{
972+
var networkObject = NetworkManager.NetworkConfig.PlayerPrefab.GetComponent<NetworkObject>();
973+
if (networkObject != null)
972974
{
973-
var networkObject = NetworkManager.NetworkConfig.PlayerPrefab.GetComponent<NetworkObject>();
974-
if (networkObject != null)
975-
{
976-
return (true, networkObject.GlobalObjectIdHash);
977-
}
978-
else
979-
{
980-
NetworkManager.Log.Error(new Logging.Context(LogLevel.Error, $"Player prefab {NetworkManager.NetworkConfig.PlayerPrefab.name} has no {nameof(NetworkObject)}!"));
981-
}
975+
return (true, networkObject.GlobalObjectIdHash);
982976
}
977+
else
978+
{
979+
NetworkManager.Log.Error(new Logging.Context(LogLevel.Error, $"Player prefab {NetworkManager.NetworkConfig.PlayerPrefab.name} has no {nameof(NetworkObject)}!"));
980+
}
981+
}
983982
return (false, 0);
984983
}
985984

0 commit comments

Comments
 (0)