diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs index f7a2f1303a..373b3c96ad 100644 --- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs @@ -1953,36 +1953,46 @@ private void SynchronizeNetworkObjectScene() { foreach (var networkObject in NetworkManager.SpawnManager.SpawnedObjectsList) { - // This is only done for dynamically spawned NetworkObjects - // Theoretically, a server could have NetworkObjects in a server-side only scene, if the client doesn't have that scene loaded - // then skip it (it will reside in the currently active scene in this scenario on the client-side) - if (networkObject.IsSceneObject.Value == false && ServerSceneHandleToClientSceneHandle.ContainsKey(networkObject.NetworkSceneHandle)) + // Edge case: If any exceptions occur, log them but continue processing so we don't break the client synchronization process. + try { - networkObject.SceneOriginHandle = ServerSceneHandleToClientSceneHandle[networkObject.NetworkSceneHandle]; - - - - // If the NetworkObject does not have a parent and is not in the same scene as it is on the server side, then find the right scene - // and move it to that scene. - if (networkObject.gameObject.scene.handle != networkObject.SceneOriginHandle && networkObject.transform.parent == null) + // This is only done for dynamically spawned NetworkObjects + // Theoretically, a server could have NetworkObjects in a server-side only scene, if the client doesn't have that scene loaded + // then skip it (it will reside in the currently active scene in this scenario on the client-side) + if (networkObject.IsSceneObject.Value == false && ServerSceneHandleToClientSceneHandle.ContainsKey(networkObject.NetworkSceneHandle)) { - if (ScenesLoaded.ContainsKey(networkObject.SceneOriginHandle)) + networkObject.SceneOriginHandle = ServerSceneHandleToClientSceneHandle[networkObject.NetworkSceneHandle]; + + // If the NetworkObject does not have a parent and is not in the same scene as it is on the server side, then find the right scene + // and move it to that scene. + if (networkObject.gameObject.scene.handle != networkObject.SceneOriginHandle && networkObject.transform.parent == null) { - var scene = ScenesLoaded[networkObject.SceneOriginHandle]; - if (scene == DontDestroyOnLoadScene) + if (ScenesLoaded.ContainsKey(networkObject.SceneOriginHandle)) { - Debug.Log($"{networkObject.gameObject.name} migrating into DDOL!"); - } + var scene = ScenesLoaded[networkObject.SceneOriginHandle]; + if (scene == DontDestroyOnLoadScene) + { + Debug.Log($"{networkObject.gameObject.name} migrating into DDOL!"); + } - SceneManager.MoveGameObjectToScene(networkObject.gameObject, scene); - } - else if (NetworkManager.LogLevel <= LogLevel.Normal) - { - NetworkLog.LogWarningServer($"[Client-{NetworkManager.LocalClientId}][{networkObject.gameObject.name}] Server - " + - $"client scene mismatch detected! Client-side has no scene loaded with handle ({networkObject.SceneOriginHandle})!"); + SceneManager.MoveGameObjectToScene(networkObject.gameObject, scene); + } + else if (NetworkManager.LogLevel <= LogLevel.Normal) + { + NetworkLog.LogWarningServer($"[Client-{NetworkManager.LocalClientId}][{networkObject.gameObject.name}] Server - " + + $"client scene mismatch detected! Client-side has no scene loaded with handle ({networkObject.SceneOriginHandle})!"); + } } } } + catch (Exception ex) + { + if (NetworkManager.LogLevel <= LogLevel.Error) + { + var networkObjectName = networkObject.gameObject != null ? networkObject.name : "Invalid GameObject"; + NetworkLog.LogErrorServer($"[Client-{NetworkManager.LocalClientId}][{networkObjectName}][Spawned: {networkObject.IsSpawned}] {ex.Message}\n {ex.StackTrace}"); + } + } } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs index 321f9137df..fa7180a2f5 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text; using NUnit.Framework; using Unity.Netcode.Components; @@ -448,6 +449,12 @@ private bool AllInstancesKeptLocalTransformValues() return true; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private string Vector3String(Vector3 vector3) + { + return $"{vector3.x,0:0.00000}, {vector3.y,0:0.00000}, {vector3.z,0:0.00000}"; + } + /// /// Handles validating the local space values match the original local space values. /// If not, it generates a message containing the axial values that did not match @@ -476,12 +483,12 @@ private void AllChildrenLocalTransformValuesMatch(bool useSubChild) } if (!Approximately(childLocalPosition, authorityObjectLocalPosition)) { - infoMessage.AppendLine($"[{childInstance.name}] Child's Local Position ({childLocalPosition}) | Authority Local Position ({authorityObjectLocalPosition})"); + infoMessage.AppendLine($"[{childInstance.name}] Child's Local Position ({Vector3String(childLocalPosition)}) | Authority Local Position ({Vector3String(authorityObjectLocalPosition)})"); success = false; } if (!Approximately(childLocalScale, authorityObjectLocalScale)) { - infoMessage.AppendLine($"[{childInstance.name}] Child's Local Scale ({childLocalScale}) | Authority Local Scale ({authorityObjectLocalScale})"); + infoMessage.AppendLine($"[{childInstance.name}] Child's Local Scale ({Vector3String(childLocalPosition)}) | Authority Local Scale ({Vector3String(authorityObjectLocalScale)})"); success = false; } @@ -492,7 +499,7 @@ private void AllChildrenLocalTransformValuesMatch(bool useSubChild) } if (!ApproximatelyEuler(childLocalRotation, authorityObjectLocalRotation)) { - infoMessage.AppendLine($"[{childInstance.name}] Child's Local Rotation ({childLocalRotation}) | Authority Local Rotation ({authorityObjectLocalRotation})"); + infoMessage.AppendLine($"[{childInstance.name}] Child's Local Rotation ({Vector3String(childLocalRotation)}) | Authority Local Rotation ({Vector3String(authorityObjectLocalRotation)})"); success = false; } }