Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
15 changes: 15 additions & 0 deletions com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Unity.Netcode.Logging;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
Expand All @@ -19,8 +20,22 @@
public int callbackOrder => 0;
public void OnProcessScene(Scene scene, BuildReport report)
{
var log = new ContextualLogger();
log.AddInfo(scene.name, scene.handle);
foreach (var networkObject in FindObjects.FromSceneByType<NetworkObject>(scene, true))
{
if (networkObject.SceneOrigin.IsValid() && networkObject.SceneOrigin.handle != scene.handle)
{
log.Warning(new Context(LogLevel.Developer, $"{nameof(NetworkObject)}'s SceneOrigin doesn't match current scene being processed! Skipping processing.").AddInfo("SceneOrigin", networkObject.SceneOriginHandle).AddNetworkObject(networkObject));
continue;

Check warning on line 30 in com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs#L27-L30

Added lines #L27 - L30 were not covered by tests
}

if (networkObject.HasBeenSpawned)
{
log.Error(new Context(LogLevel.Normal, $"Processing {nameof(NetworkObject)} that has already been spawned! This should not be possible. Skipping processing.").AddNetworkObject(networkObject));
continue;

Check warning on line 36 in com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs#L33-L36

Added lines #L33 - L36 were not covered by tests
}

networkObject.InScenePlaced = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,22 @@
return false;
}

if (networkObject.InScenePlaced)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
{
NetworkLog.LogWarning($"{NetworkPrefabHandler.PrefabDebugHelper(this)} InScenePlaced {nameof(NetworkObject)} is being registered as a Prefab. This can cause issues!");
}
}

Check warning on line 175 in com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefab.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefab.cs#L170-L175

Added lines #L170 - L175 were not covered by tests

if (networkObject.IsSpawned)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
{
NetworkLog.LogWarning($"{NetworkPrefabHandler.PrefabDebugHelper(this)} Currently spawned {nameof(NetworkObject)} is being registered as a Prefab. This can cause issues!");
}
}

Check warning on line 183 in com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefab.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefab.cs#L178-L183

Added lines #L178 - L183 were not covered by tests

return true;
}

Expand Down
66 changes: 46 additions & 20 deletions com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using Unity.Netcode.Components;
using Unity.Netcode.Logging;
using Unity.Netcode.Runtime;
#if UNITY_EDITOR
using UnityEditor;
Expand Down Expand Up @@ -106,6 +107,9 @@
/// </summary>
public NetworkObject CurrentParent { get; private set; }

private int m_SpawnCount;
internal bool HasBeenSpawned => m_SpawnCount > 0;

Check warning on line 111 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L111

Added line #L111 was not covered by tests

#if UNITY_EDITOR
private const string k_GlobalIdTemplate = "GlobalObjectId_V1-{0}-{1}-{2}-{3}";

Expand Down Expand Up @@ -1448,12 +1452,16 @@

set
{
if (SceneOriginHandle.IsEmpty() && value.IsValid() && value.isLoaded)
{
SceneOriginHandle = value.handle;
}

// The scene origin should only be set once.
// Once set, it should never change.
if (SceneOriginHandle.IsEmpty() && value.IsValid() && value.isLoaded)
if (!m_SceneOrigin.IsValid())
{
m_SceneOrigin = value;
SceneOriginHandle = value.handle;
}
}
}
Expand Down Expand Up @@ -1782,7 +1790,7 @@
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool playerObject)
private void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool playerObject)
{
if (NetworkManagerOwner == null)
{
Expand Down Expand Up @@ -1853,7 +1861,28 @@
}
}

if (!NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), InScenePlaced, playerObject, ownerClientId, destroyWithScene))

// Calculate the legacy IsSceneObject value as the public field is obsolete with warning
// We can't break the public behavior of the field.
#pragma warning disable CS0618 // Type or member is obsolete
var legacyIsSceneObject = IsSceneObject.HasValue && IsSceneObject.Value;
#pragma warning restore CS0618 // Type or member is obsolete

// If SpawnInternal is being called on an object that is marked as InScenePlaced,
// The scene object was never automatically spawned when the scene was loaded.
// Count this object as a dynamically spawned object.
// TODO-[MTT-15388]: Actually support disabled/not spawned InScenePlaced NetworkObjects
if (InScenePlaced && m_SpawnCount == 0)
Comment thread
EmandM marked this conversation as resolved.
Outdated
{
if (NetworkManagerOwner.NetworkConfig.EnableSceneManagement && NetworkManagerOwner.LogLevel <= LogLevel.Developer)
{
Debug.LogWarning($"[{name}][SceneOrigin={SceneOriginHandle}] Dynamically spawning InScenePlaced network object. This can cause issues!", this);
}

Check warning on line 1880 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L1876-L1880

Added lines #L1876 - L1880 were not covered by tests

InScenePlaced = false;
}

Check warning on line 1883 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L1882-L1883

Added lines #L1882 - L1883 were not covered by tests

if (!NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), legacyIsSceneObject, playerObject, ownerClientId, destroyWithScene))
{
if (NetworkManagerOwner.LogLevel <= LogLevel.Normal)
{
Expand Down Expand Up @@ -2053,6 +2082,7 @@
// When spawned, previous owner is always the first assigned owner
PreviousOwnerId = ownerClientId;
m_HasAuthority = NetworkManagerOwner.DistributedAuthorityMode ? OwnerClientId == NetworkManagerOwner.LocalClientId : NetworkManagerOwner.IsServer;
m_SpawnCount++;
IsSpawned = true;

// If this is the player, and the client is the owner, then lock ownership by default
Expand Down Expand Up @@ -3466,11 +3496,7 @@

if (serializedObject.NetworkObjectId == default)
{
if (networkManager.LogLevel <= LogLevel.Error)
{
NetworkLog.LogErrorServer($"[{nameof(GlobalObjectIdHash)}={serializedObject.Hash}] Received spawn request with invalid {nameof(NetworkObjectId)} {serializedObject.NetworkObjectId}. This should not happen!");
}

NetworkLog.LogErrorServer(new Context(LogLevel.Error, $"Received spawn request with invalid {nameof(NetworkObjectId)}. This should not happen!").AddInfo(nameof(NetworkObjectId), serializedObject.NetworkObjectId).AddInfo(nameof(GlobalObjectIdHash), serializedObject.Hash));

Check warning on line 3499 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L3499

Added line #L3499 was not covered by tests
reader.Seek(endOfSynchronizationData);
return null;
}
Expand Down Expand Up @@ -3627,17 +3653,17 @@
NetworkSceneHandle = SceneOriginHandle;
}
}
else // Otherwise, the client did not find the client to server scene handle
if (NetworkManagerOwner.LogLevel <= LogLevel.Developer)
{
// There could be a scenario where a user has some client-local scene loaded that they migrate the NetworkObject
// into, but that scenario seemed very edge case and under most instances a user should be notified that this
// server - client scene handle mismatch has occurred. It also seemed pertinent to make the message replicate to
// the server-side too.
NetworkLog.LogWarningServer($"[Client-{NetworkManagerOwner.LocalClientId}][{name}] Server - " +
$"client scene mismatch detected! Client-side scene handle ({SceneOriginHandle}) for scene ({gameObject.scene.name})" +
$"has no associated server side (network) scene handle!");
}
// Otherwise, the client did not find the client to server scene handle
else if (NetworkManagerOwner.LogLevel <= LogLevel.Developer)
{

Check warning on line 3658 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L3657-L3658

Added lines #L3657 - L3658 were not covered by tests
// There could be a scenario where a user has some client-local scene loaded that they migrate the NetworkObject
// into, but that scenario seemed very edge case and under most instances a user should be notified that this
// server - client scene handle mismatch has occurred. It also seemed pertinent to make the message replicate to
// the server-side too.
NetworkLog.LogWarningServer($"[Client-{NetworkManagerOwner.LocalClientId}][{name}] Server - " +

Check warning on line 3663 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L3663

Added line #L3663 was not covered by tests
$"client scene mismatch detected! Client-side scene handle ({SceneOriginHandle}) for scene ({gameObject.scene.name})" +
$"has no associated server side (network) scene handle!");
}

Check warning on line 3666 in com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L3666

Added line #L3666 was not covered by tests
OnMigratedToNewScene?.Invoke();

// Only the authority side will notify clients of non-parented NetworkObject scene changes
Expand Down
40 changes: 27 additions & 13 deletions com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@
/// <param name="message">The message to log</param>
[HideInCallstack]
public static void LogErrorServer(string message) => s_Log.ErrorServer(new Context(LogLevel.Error, message, true));
[HideInCallstack]
internal static void LogErrorServer(Context context) => s_Log.ErrorServer(context);

Check warning on line 107 in com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs#L107

Added line #L107 was not covered by tests

internal static LogType GetMessageLogType(UnityEngine.LogType engineLogType)
{
Expand All @@ -115,14 +117,14 @@
};
}


private const string k_SenderId = "SenderId";
internal static Context BuildContextForServerMessage([NotNull] NetworkManager networkManager, LogLevel level, ulong senderId, string message)
{
var ctx = new Context(level, message, true).AddInfo(k_SenderId, senderId);
if (TryGetNetworkObjectName(networkManager, message, out var name))
var ctx = new Context(level, message, true).AddTag("Received log from client").AddInfo(k_SenderId, senderId);
var networkObject = TryGetNetworkObject(networkManager, message);
if (networkObject != null)
{
ctx.AddTag(name);
ctx.AddNetworkObject(networkObject);
}
return ctx;
}
Expand All @@ -135,29 +137,41 @@
None
}

private static readonly Regex k_GlobalObjectIdHash = new($@"\[{nameof(NetworkObject.GlobalObjectIdHash)}=(\d+)\]", RegexOptions.Compiled);
private static readonly Regex k_NetworkObjectId = new($@"\[{nameof(NetworkObject.NetworkObjectId)}:(\d+)\]", RegexOptions.Compiled);
private static readonly Regex k_GlobalObjectIdHash = new($@"\[{nameof(NetworkObject.GlobalObjectIdHash)}:(\d+)\]", RegexOptions.Compiled);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryGetNetworkObjectName([NotNull] NetworkManager networkManager, string message, out string name)
private static NetworkObject TryGetNetworkObject([NotNull] NetworkManager networkManager, string message)
{
name = null;
if (k_NetworkObjectId.IsMatch(message))
{
var stringId = k_NetworkObjectId.Match(message).Groups[1].Value;
if (ulong.TryParse(stringId, out var networkObjectId) && networkObjectId > 0 && networkManager.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out var networkObject))
{
return networkObject;
}
}

Check warning on line 152 in com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs#L152

Added line #L152 was not covered by tests

if (!k_GlobalObjectIdHash.IsMatch(message))
{
return false;
return null;

Check warning on line 156 in com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs#L156

Added line #L156 was not covered by tests
}

var stringHash = k_GlobalObjectIdHash.Match(message).Groups[1].Value;
if (!ulong.TryParse(stringHash, out var globalObjectIdHash))
{
return false;
return null;

Check warning on line 162 in com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Logging/NetworkLog.cs#L162

Added line #L162 was not covered by tests
}

if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(globalObjectIdHash, out var networkObject))
NetworkObject matchingObject = null;
foreach (var networkObject in networkManager.SpawnManager.SpawnedObjectsList)
{
return false;
if (networkObject.GlobalObjectIdHash == globalObjectIdHash)
{
matchingObject = networkObject;
}
}

name = networkObject.name;
return true;
return matchingObject;
}

[HideInCallstack]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -907,10 +907,7 @@
// If not, then there is an issue (user possibly didn't register the prefab properly?)
if (networkPrefabReference == null)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
{
NetworkLog.LogErrorServer($"[{nameof(globalObjectIdHash)}={globalObjectIdHash}] Failed to create object locally. {nameof(NetworkPrefab)} could not be found. Is the prefab registered with {NetworkManager.name}?");
}
NetworkManager.Log.ErrorServer(new Context(LogLevel.Error, $"Failed to create object locally. {nameof(NetworkPrefab)} could not be found. Is the prefab registered with this {nameof(NetworkManager)}").AddInfo(nameof(NetworkObject.GlobalObjectIdHash), globalObjectIdHash).AddTag(NetworkManager.name));
return null;
}

Expand Down Expand Up @@ -957,6 +954,7 @@
/// <remarks>
/// For most cases this is client-side only, except when the server is spawning a player.
/// </remarks>
[return: MaybeNull]
internal NetworkObject CreateLocalNetworkObject(NetworkObject.SerializedObject serializedObject, byte[] instantiationData = null)
{
NetworkObject networkObject = null;
Expand All @@ -977,11 +975,7 @@
networkObject = NetworkManager.SceneManager.GetSceneRelativeInSceneNetworkObject(globalObjectIdHash, serializedObject.NetworkSceneHandle);
if (networkObject == null)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
{
NetworkLog.LogError($"{nameof(NetworkPrefab)} hash was not found! In-Scene placed {nameof(NetworkObject)} soft synchronization failure for Hash: {globalObjectIdHash}!");
}

NetworkLog.LogErrorServer(new Context(LogLevel.Error, $"{nameof(NetworkPrefab)} hash was not found! In-Scene placed {nameof(NetworkObject)} soft synchronization failure!").AddInfo(nameof(NetworkObject.GlobalObjectIdHash), globalObjectIdHash));

Check warning on line 978 in com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs#L978

Added line #L978 was not covered by tests
return null;
}

Expand Down Expand Up @@ -1122,7 +1116,14 @@
return false;
}

if (!sceneObject && NetworkManager.LogLevel <= LogLevel.Error)
if (playerObject && networkObject.InScenePlaced)
{
NetworkLog.LogError(new Context(LogLevel.Developer, "Player prefab is marked as belonging to a scene. This may cause issues.").AddNetworkObject(networkObject).AddInfo("SceneName", networkObject.SceneOrigin.name));
networkObject.InScenePlaced = false;
}

Check warning on line 1123 in com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs#L1120-L1123

Added lines #L1120 - L1123 were not covered by tests
NetworkLog.InternalAssert(sceneObject == networkObject.InScenePlaced, "Legacy sceneObject value should match calculated InScenePlaced value.");

if (!networkObject.InScenePlaced && NetworkManager.LogLevel <= LogLevel.Error)
{
var networkObjectChildren = networkObject.GetComponentsInChildren<NetworkObject>();
if (networkObjectChildren.Length > 1)
Expand All @@ -1137,7 +1138,7 @@
networkObject.NetworkManagerOwner = NetworkManager;
networkObject.InvokeBehaviourNetworkPreSpawn();

if (NetworkManager.DistributedAuthorityMode && NetworkManager.NetworkConfig.EnableSceneManagement && sceneObject)
if (NetworkManager.DistributedAuthorityMode && NetworkManager.NetworkConfig.EnableSceneManagement && networkObject.InScenePlaced)
{
networkObject.SceneOriginHandle = networkObject.gameObject.scene.handle;
networkObject.NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[networkObject.gameObject.scene.handle];
Expand Down Expand Up @@ -1175,10 +1176,7 @@
{
if (SpawnedObjects.ContainsKey(serializedObject.NetworkObjectId))
{
if (NetworkManager.LogLevel <= LogLevel.Error)
{
NetworkLog.LogWarning($"Trying to spawn a {nameof(NetworkObject)} with a {nameof(NetworkObject.NetworkObjectId)} of {serializedObject.NetworkObjectId} but an object with that id is already in the spawned list. This should not happen!");
}
NetworkManager.Log.Warning(new Context(LogLevel.Error, $"Trying to spawn a {nameof(NetworkObject)} but an object with that {nameof(NetworkObject.NetworkObjectId)} is already in the spawned list. This should not happen!"));

Check warning on line 1179 in com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs#L1179

Added line #L1179 was not covered by tests
networkObject = null;
return false;
}
Expand All @@ -1195,14 +1193,11 @@
// Log the error that the NetworkObject failed to construct
if (networkObject == null)
{
if (NetworkManager.LogLevel <= LogLevel.Normal)
{
NetworkLog.LogError($"[{nameof(NetworkObject.GlobalObjectIdHash)}={serializedObject.Hash}] Failed to spawn {nameof(NetworkObject)}!");
}

NetworkManager.Log.ErrorServer(new Context(LogLevel.Normal, $"Failed to spawn {nameof(NetworkObject)}!").AddInfo(nameof(NetworkObject.GlobalObjectIdHash), serializedObject.Hash));
return false;
}

networkObject.InScenePlaced = serializedObject.IsSceneObject;
networkObject.NetworkManagerOwner = NetworkManager;

// This will get set again when the NetworkObject is spawned locally, but we set it here ahead of spawning
Expand All @@ -1227,11 +1222,7 @@

if (networkObject.IsSpawned)
{
if (NetworkManager.LogLevel <= LogLevel.Error)
{
NetworkLog.LogErrorServer($"[{networkObject.name}] Object-{networkObject.NetworkObjectId} is already spawned!");
}

NetworkManager.Log.ErrorServer(new Context(LogLevel.Normal, $"{nameof(NetworkObject)} is already spawned!").AddNetworkObject(networkObject));

Check warning on line 1225 in com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs#L1225

Added line #L1225 was not covered by tests
// Mark the spawn as a success if the object is already spawned
return true;
}
Expand Down
Loading