Skip to content

Commit 8e78d21

Browse files
Merge branch 'develop-2.0.0' into renovate/develop-2.0.0-package-ci-ubuntu-22.04-4.x
2 parents 0f5d56f + 1b54dd3 commit 8e78d21

File tree

57 files changed

+592
-276
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+592
-276
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,11 @@ Additional documentation and release notes are available at [Multiplayer Documen
1010

1111
### Added
1212

13-
- Added stricter checks on `InSpawned` within `NetworkObject`. (#3831)
14-
- Added a new `InvalidOperation` status to `OwnershipRequestStatus`. (#3831)
13+
- The `NetworkMetricsPipelineStage` for Unity Transport is now part of the public API. This allows using it in custom implementations of `INetworkStreamDriverConstructor` that want to maintain compatibility with the multiplayer tools package. (#3853)
1514

1615
### Changed
1716

18-
- Ensure logs in `NetworkObject` log the `NetworkObject.name` wherever possible. (#3831)
19-
- Improved performance of NetworkBehaviour ILPostProcessor by omitting unnecessary type and assembly resolutions. (#3827)
20-
- Improve performance of `NetworkObject`. (#3820, #3831)
21-
- If the Unity Transport Disconnect Timeout is set to 0 in the Editor, the timeout will be entirely disabled. (#3810)
17+
- Updating usage of deprecated `FindObjectsByType(FindObjectsSortMode)` and enum `FindObjectSortMode` in 6000.4 and 6000.5. (#3857)
2218

2319
### Deprecated
2420

@@ -28,16 +24,37 @@ Additional documentation and release notes are available at [Multiplayer Documen
2824

2925
### Fixed
3026

31-
- Fixed issue when using a client-server topology where a `NetworkList` with owner write permissions was resetting sent time and dirty flags after having been spawned on owning clients that were not the spawn authority. (#3850)
32-
- Fixed an integer overflow that occurred when configuring a large disconnect timeout with Unity Transport. (#3810)
33-
27+
- Fixed issue where `NetworkManager` was not cleaning itself up if an exception was thrown while starting. (#3864)
28+
- Prevented a `NullReferenceException` in `UnityTransport` when using a custom `INetworkStreamDriverConstructor` that doesn't use all the default pipelines and the multiplayer tools package is installed. (#3853)
3429

3530
### Security
3631

3732

3833
### Obsolete
3934

4035

36+
## [2.9.0] - 2026-02-01
37+
38+
### Added
39+
40+
- Added stricter checks on `InSpawned` within `NetworkObject`. (#3831)
41+
- Added a new `InvalidOperation` status to `OwnershipRequestStatus`. (#3831)
42+
43+
### Changed
44+
45+
- Ensure logs in `NetworkObject` log the `NetworkObject.name` wherever possible. (#3831)
46+
- Improved performance of NetworkBehaviour ILPostProcessor by omitting unnecessary type and assembly resolutions. (#3827)
47+
- Improve performance of `NetworkObject`. (#3820, #3831)
48+
- If the Unity Transport Disconnect Timeout is set to 0 in the Editor, the timeout will be entirely disabled. (#3810)
49+
50+
### Fixed
51+
52+
- Duplicate transport connection events for the same connection will now do nothing. (#3863)
53+
- Fixed memory leak in `NetworkAnimator` on clients where `RpcTarget` groups were not being properly disposed due to incorrect type casting of `ProxyRpcTargetGroup` to `RpcTargetGroup`.
54+
- Fixed issue when using a client-server topology where a `NetworkList` with owner write permissions was resetting sent time and dirty flags after having been spawned on owning clients that were not the spawn authority. (#3850)
55+
- Fixed an integer overflow that occurred when configuring a large disconnect timeout with Unity Transport. (#3810)
56+
57+
4158
## [2.8.0] - 2025-12-15
4259

4360
### Added

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ private static void ScenesInBuildActiveSceneCheck()
9292
var activeScene = SceneManager.GetActiveScene();
9393
var isSceneInBuildSettings = scenesList.Count((c) => c.path == activeScene.path) == 1;
9494
#if UNITY_2023_1_OR_NEWER
95-
var networkManager = Object.FindFirstObjectByType<NetworkManager>();
95+
var networkManager = Object.FindAnyObjectByType<NetworkManager>();
9696
#else
9797
var networkManager = Object.FindObjectOfType<NetworkManager>();
9898
#endif

com.unity.netcode.gameobjects/Runtime/Components/Helpers/AttachableBehaviour.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ public override void OnNetworkPreDespawn()
282282
{
283283
ForceDetach();
284284
}
285-
base.OnNetworkDespawn();
285+
base.OnNetworkPreDespawn();
286286
}
287287

288288
/// <summary>

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ protected virtual bool OnIsServerAuthoritative()
709709
private static byte[] s_EmptyArray = new byte[] { };
710710
private List<int> m_ParametersToUpdate;
711711
private RpcParams m_RpcParams;
712-
private RpcTargetGroup m_TargetGroup;
712+
private IGroupRpcTarget m_TargetGroup;
713713
private AnimationMessage m_AnimationMessage;
714714
private NetworkAnimatorStateChangeHandler m_NetworkAnimatorStateChangeHandler;
715715

@@ -762,7 +762,7 @@ public override void OnDestroy()
762762
{
763763
SpawnCleanup();
764764

765-
m_TargetGroup?.Dispose();
765+
m_TargetGroup?.Target?.Dispose();
766766

767767
if (m_CachedAnimatorParameters != null && m_CachedAnimatorParameters.IsCreated)
768768
{
@@ -928,12 +928,12 @@ public override void OnNetworkSpawn()
928928
NetworkLog.LogWarningServer($"[{gameObject.name}][{nameof(NetworkAnimator)}] {nameof(Animator)} is not assigned! Animation synchronization will not work for this instance!");
929929
}
930930

931-
m_TargetGroup = RpcTarget.Group(new List<ulong>(128), RpcTargetUse.Persistent) as RpcTargetGroup;
931+
m_TargetGroup = RpcTarget.Group(new List<ulong>(128), RpcTargetUse.Persistent) as IGroupRpcTarget;
932932
m_RpcParams = new RpcParams()
933933
{
934934
Send = new RpcSendParams()
935935
{
936-
Target = m_TargetGroup
936+
Target = m_TargetGroup?.Target
937937
}
938938
};
939939

@@ -1219,7 +1219,7 @@ internal void CheckForAnimatorChanges()
12191219
}
12201220
m_TargetGroup.Add(clientId);
12211221
}
1222-
m_RpcParams.Send.Target = m_TargetGroup;
1222+
m_RpcParams.Send.Target = m_TargetGroup.Target;
12231223
SendClientAnimStateRpc(m_AnimationMessage, m_RpcParams);
12241224
}
12251225
}
@@ -1555,7 +1555,7 @@ private unsafe void SendServerParametersUpdateRpc(ParametersUpdateMessage parame
15551555
m_TargetGroup.Add(clientId);
15561556
}
15571557

1558-
m_RpcParams.Send.Target = m_TargetGroup;
1558+
m_RpcParams.Send.Target = m_TargetGroup.Target;
15591559
m_NetworkAnimatorStateChangeHandler.SendParameterUpdate(parametersUpdate, m_RpcParams);
15601560
}
15611561
}
@@ -1621,7 +1621,7 @@ private void SendServerAnimStateRpc(AnimationMessage animationMessage, RpcParams
16211621
}
16221622
m_TargetGroup.Add(clientId);
16231623
}
1624-
m_RpcParams.Send.Target = m_TargetGroup;
1624+
m_RpcParams.Send.Target = m_TargetGroup.Target;
16251625
m_NetworkAnimatorStateChangeHandler.SendAnimationUpdate(animationMessage, m_RpcParams);
16261626
}
16271627
}

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

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,12 @@ internal void HandleNetworkEvent(NetworkEvent networkEvent, ulong transportClien
494494

495495
internal ulong LocalClientTransportId => m_LocalClientTransportId;
496496

497+
private bool m_IsTransportConnected = false;
498+
497499
/// <summary>
498500
/// Handles a <see cref="NetworkEvent.Connect"/> event.
499501
/// </summary>
500-
internal void ConnectEventHandler(ulong transportClientId)
502+
internal void ConnectEventHandler(ulong transportId)
501503
{
502504
#if DEVELOPMENT_BUILD || UNITY_EDITOR
503505
s_TransportConnect.Begin();
@@ -507,20 +509,45 @@ internal void ConnectEventHandler(ulong transportClientId)
507509
// - When client receives one, it *must be* the server
508510
// Client's can't connect to or talk to other clients.
509511
// Server is a sentinel so only one exists, if we are server, we can't be connecting to it.
510-
var clientId = transportClientId;
512+
513+
ulong clientId;
514+
515+
// If we're the server, then this connect event is firing for a new incoming client connection
511516
if (LocalClient.IsServer)
512517
{
518+
var (_, alreadyConnected) = TransportIdToClientId(transportId);
519+
if (alreadyConnected)
520+
{
521+
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
522+
{
523+
NetworkLog.LogError($"[TransportApproval][Server] TransportId {transportId} is already connected to this server!");
524+
}
525+
return;
526+
}
527+
513528
clientId = m_NextClientId++;
514529
}
530+
// Otherwise this connect event is an approved connection from the server
515531
else
516532
{
533+
if (m_IsTransportConnected)
534+
{
535+
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
536+
{
537+
NetworkLog.LogError("[TransportApproval][Client] Client received a transport connection event after already connecting!");
538+
}
539+
return;
540+
}
541+
542+
m_IsTransportConnected = true;
543+
517544
// Cache the local client's transport id.
518-
m_LocalClientTransportId = transportClientId;
545+
m_LocalClientTransportId = transportId;
519546
clientId = NetworkManager.ServerClientId;
520547
}
521548

522-
ClientIdToTransportIdMap[clientId] = transportClientId;
523-
TransportIdToClientIdMap[transportClientId] = clientId;
549+
ClientIdToTransportIdMap[clientId] = transportId;
550+
TransportIdToClientIdMap[transportId] = clientId;
524551
MessageManager.ClientConnected(clientId);
525552

526553
if (LocalClient.IsServer)
@@ -1540,6 +1567,7 @@ internal void Initialize(NetworkManager networkManager)
15401567
ConnectedClientIds.Clear();
15411568
ClientIdToTransportIdMap.Clear();
15421569
TransportIdToClientIdMap.Clear();
1570+
m_IsTransportConnected = false;
15431571
ClientsToApprove.Clear();
15441572
NetworkObject.OrphanChildren.Clear();
15451573
m_DisconnectReason = string.Empty;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#if NGO_FINDOBJECTS_NOSORTING
2+
using System;
3+
#endif
4+
using System.Runtime.CompilerServices;
5+
using Object = UnityEngine.Object;
6+
7+
namespace Unity.Netcode
8+
{
9+
/// <summary>
10+
/// Helper class to handle the variations of FindObjectsByType.
11+
/// </summary>
12+
/// <remarks>
13+
/// It is intentional that we do not include the UnityEngine namespace in order to avoid
14+
/// over-complicatd define wrapping between versions that do or don't support FindObjectsSortMode.
15+
/// </remarks>
16+
internal static class FindObjects
17+
{
18+
/// <summary>
19+
/// Replaces <see cref="Object.FindObjectsByType"/> to have one place where these changes are applied.
20+
/// </summary>
21+
/// <typeparam name="T"></typeparam>
22+
/// <param name="includeInactive">When true, inactive objects will be included.</param>
23+
/// <param name="orderByIdentifier">When true, the array returned will be sorted by identifier.</param>
24+
/// <returns>Resulst as an <see cref="Array"/> of type T</returns>
25+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
26+
public static T[] ByType<T>(bool includeInactive = false, bool orderByIdentifier = false) where T : Object
27+
{
28+
var inactive = includeInactive ? UnityEngine.FindObjectsInactive.Include : UnityEngine.FindObjectsInactive.Exclude;
29+
#if NGO_FINDOBJECTS_NOSORTING
30+
var results = Object.FindObjectsByType<T>(inactive);
31+
if (orderByIdentifier)
32+
{
33+
Array.Sort(results, (a, b) => a.GetEntityId().CompareTo(b.GetEntityId()));
34+
}
35+
#else
36+
var results = Object.FindObjectsByType<T>(inactive, orderByIdentifier ? UnityEngine.FindObjectsSortMode.InstanceID : UnityEngine.FindObjectsSortMode.None);
37+
#endif
38+
return results;
39+
}
40+
}
41+
}

com.unity.netcode.gameobjects/Runtime/Core/FindObjects.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,17 @@ public bool StartServer()
13231323
}
13241324
ConnectionManager.LocalClient.ClientId = ServerClientId;
13251325

1326-
Initialize(true);
1326+
try
1327+
{
1328+
Initialize(true);
1329+
}
1330+
catch (Exception ex)
1331+
{
1332+
Debug.LogException(ex);
1333+
// Always shutdown to assure everything is cleaned up
1334+
ShutdownInternal();
1335+
return false;
1336+
}
13271337

13281338
try
13291339
{
@@ -1342,11 +1352,12 @@ public bool StartServer()
13421352

13431353
ConnectionManager.TransportFailureEventHandler(true);
13441354
}
1345-
catch (Exception)
1355+
catch (Exception ex)
13461356
{
1347-
ConnectionManager.LocalClient.SetRole(false, false);
1357+
Debug.LogException(ex);
1358+
// Always shutdown to assure everything is cleaned up
1359+
ShutdownInternal();
13481360
IsListening = false;
1349-
throw;
13501361
}
13511362

13521363
return IsListening;
@@ -1373,7 +1384,16 @@ public bool StartClient()
13731384
return false;
13741385
}
13751386

1376-
Initialize(false);
1387+
try
1388+
{
1389+
Initialize(false);
1390+
}
1391+
catch (Exception ex)
1392+
{
1393+
Debug.LogException(ex);
1394+
ShutdownInternal();
1395+
return false;
1396+
}
13771397

13781398
try
13791399
{
@@ -1391,7 +1411,7 @@ public bool StartClient()
13911411
catch (Exception ex)
13921412
{
13931413
Debug.LogException(ex);
1394-
ConnectionManager.LocalClient.SetRole(false, false);
1414+
ShutdownInternal();
13951415
IsListening = false;
13961416
}
13971417

@@ -1419,7 +1439,18 @@ public bool StartHost()
14191439
return false;
14201440
}
14211441

1422-
Initialize(true);
1442+
try
1443+
{
1444+
Initialize(true);
1445+
}
1446+
catch (Exception ex)
1447+
{
1448+
Debug.LogException(ex);
1449+
// Always shutdown to assure everything is cleaned up
1450+
ShutdownInternal();
1451+
return false;
1452+
}
1453+
14231454
try
14241455
{
14251456
IsListening = NetworkConfig.NetworkTransport.StartServer();
@@ -1437,7 +1468,8 @@ public bool StartHost()
14371468
catch (Exception ex)
14381469
{
14391470
Debug.LogException(ex);
1440-
ConnectionManager.LocalClient.SetRole(false, false);
1471+
// Always shutdown to assure everything is cleaned up
1472+
ShutdownInternal();
14411473
IsListening = false;
14421474
}
14431475

com.unity.netcode.gameobjects/Runtime/Messaging/NetworkManagerHooks.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public bool OnVerifyCanReceive(ulong senderId, Type messageType, FastBufferReade
104104
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
105105
{
106106
var transportErrorMsg = GetTransportErrorMessage(messageContent, m_NetworkManager);
107-
NetworkLog.LogError($"A {nameof(ConnectionApprovedMessage)} was received from the server when the connection has already been established. {transportErrorMsg}");
107+
NetworkLog.LogError($"A {nameof(ConnectionApprovedMessage)} was received from the server when a connection has already been established. {transportErrorMsg}");
108108
}
109109

110110
return false;
@@ -118,11 +118,11 @@ private static string GetTransportErrorMessage(FastBufferReader messageContent,
118118
{
119119
if (networkManager.NetworkConfig.NetworkTransport is not UnityTransport)
120120
{
121-
return $"NetworkTransport: {networkManager.NetworkConfig.NetworkTransport.GetType()}. Please report this to the maintainer of transport layer.";
121+
return $"NetworkTransport: {networkManager.NetworkConfig.NetworkTransport.GetType()}. Please report this to the maintainer of the transport layer.";
122122
}
123123

124124
var transportVersion = GetTransportVersion(networkManager);
125-
return $"{transportVersion}. This should not happen. Please report this to the Netcode for GameObjects team at https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues and include the following data: Message Size: {messageContent.Length}. Message Content: {NetworkMessageManager.ByteArrayToString(messageContent.ToArray(), 0, messageContent.Length)}";
125+
return $"{transportVersion}. This should not happen. Further information: Message Size: {messageContent.Length}. Message Content: {NetworkMessageManager.ByteArrayToString(messageContent.ToArray(), 0, messageContent.Length)}";
126126
}
127127

128128
private static string GetTransportVersion(NetworkManager networkManager)

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,12 +2729,7 @@ internal void PopulateScenePlacedObjects(Scene sceneToFilterBy, bool clearSceneP
27292729
{
27302730
ScenePlacedObjects.Clear();
27312731
}
2732-
2733-
#if UNITY_2023_1_OR_NEWER
2734-
var networkObjects = UnityEngine.Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.InstanceID);
2735-
#else
2736-
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>();
2737-
#endif
2732+
var networkObjects = FindObjects.ByType<NetworkObject>();
27382733

27392734
// Just add every NetworkObject found that isn't already in the list
27402735
// With additive scenes, we can have multiple in-scene placed NetworkObjects with the same GlobalObjectIdHash value

0 commit comments

Comments
 (0)