Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: client synchronization edge case interruption [MTT-7100] #2658

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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}");
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using NUnit.Framework;
using Unity.Netcode.Components;
Expand Down Expand Up @@ -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}";
}

/// <summary>
/// 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
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
}
Expand Down