com.unity.netcode.gameobjects@1.5.1

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).

## [1.5.1] - 2023-06-07

### Added

- Added support for serializing `NativeArray<>` and `NativeList<>` in `FastBufferReader`/`FastBufferWriter`, `BufferSerializer`, `NetworkVariable`, and RPCs. (To use `NativeList<>`, add `UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT` to your Scripting Define Symbols in `Project Settings > Player`) (#2375)
- The location of the automatically-created default network prefab list can now be configured (#2544)
- Added: Message size limits (max single message and max fragmented message) can now be set using NetworkManager.MaximumTransmissionUnitSize and NetworkManager.MaximumFragmentedMessageSize for transports that don't work with the default values (#2530)
- Added `NetworkObject.SpawnWithObservers` property (default is true) that when set to false will spawn a `NetworkObject` with no observers and will not be spawned on any client until `NetworkObject.NetworkShow` is invoked. (#2568)

### Fixed

- Fixed: Fixed a null reference in codegen in some projects (#2581)
- Fixed issue where the `OnClientDisconnected` client identifier was incorrect after a pending client connection was denied. (#2569)
- Fixed warning "Runtime Network Prefabs was not empty at initialization time." being erroneously logged when no runtime network prefabs had been added (#2565)
- Fixed issue where some temporary debug console logging was left in a merged PR. (#2562)
- Fixed the "Generate Default Network Prefabs List" setting not loading correctly and always reverting to being checked. (#2545)
- Fixed issue where users could not use NetworkSceneManager.VerifySceneBeforeLoading to exclude runtime generated scenes from client synchronization. (#2550)
- Fixed missing value on `NetworkListEvent` for `EventType.RemoveAt` events.  (#2542,#2543)
- Fixed issue where parenting a NetworkTransform under a transform with a scale other than Vector3.one would result in incorrect values on non-authoritative instances. (#2538)
- Fixed issue where a server would include scene migrated and then despawned NetworkObjects to a client that was being synchronized. (#2532)
- Fixed the inspector throwing exceptions when attempting to render `NetworkVariable`s of enum types. (#2529)
- Making a `NetworkVariable` with an `INetworkSerializable` type that doesn't meet the `new()` constraint will now create a compile-time error instead of an editor crash (#2528)
- Fixed Multiplayer Tools package installation docs page link on the NetworkManager popup. (#2526)
- Fixed an exception and error logging when two different objects are shown and hidden on the same frame (#2524)
- Fixed a memory leak in `UnityTransport` that occurred if `StartClient` failed. (#2518)
- Fixed issue where a client could throw an exception if abruptly disconnected from a network session with one or more spawned `NetworkObject`(s). (#2510)
- Fixed issue where invalid endpoint addresses were not being detected and returning false from NGO UnityTransport. (#2496)
- Fixed some errors that could occur if a connection is lost and the loss is detected when attempting to write to the socket. (#2495)

## Changed

- Adding network prefabs before NetworkManager initialization is now supported. (#2565)
- Connecting clients being synchronized now switch to the server's active scene before spawning and synchronizing NetworkObjects. (#2532)
- Updated `UnityTransport` dependency on `com.unity.transport` to 1.3.4. (#2533)
- Improved performance of NetworkBehaviour initialization by replacing reflection when initializing NetworkVariables with compile-time code generation, which should help reduce hitching during additive scene loads. (#2522)
This commit is contained in:
Unity Technologies
2023-06-07 00:00:00 +00:00
parent b5abc3ff7c
commit 4d70c198bd
119 changed files with 11328 additions and 3164 deletions

View File

@@ -337,7 +337,7 @@ namespace Unity.Netcode
return;
}
else // Warn users if they are changing this after there are clients already connected and synchronized
if (networkManager.ConnectedClientsIds.Count > (networkManager.IsServer ? 0 : 1) && sceneManager.ClientSynchronizationMode != mode)
if (networkManager.ConnectedClientsIds.Count > (networkManager.IsHost ? 1 : 0) && sceneManager.ClientSynchronizationMode != mode)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
{

View File

@@ -524,7 +524,7 @@ namespace Unity.Netcode
/// </summary>
internal Dictionary<uint, SceneEventData> SceneEventDataStore;
private NetworkManager m_NetworkManager { get; }
internal readonly NetworkManager NetworkManager;
// Keep track of this scene until the NetworkSceneManager is destroyed.
internal Scene DontDestroyOnLoadScene;
@@ -575,7 +575,7 @@ namespace Unity.Netcode
/// <returns>SceneEventData instance</returns>
internal SceneEventData BeginSceneEvent()
{
var sceneEventData = new SceneEventData(m_NetworkManager);
var sceneEventData = new SceneEventData(NetworkManager);
SceneEventDataStore.Add(sceneEventData.SceneEventId, sceneEventData);
return sceneEventData;
}
@@ -720,18 +720,18 @@ namespace Unity.Netcode
/// <param name="mode"><see cref="LoadSceneMode"/> for initial client synchronization</param>
public void SetClientSynchronizationMode(LoadSceneMode mode)
{
var networkManager = m_NetworkManager;
var networkManager = NetworkManager;
SceneManagerHandler.SetClientSynchronizationMode(ref networkManager, mode);
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="networkManager">one <see cref="NetworkManager"/> instance per <see cref="NetworkSceneManager"/> instance</param>
/// <param name="networkManager">one <see cref="Netcode.NetworkManager"/> instance per <see cref="NetworkSceneManager"/> instance</param>
/// <param name="sceneEventDataPoolSize">maximum <see cref="SceneEventData"/> pool size</param>
internal NetworkSceneManager(NetworkManager networkManager)
{
m_NetworkManager = networkManager;
NetworkManager = networkManager;
SceneEventDataStore = new Dictionary<uint, SceneEventData>();
// Generates the scene name to hash value
@@ -750,7 +750,7 @@ namespace Unity.Netcode
private void SceneManager_ActiveSceneChanged(Scene current, Scene next)
{
// If no clients are connected, then don't worry about notifications
if (!(m_NetworkManager.ConnectedClientsIds.Count > (m_NetworkManager.IsHost ? 1 : 0)))
if (!(NetworkManager.ConnectedClientsIds.Count > (NetworkManager.IsHost ? 1 : 0)))
{
return;
}
@@ -771,7 +771,7 @@ namespace Unity.Netcode
var sceneEvent = BeginSceneEvent();
sceneEvent.SceneEventType = SceneEventType.ActiveSceneChanged;
sceneEvent.ActiveSceneHash = BuildIndexToHash[next.buildIndex];
SendSceneEventData(sceneEvent.SceneEventId, m_NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
SendSceneEventData(sceneEvent.SceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
EndSceneEvent(sceneEvent.SceneEventId);
}
}
@@ -786,9 +786,18 @@ namespace Unity.Netcode
/// <returns>true (Valid) or false (Invalid)</returns>
internal bool ValidateSceneBeforeLoading(uint sceneHash, LoadSceneMode loadSceneMode)
{
var validated = true;
var sceneName = SceneNameFromHash(sceneHash);
var sceneIndex = SceneUtility.GetBuildIndexByScenePath(sceneName);
return ValidateSceneBeforeLoading(sceneIndex, sceneName, loadSceneMode);
}
/// <summary>
/// Overloaded version that is invoked by <see cref="ValidateSceneBeforeLoading"/> and <see cref="SynchronizeNetworkObjects"/>.
/// This specifically is to allow runtime generated scenes to be excluded by the server during synchronization.
/// </summary>
internal bool ValidateSceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
{
var validated = true;
if (VerifySceneBeforeLoading != null)
{
validated = VerifySceneBeforeLoading.Invoke(sceneIndex, sceneName, loadSceneMode);
@@ -796,9 +805,9 @@ namespace Unity.Netcode
if (!validated && !m_DisableValidationWarningMessages)
{
var serverHostorClient = "Client";
if (m_NetworkManager.IsServer)
if (NetworkManager.IsServer)
{
serverHostorClient = m_NetworkManager.IsHost ? "Host" : "Server";
serverHostorClient = NetworkManager.IsHost ? "Host" : "Server";
}
Debug.LogWarning($"Scene {sceneName} of Scenes in Build Index {sceneIndex} being loaded in {loadSceneMode} mode failed validation on the {serverHostorClient}!");
@@ -837,7 +846,7 @@ namespace Unity.Netcode
if (!ScenesLoaded.ContainsKey(sceneLoaded.handle))
{
ScenesLoaded.Add(sceneLoaded.handle, sceneLoaded);
SceneManagerHandler.StartTrackingScene(sceneLoaded, true, m_NetworkManager);
SceneManagerHandler.StartTrackingScene(sceneLoaded, true, NetworkManager);
return sceneLoaded;
}
}
@@ -886,7 +895,7 @@ namespace Unity.Netcode
// Most common scenario for DontDestroyOnLoad is when NetworkManager is set to not be destroyed
if (serverSceneHandle == DontDestroyOnLoadScene.handle)
{
SceneBeingSynchronized = m_NetworkManager.gameObject.scene;
SceneBeingSynchronized = NetworkManager.gameObject.scene;
return;
}
else
@@ -940,9 +949,9 @@ namespace Unity.Netcode
{
EventData = SceneEventDataStore[sceneEventId]
};
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, targetClientIds);
var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, targetClientIds);
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(targetClientIds, (uint)SceneEventDataStore[sceneEventId].SceneEventType, SceneNameFromHash(SceneEventDataStore[sceneEventId].SceneHash), size);
NetworkManager.NetworkMetrics.TrackSceneEventSent(targetClientIds, (uint)SceneEventDataStore[sceneEventId].SceneEventType, SceneNameFromHash(SceneEventDataStore[sceneEventId].SceneHash), size);
}
/// <summary>
@@ -952,16 +961,16 @@ namespace Unity.Netcode
/// <returns></returns>
private SceneEventProgress ValidateSceneEventUnloading(Scene scene)
{
if (!m_NetworkManager.IsServer)
if (!NetworkManager.IsServer)
{
throw new NotServerException("Only server can start a scene event!");
}
if (!m_NetworkManager.NetworkConfig.EnableSceneManagement)
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
{
//Log message about enabling SceneManagement
throw new Exception(
$"{nameof(NetworkConfig.EnableSceneManagement)} flag is not enabled in the {nameof(NetworkManager)}'s {nameof(NetworkConfig)}. " +
$"{nameof(NetworkConfig.EnableSceneManagement)} flag is not enabled in the {nameof(Netcode.NetworkManager)}'s {nameof(NetworkConfig)}. " +
$"Please set {nameof(NetworkConfig.EnableSceneManagement)} flag to true before calling {nameof(LoadScene)} or {nameof(UnloadScene)}.");
}
@@ -981,15 +990,15 @@ namespace Unity.Netcode
/// <returns></returns>
private SceneEventProgress ValidateSceneEventLoading(string sceneName)
{
if (!m_NetworkManager.IsServer)
if (!NetworkManager.IsServer)
{
throw new NotServerException("Only server can start a scene event!");
}
if (!m_NetworkManager.NetworkConfig.EnableSceneManagement)
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
{
//Log message about enabling SceneManagement
throw new Exception(
$"{nameof(NetworkConfig.EnableSceneManagement)} flag is not enabled in the {nameof(NetworkManager)}'s {nameof(NetworkConfig)}. " +
$"{nameof(NetworkConfig.EnableSceneManagement)} flag is not enabled in the {nameof(Netcode.NetworkManager)}'s {nameof(NetworkConfig)}. " +
$"Please set {nameof(NetworkConfig.EnableSceneManagement)} flag to true before calling {nameof(LoadScene)} or {nameof(UnloadScene)}.");
}
@@ -1017,7 +1026,7 @@ namespace Unity.Netcode
return new SceneEventProgress(null, SceneEventProgressStatus.InvalidSceneName);
}
var sceneEventProgress = new SceneEventProgress(m_NetworkManager)
var sceneEventProgress = new SceneEventProgress(NetworkManager)
{
SceneHash = SceneHashFromNameOrPath(sceneName)
};
@@ -1052,10 +1061,10 @@ namespace Unity.Netcode
{
EventData = sceneEventData
};
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, m_NetworkManager.ConnectedClientsIds);
var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, NetworkManager.ConnectedClientsIds);
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(
m_NetworkManager.ConnectedClientsIds,
NetworkManager.NetworkMetrics.TrackSceneEventSent(
NetworkManager.ConnectedClientsIds,
(uint)sceneEventProgress.SceneEventType,
SceneNameFromHash(sceneEventProgress.SceneHash),
size);
@@ -1116,7 +1125,7 @@ namespace Unity.Netcode
// Any NetworkObjects marked to not be destroyed with a scene and reside within the scene about to be unloaded
// should be migrated temporarily into the DDOL, once the scene is unloaded they will be migrated into the
// currently active scene.
var networkManager = m_NetworkManager;
var networkManager = NetworkManager;
SceneManagerHandler.MoveObjectsFromSceneToDontDestroyOnLoad(ref networkManager, scene);
var sceneEventData = BeginSceneEvent();
@@ -1179,18 +1188,18 @@ namespace Unity.Netcode
// Any NetworkObjects marked to not be destroyed with a scene and reside within the scene about to be unloaded
// should be migrated temporarily into the DDOL, once the scene is unloaded they will be migrated into the
// currently active scene.
var networkManager = m_NetworkManager;
var networkManager = NetworkManager;
SceneManagerHandler.MoveObjectsFromSceneToDontDestroyOnLoad(ref networkManager, scene);
m_IsSceneEventActive = true;
var sceneEventProgress = new SceneEventProgress(m_NetworkManager)
var sceneEventProgress = new SceneEventProgress(NetworkManager)
{
SceneEventId = sceneEventData.SceneEventId,
OnSceneEventCompleted = OnSceneUnloaded
};
var sceneUnload = SceneManagerHandler.UnloadSceneAsync(scene, sceneEventProgress);
SceneManagerHandler.StopTrackingScene(sceneHandle, sceneName, m_NetworkManager);
SceneManagerHandler.StopTrackingScene(sceneHandle, sceneName, NetworkManager);
// Remove our server to scene handle lookup
if (!RemoveServerClientSceneHandle(sceneEventData.SceneHandle, sceneHandle))
@@ -1206,10 +1215,10 @@ namespace Unity.Netcode
SceneEventType = sceneEventData.SceneEventType,
LoadSceneMode = LoadSceneMode.Additive, // The only scenes unloaded are scenes that were additively loaded
SceneName = sceneName,
ClientId = m_NetworkManager.LocalClientId // Server sent this message to the client, but client is executing it
ClientId = NetworkManager.LocalClientId // Server sent this message to the client, but client is executing it
});
OnUnload?.Invoke(m_NetworkManager.LocalClientId, sceneName, sceneUnload);
OnUnload?.Invoke(NetworkManager.LocalClientId, sceneName, sceneUnload);
}
/// <summary>
@@ -1219,7 +1228,7 @@ namespace Unity.Netcode
private void OnSceneUnloaded(uint sceneEventId)
{
// If we are shutdown or about to shutdown, then ignore this event
if (!m_NetworkManager.IsListening || m_NetworkManager.ShutdownInProgress)
if (!NetworkManager.IsListening || NetworkManager.ShutdownInProgress)
{
return;
}
@@ -1229,15 +1238,15 @@ namespace Unity.Netcode
var sceneEventData = SceneEventDataStore[sceneEventId];
// First thing we do, if we are a server, is to send the unload scene event.
if (m_NetworkManager.IsServer)
if (NetworkManager.IsServer)
{
// Server sends the unload scene notification after unloading because it will despawn all scene relative in-scene NetworkObjects
// If we send this event to all clients before the server is finished unloading they will get warning about an object being
// despawned that no longer exists
SendSceneEventData(sceneEventId, m_NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
SendSceneEventData(sceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
//Only if we are a host do we want register having loaded for the associated SceneEventProgress
if (SceneEventProgressTracking.ContainsKey(sceneEventData.SceneEventProgressId) && m_NetworkManager.IsHost)
if (SceneEventProgressTracking.ContainsKey(sceneEventData.SceneEventProgressId) && NetworkManager.IsHost)
{
SceneEventProgressTracking[sceneEventData.SceneEventProgressId].ClientFinishedSceneEvent(NetworkManager.ServerClientId);
}
@@ -1252,13 +1261,13 @@ namespace Unity.Netcode
SceneEventType = sceneEventData.SceneEventType,
LoadSceneMode = sceneEventData.LoadSceneMode,
SceneName = SceneNameFromHash(sceneEventData.SceneHash),
ClientId = m_NetworkManager.IsServer ? NetworkManager.ServerClientId : m_NetworkManager.LocalClientId
ClientId = NetworkManager.IsServer ? NetworkManager.ServerClientId : NetworkManager.LocalClientId
});
OnUnloadComplete?.Invoke(m_NetworkManager.LocalClientId, SceneNameFromHash(sceneEventData.SceneHash));
OnUnloadComplete?.Invoke(NetworkManager.LocalClientId, SceneNameFromHash(sceneEventData.SceneHash));
// Clients send a notification back to the server they have completed the unload scene event
if (!m_NetworkManager.IsServer)
if (!NetworkManager.IsServer)
{
SendSceneEventData(sceneEventId, new ulong[] { NetworkManager.ServerClientId });
}
@@ -1288,7 +1297,7 @@ namespace Unity.Netcode
// Validate the scene as well as ignore the DDOL (which will have a negative buildIndex)
if (currentActiveScene.name != keyHandleEntry.Value.name && keyHandleEntry.Value.buildIndex >= 0)
{
var sceneEventProgress = new SceneEventProgress(m_NetworkManager)
var sceneEventProgress = new SceneEventProgress(NetworkManager)
{
SceneEventId = sceneEventId,
OnSceneEventCompleted = EmptySceneUnloadedOperation
@@ -1299,7 +1308,7 @@ namespace Unity.Netcode
}
// clear out our scenes loaded list
ScenesLoaded.Clear();
SceneManagerHandler.ClearSceneTracking(m_NetworkManager);
SceneManagerHandler.ClearSceneTracking(NetworkManager);
}
/// <summary>
@@ -1348,7 +1357,7 @@ namespace Unity.Netcode
IsSpawnedObjectsPendingInDontDestroyOnLoad = true;
// Destroy current scene objects before switching.
m_NetworkManager.SpawnManager.ServerDestroySpawnedSceneObjects();
NetworkManager.SpawnManager.ServerDestroySpawnedSceneObjects();
// Preserve the objects that should not be destroyed during the scene event
MoveObjectsToDontDestroyOnLoad();
@@ -1390,7 +1399,7 @@ namespace Unity.Netcode
internal static void RegisterScene(NetworkSceneManager networkSceneManager, Scene scene, LoadSceneMode loadSceneMode, AsyncOperation asyncOperation = null)
{
var networkManager = networkSceneManager.m_NetworkManager;
var networkManager = networkSceneManager.NetworkManager;
if (!s_Instances.ContainsKey(networkManager))
{
s_Instances.Add(networkManager, new List<SceneUnloadEventHandler>());
@@ -1401,11 +1410,11 @@ namespace Unity.Netcode
private static void SceneUnloadComplete(SceneUnloadEventHandler sceneUnloadEventHandler)
{
if (sceneUnloadEventHandler == null || sceneUnloadEventHandler.m_NetworkSceneManager == null || sceneUnloadEventHandler.m_NetworkSceneManager.m_NetworkManager == null)
if (sceneUnloadEventHandler == null || sceneUnloadEventHandler.m_NetworkSceneManager == null || sceneUnloadEventHandler.m_NetworkSceneManager.NetworkManager == null)
{
return;
}
var networkManager = sceneUnloadEventHandler.m_NetworkSceneManager.m_NetworkManager;
var networkManager = sceneUnloadEventHandler.m_NetworkSceneManager.NetworkManager;
if (s_Instances.ContainsKey(networkManager))
{
s_Instances[networkManager].Remove(sceneUnloadEventHandler);
@@ -1449,7 +1458,7 @@ namespace Unity.Netcode
{
if (m_Scene.handle == scene.handle && !m_ShuttingDown)
{
if (m_NetworkSceneManager != null && m_NetworkSceneManager.m_NetworkManager != null)
if (m_NetworkSceneManager != null && m_NetworkSceneManager.NetworkManager != null)
{
m_NetworkSceneManager.OnSceneEvent?.Invoke(new SceneEvent()
{
@@ -1484,7 +1493,7 @@ namespace Unity.Netcode
ClientId = clientId
});
m_NetworkSceneManager.OnUnload?.Invoke(networkSceneManager.m_NetworkManager.LocalClientId, m_Scene.name, null);
m_NetworkSceneManager.OnUnload?.Invoke(networkSceneManager.NetworkManager.LocalClientId, m_Scene.name, null);
}
}
@@ -1527,7 +1536,7 @@ namespace Unity.Netcode
SceneUnloadEventHandler.RegisterScene(this, SceneManager.GetActiveScene(), LoadSceneMode.Single);
}
var sceneEventProgress = new SceneEventProgress(m_NetworkManager)
var sceneEventProgress = new SceneEventProgress(NetworkManager)
{
SceneEventId = sceneEventId,
OnSceneEventCompleted = OnSceneLoaded
@@ -1540,10 +1549,10 @@ namespace Unity.Netcode
SceneEventType = sceneEventData.SceneEventType,
LoadSceneMode = sceneEventData.LoadSceneMode,
SceneName = sceneName,
ClientId = m_NetworkManager.LocalClientId
ClientId = NetworkManager.LocalClientId
});
OnLoad?.Invoke(m_NetworkManager.LocalClientId, sceneName, sceneEventData.LoadSceneMode, sceneLoad);
OnLoad?.Invoke(NetworkManager.LocalClientId, sceneName, sceneEventData.LoadSceneMode, sceneLoad);
}
/// <summary>
@@ -1553,7 +1562,7 @@ namespace Unity.Netcode
private void OnSceneLoaded(uint sceneEventId)
{
// If we are shutdown or about to shutdown, then ignore this event
if (!m_NetworkManager.IsListening || m_NetworkManager.ShutdownInProgress)
if (!NetworkManager.IsListening || NetworkManager.ShutdownInProgress)
{
return;
}
@@ -1586,7 +1595,7 @@ namespace Unity.Netcode
// not destroy temporary scene are moved into the active scene
IsSpawnedObjectsPendingInDontDestroyOnLoad = false;
if (m_NetworkManager.IsServer)
if (NetworkManager.IsServer)
{
OnServerLoadedScene(sceneEventId, nextScene);
}
@@ -1618,8 +1627,8 @@ namespace Unity.Netcode
if (!keyValuePairBySceneHandle.Value.IsPlayerObject)
{
// All in-scene placed NetworkObjects default to being owned by the server
m_NetworkManager.SpawnManager.SpawnNetworkObjectLocally(keyValuePairBySceneHandle.Value,
m_NetworkManager.SpawnManager.GetNetworkObjectId(), true, false, NetworkManager.ServerClientId, true);
NetworkManager.SpawnManager.SpawnNetworkObjectLocally(keyValuePairBySceneHandle.Value,
NetworkManager.SpawnManager.GetNetworkObjectId(), true, false, NetworkManager.ServerClientId, true);
}
}
}
@@ -1631,9 +1640,9 @@ namespace Unity.Netcode
sceneEventData.SceneHandle = scene.handle;
// Send all clients the scene load event
for (int j = 0; j < m_NetworkManager.ConnectedClientsList.Count; j++)
for (int j = 0; j < NetworkManager.ConnectedClientsList.Count; j++)
{
var clientId = m_NetworkManager.ConnectedClientsList[j].ClientId;
var clientId = NetworkManager.ConnectedClientsList[j].ClientId;
if (clientId != NetworkManager.ServerClientId)
{
sceneEventData.TargetClientId = clientId;
@@ -1641,8 +1650,8 @@ namespace Unity.Netcode
{
EventData = sceneEventData
};
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, clientId);
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEventData.SceneEventType, scene.name, size);
var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, clientId);
NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEventData.SceneEventType, scene.name, size);
}
}
@@ -1660,7 +1669,7 @@ namespace Unity.Netcode
OnLoadComplete?.Invoke(NetworkManager.ServerClientId, SceneNameFromHash(sceneEventData.SceneHash), sceneEventData.LoadSceneMode);
//Second, only if we are a host do we want register having loaded for the associated SceneEventProgress
if (SceneEventProgressTracking.ContainsKey(sceneEventData.SceneEventProgressId) && m_NetworkManager.IsHost)
if (SceneEventProgressTracking.ContainsKey(sceneEventData.SceneEventProgressId) && NetworkManager.IsHost)
{
SceneEventProgressTracking[sceneEventData.SceneEventProgressId].ClientFinishedSceneEvent(NetworkManager.ServerClientId);
}
@@ -1686,11 +1695,11 @@ namespace Unity.Netcode
SceneEventType = SceneEventType.LoadComplete,
LoadSceneMode = sceneEventData.LoadSceneMode,
SceneName = SceneNameFromHash(sceneEventData.SceneHash),
ClientId = m_NetworkManager.LocalClientId,
ClientId = NetworkManager.LocalClientId,
Scene = scene,
});
OnLoadComplete?.Invoke(m_NetworkManager.LocalClientId, SceneNameFromHash(sceneEventData.SceneHash), sceneEventData.LoadSceneMode);
OnLoadComplete?.Invoke(NetworkManager.LocalClientId, SceneNameFromHash(sceneEventData.SceneHash), sceneEventData.LoadSceneMode);
EndSceneEvent(sceneEventId);
}
@@ -1713,7 +1722,7 @@ namespace Unity.Netcode
internal void SynchronizeNetworkObjects(ulong clientId)
{
// Update the clients
m_NetworkManager.SpawnManager.UpdateObservedNetworkObjects(clientId);
NetworkManager.SpawnManager.UpdateObservedNetworkObjects(clientId);
var sceneEventData = BeginSceneEvent();
sceneEventData.ClientSynchronizationMode = ClientSynchronizationMode;
@@ -1744,24 +1753,22 @@ namespace Unity.Netcode
continue;
}
var sceneHash = SceneHashFromNameOrPath(scene.path);
// This would depend upon whether we are additive or not
// If we are the base scene, then we set the root scene index;
if (activeScene == scene)
{
if (!ValidateSceneBeforeLoading(sceneHash, sceneEventData.LoadSceneMode))
if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode))
{
continue;
}
sceneEventData.SceneHash = sceneHash;
sceneEventData.SceneHash = SceneHashFromNameOrPath(scene.path);
sceneEventData.SceneHandle = scene.handle;
}
else if (!ValidateSceneBeforeLoading(sceneHash, LoadSceneMode.Additive))
else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
{
continue;
}
sceneEventData.AddSceneToSynchronize(sceneHash, scene.handle);
sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), scene.handle);
}
sceneEventData.AddSpawnedNetworkObjects();
@@ -1771,8 +1778,8 @@ namespace Unity.Netcode
{
EventData = sceneEventData
};
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, clientId);
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEventData.SceneEventType, "", size);
var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, clientId);
NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEventData.SceneEventType, "", size);
// Notify the local server that the client has been sent the synchronize event
OnSceneEvent?.Invoke(new SceneEvent()
@@ -1811,17 +1818,17 @@ namespace Unity.Netcode
OnSceneEvent?.Invoke(new SceneEvent()
{
SceneEventType = SceneEventType.Synchronize,
ClientId = m_NetworkManager.LocalClientId,
ClientId = NetworkManager.LocalClientId,
});
OnSynchronize?.Invoke(m_NetworkManager.LocalClientId);
OnSynchronize?.Invoke(NetworkManager.LocalClientId);
}
// Always check to see if the scene needs to be validated
if (!ValidateSceneBeforeLoading(sceneHash, loadSceneMode))
{
HandleClientSceneEvent(sceneEventId);
if (m_NetworkManager.LogLevel == LogLevel.Developer)
if (NetworkManager.LogLevel == LogLevel.Developer)
{
NetworkLog.LogInfo($"Client declined to load the scene {sceneName}, continuing with synchronization.");
}
@@ -1835,12 +1842,12 @@ namespace Unity.Netcode
// it should pass through to post load processing (ClientLoadedSynchronization).
// For ClientSynchronizationMode LoadSceneMode.Additive, if the scene is already loaded or the active scene is the scene to be loaded (does not require it to
// be the initial primary scene) then go ahead and pass through to post load processing (ClientLoadedSynchronization).
var shouldPassThrough = SceneManagerHandler.ClientShouldPassThrough(sceneName, sceneHash == sceneEventData.SceneHash, ClientSynchronizationMode, m_NetworkManager);
var shouldPassThrough = SceneManagerHandler.ClientShouldPassThrough(sceneName, sceneHash == sceneEventData.SceneHash, ClientSynchronizationMode, NetworkManager);
if (!shouldPassThrough)
{
// If not, then load the scene
var sceneEventProgress = new SceneEventProgress(m_NetworkManager)
var sceneEventProgress = new SceneEventProgress(NetworkManager)
{
SceneEventId = sceneEventId,
OnSceneEventCompleted = ClientLoadedSynchronization
@@ -1854,10 +1861,10 @@ namespace Unity.Netcode
SceneEventType = SceneEventType.Load,
LoadSceneMode = loadSceneMode,
SceneName = sceneName,
ClientId = m_NetworkManager.LocalClientId,
ClientId = NetworkManager.LocalClientId,
});
OnLoad?.Invoke(m_NetworkManager.LocalClientId, sceneName, loadSceneMode, sceneLoad);
OnLoad?.Invoke(NetworkManager.LocalClientId, sceneName, loadSceneMode, sceneLoad);
}
else
{
@@ -1875,7 +1882,7 @@ namespace Unity.Netcode
{
var sceneEventData = SceneEventDataStore[sceneEventId];
var sceneName = SceneNameFromHash(sceneEventData.ClientSceneHash);
var nextScene = SceneManagerHandler.GetSceneFromLoadedScenes(sceneName, m_NetworkManager);
var nextScene = SceneManagerHandler.GetSceneFromLoadedScenes(sceneName, NetworkManager);
if (!nextScene.IsValid())
{
nextScene = GetAndAddNewlyLoadedSceneByName(sceneName);
@@ -1915,9 +1922,9 @@ namespace Unity.Netcode
{
EventData = responseSceneEventData
};
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, NetworkManager.ServerClientId);
var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, NetworkManager.ServerClientId);
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(NetworkManager.ServerClientId, (uint)responseSceneEventData.SceneEventType, sceneName, size);
NetworkManager.NetworkMetrics.TrackSceneEventSent(NetworkManager.ServerClientId, (uint)responseSceneEventData.SceneEventType, sceneName, size);
EndSceneEvent(responseSceneEventData.SceneEventId);
@@ -1928,10 +1935,10 @@ namespace Unity.Netcode
LoadSceneMode = loadSceneMode,
SceneName = sceneName,
Scene = nextScene,
ClientId = m_NetworkManager.LocalClientId,
ClientId = NetworkManager.LocalClientId,
});
OnLoadComplete?.Invoke(m_NetworkManager.LocalClientId, sceneName, loadSceneMode);
OnLoadComplete?.Invoke(NetworkManager.LocalClientId, sceneName, loadSceneMode);
// Check to see if we still have scenes to load and synchronize with
HandleClientSceneEvent(sceneEventId);
@@ -1944,7 +1951,7 @@ namespace Unity.Netcode
/// </summary>
private void SynchronizeNetworkObjectScene()
{
foreach (var networkObject in m_NetworkManager.SpawnManager.SpawnedObjectsList)
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
@@ -1969,9 +1976,9 @@ namespace Unity.Netcode
SceneManager.MoveGameObjectToScene(networkObject.gameObject, scene);
}
else if (m_NetworkManager.LogLevel <= LogLevel.Normal)
else if (NetworkManager.LogLevel <= LogLevel.Normal)
{
NetworkLog.LogWarningServer($"[Client-{m_NetworkManager.LocalClientId}][{networkObject.gameObject.name}] Server - " +
NetworkLog.LogWarningServer($"[Client-{NetworkManager.LocalClientId}][{networkObject.gameObject.name}] Server - " +
$"client scene mismatch detected! Client-side has no scene loaded with handle ({networkObject.SceneOriginHandle})!");
}
}
@@ -2026,8 +2033,6 @@ namespace Unity.Netcode
{
// Include anything in the DDOL scene
PopulateScenePlacedObjects(DontDestroyOnLoadScene, false);
// Synchronize the NetworkObjects for this scene
sceneEventData.SynchronizeSceneNetworkObjects(m_NetworkManager);
// If needed, set the currently active scene
if (HashToBuildIndex.ContainsKey(sceneEventData.ActiveSceneHash))
@@ -2039,23 +2044,26 @@ namespace Unity.Netcode
}
}
// If needed, migrate dynamically spawned NetworkObjects to the same scene as on the server side
// Spawn and Synchronize all NetworkObjects
sceneEventData.SynchronizeSceneNetworkObjects(NetworkManager);
// If needed, migrate dynamically spawned NetworkObjects to the same scene as they are on the server
SynchronizeNetworkObjectScene();
sceneEventData.SceneEventType = SceneEventType.SynchronizeComplete;
SendSceneEventData(sceneEventId, new ulong[] { NetworkManager.ServerClientId });
// All scenes are synchronized, let the server know we are done synchronizing
m_NetworkManager.IsConnectedClient = true;
NetworkManager.IsConnectedClient = true;
// Client is now synchronized and fully "connected". This also means the client can send "RPCs" at this time
m_NetworkManager.InvokeOnClientConnectedCallback(m_NetworkManager.LocalClientId);
NetworkManager.ConnectionManager.InvokeOnClientConnectedCallback(NetworkManager.LocalClientId);
// Notify the client that they have finished synchronizing
OnSceneEvent?.Invoke(new SceneEvent()
{
SceneEventType = sceneEventData.SceneEventType,
ClientId = m_NetworkManager.LocalClientId, // Client sent this to the server
ClientId = NetworkManager.LocalClientId, // Client sent this to the server
});
// Process any SceneEventType.ObjectSceneChanged messages that
@@ -2068,10 +2076,10 @@ namespace Unity.Netcode
// scene not synchronized by the server will remain loaded)
if (PostSynchronizationSceneUnloading && ClientSynchronizationMode == LoadSceneMode.Additive)
{
SceneManagerHandler.UnloadUnassignedScenes(m_NetworkManager);
SceneManagerHandler.UnloadUnassignedScenes(NetworkManager);
}
OnSynchronizeComplete?.Invoke(m_NetworkManager.LocalClientId);
OnSynchronizeComplete?.Invoke(NetworkManager.LocalClientId);
EndSceneEvent(sceneEventId);
}
@@ -2191,11 +2199,11 @@ namespace Unity.Netcode
// TODO 2023: We should have a better name for this or have multiple states the
// client progresses through (the name and associated legacy behavior/expected state
// of the client was persisted since MLAPI)
m_NetworkManager.InvokeOnClientConnectedCallback(clientId);
NetworkManager.ConnectionManager.InvokeOnClientConnectedCallback(clientId);
// Check to see if the client needs to resynchronize and before sending the message make sure the client is still connected to avoid
// a potential crash within the MessageSystem (i.e. sending to a client that no longer exists)
if (sceneEventData.ClientNeedsReSynchronization() && !DisableReSynchronization && m_NetworkManager.ConnectedClients.ContainsKey(clientId))
if (sceneEventData.ClientNeedsReSynchronization() && !DisableReSynchronization && NetworkManager.ConnectedClients.ContainsKey(clientId))
{
sceneEventData.SceneEventType = SceneEventType.ReSynchronize;
SendSceneEventData(sceneEventId, new ulong[] { clientId });
@@ -2225,13 +2233,13 @@ namespace Unity.Netcode
/// <param name="reader">data associated with the scene event</param>
internal void HandleSceneEvent(ulong clientId, FastBufferReader reader)
{
if (m_NetworkManager != null)
if (NetworkManager != null)
{
var sceneEventData = BeginSceneEvent();
sceneEventData.Deserialize(reader);
m_NetworkManager.NetworkMetrics.TrackSceneEventReceived(
NetworkManager.NetworkMetrics.TrackSceneEventReceived(
clientId, (uint)sceneEventData.SceneEventType, SceneNameFromHash(sceneEventData.SceneHash), reader.Length);
if (sceneEventData.IsSceneEventClientSide())
@@ -2250,7 +2258,7 @@ namespace Unity.Netcode
// used if the server is synchronizing the same scenes (i.e. if a matching scene is already loaded on the
// client side, then that scene will be used as opposed to loading another scene). This allows for clients
// to reconnect to a network session without having to unload all of the scenes and reload all of the scenes.
SceneManagerHandler.PopulateLoadedScenes(ref ScenesLoaded, m_NetworkManager);
SceneManagerHandler.PopulateLoadedScenes(ref ScenesLoaded, NetworkManager);
}
}
HandleClientSceneEvent(sceneEventData.SceneEventId);
@@ -2262,7 +2270,7 @@ namespace Unity.Netcode
}
else
{
Debug.LogError($"{nameof(HandleSceneEvent)} was invoked but {nameof(NetworkManager)} reference was null!");
Debug.LogError($"{nameof(HandleSceneEvent)} was invoked but {nameof(Netcode.NetworkManager)} reference was null!");
}
}
@@ -2274,7 +2282,7 @@ namespace Unity.Netcode
{
// Create a local copy of the spawned objects list since the spawn manager will adjust the list as objects
// are despawned.
var localSpawnedObjectsHashSet = new HashSet<NetworkObject>(m_NetworkManager.SpawnManager.SpawnedObjectsList);
var localSpawnedObjectsHashSet = new HashSet<NetworkObject>(NetworkManager.SpawnManager.SpawnedObjectsList);
foreach (var networkObject in localSpawnedObjectsHashSet)
{
if (networkObject == null || (networkObject != null && networkObject.gameObject.scene == DontDestroyOnLoadScene))
@@ -2291,7 +2299,7 @@ namespace Unity.Netcode
UnityEngine.Object.DontDestroyOnLoad(networkObject.gameObject);
}
}
else if (m_NetworkManager.IsServer)
else if (NetworkManager.IsServer)
{
networkObject.Despawn();
}
@@ -2330,7 +2338,7 @@ namespace Unity.Netcode
var globalObjectIdHash = networkObjectInstance.GlobalObjectIdHash;
var sceneHandle = networkObjectInstance.gameObject.scene.handle;
// We check to make sure the NetworkManager instance is the same one to be "NetcodeIntegrationTestHelpers" compatible and filter the list on a per scene basis (for additive scenes)
if (networkObjectInstance.IsSceneObject != false && (networkObjectInstance.NetworkManager == m_NetworkManager ||
if (networkObjectInstance.IsSceneObject != false && (networkObjectInstance.NetworkManager == NetworkManager ||
networkObjectInstance.NetworkManagerOwner == null) && sceneHandle == sceneToFilterBy.handle)
{
if (!ScenePlacedObjects.ContainsKey(globalObjectIdHash))
@@ -2358,7 +2366,7 @@ namespace Unity.Netcode
/// <param name="scene">scene to move the NetworkObjects to</param>
internal void MoveObjectsFromDontDestroyOnLoadToScene(Scene scene)
{
foreach (var networkObject in m_NetworkManager.SpawnManager.SpawnedObjectsList)
foreach (var networkObject in NetworkManager.SpawnManager.SpawnedObjectsList)
{
if (networkObject == null)
{
@@ -2389,9 +2397,9 @@ namespace Unity.Netcode
internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject)
{
// Really, this should never happen but in case it does
if (!m_NetworkManager.IsServer)
if (!NetworkManager.IsServer)
{
if (m_NetworkManager.LogLevel == LogLevel.Developer)
if (NetworkManager.LogLevel == LogLevel.Developer)
{
NetworkLog.LogErrorServer("[Please Report This Error][NotifyNetworkObjectSceneChanged] A client is trying to notify of an object's scene change!");
}
@@ -2402,7 +2410,7 @@ namespace Unity.Netcode
if (networkObject.IsSceneObject != false)
{
// Really, this should ever happen but in case it does
if (m_NetworkManager.LogLevel == LogLevel.Developer)
if (NetworkManager.LogLevel == LogLevel.Developer)
{
NetworkLog.LogErrorServer("[Please Report This Error][NotifyNetworkObjectSceneChanged] Trying to notify in-scene placed object scene change!");
}
@@ -2468,20 +2476,57 @@ namespace Unity.Netcode
ObjectsMigratedIntoNewScene.Clear();
}
private List<int> m_ScenesToRemoveFromObjectMigration = new List<int>();
/// <summary>
/// Should be invoked during PostLateUpdate just prior to the
/// MessagingSystem processes its outbound message queue.
/// Should be invoked during PostLateUpdate just prior to the NetworkMessageManager processes its outbound message queue.
/// </summary>
internal void CheckForAndSendNetworkObjectSceneChanged()
{
// Early exit if not the server or there is nothing pending
if (!m_NetworkManager.IsServer || ObjectsMigratedIntoNewScene.Count == 0)
if (!NetworkManager.IsServer || ObjectsMigratedIntoNewScene.Count == 0)
{
return;
}
// Double check that the NetworkObjects to migrate still exist
m_ScenesToRemoveFromObjectMigration.Clear();
foreach (var sceneEntry in ObjectsMigratedIntoNewScene)
{
for (int i = sceneEntry.Value.Count - 1; i >= 0; i--)
{
// Remove NetworkObjects that are no longer spawned
if (!sceneEntry.Value[i].IsSpawned)
{
sceneEntry.Value.RemoveAt(i);
}
}
// If the scene entry no longer has any NetworkObjects to migrate
// then add it to the list of scenes to be removed from the table
// of scenes containing NetworkObjects to migrate.
if (sceneEntry.Value.Count == 0)
{
m_ScenesToRemoveFromObjectMigration.Add(sceneEntry.Key);
}
}
// Remove sceneHandle entries that no longer have any NetworkObjects remaining
foreach (var sceneHandle in m_ScenesToRemoveFromObjectMigration)
{
ObjectsMigratedIntoNewScene.Remove(sceneHandle);
}
// If there is nothing to send a migration notification for then exit
if (ObjectsMigratedIntoNewScene.Count == 0)
{
return;
}
// Some NetworkObjects still exist, send the message
var sceneEvent = BeginSceneEvent();
sceneEvent.SceneEventType = SceneEventType.ObjectSceneChanged;
SendSceneEventData(sceneEvent.SceneEventId, m_NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
SendSceneEventData(sceneEvent.SceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
EndSceneEvent(sceneEvent.SceneEventId);
}