diff --git a/CHANGELOG.md b/CHANGELOG.md index e043ec1..1410b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). +## [1.0.0-pre.9] - 2022-05-10 + +### Fixed + +- Fixed Hosting again after failing to host now works correctly (#1938) +- Fixed NetworkManager to cleanup connected client lists after stopping (#1945) +- Fixed NetworkHide followed by NetworkShow on the same frame works correctly (#1940) + ## [1.0.0-pre.8] - 2022-04-27 ### Changed @@ -13,9 +21,9 @@ Additional documentation and release notes are available at [Multiplayer Documen - `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy`. (#1901) ### Removed -- Removed `SIPTransport` (#1870) -- Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs). +- Removed `SIPTransport` (#1870) +- Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs) (#1912). ### Fixed @@ -24,6 +32,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883) - Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854) - Passing generic types to RPCs no longer causes a native crash (#1901) +- Fixed a compile failure when compiling against com.unity.nuget.mono-cecil >= 1.11.4 (#1920) - Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877) ## [1.0.0-pre.7] - 2022-04-06 diff --git a/Editor/CodeGen/NetworkBehaviourILPP.cs b/Editor/CodeGen/NetworkBehaviourILPP.cs index 5da75bd..f4008a4 100644 --- a/Editor/CodeGen/NetworkBehaviourILPP.cs +++ b/Editor/CodeGen/NetworkBehaviourILPP.cs @@ -607,7 +607,11 @@ namespace Unity.Netcode.Editor.CodeGen var meetsConstraints = true; foreach (var constraint in method.GenericParameters[0].Constraints) { +#if CECIL_CONSTRAINTS_ARE_TYPE_REFERENCES var resolvedConstraint = constraint.Resolve(); +#else + var resolvedConstraint = constraint.ConstraintType.Resolve(); +#endif var resolvedConstraintName = resolvedConstraint.FullNameWithGenericParameters(new[] { method.GenericParameters[0] }, new[] { checkType }); if ((resolvedConstraint.IsInterface && !checkType.HasInterface(resolvedConstraintName)) || @@ -737,7 +741,12 @@ namespace Unity.Netcode.Editor.CodeGen var meetsConstraints = true; foreach (var constraint in method.GenericParameters[0].Constraints) { +#if CECIL_CONSTRAINTS_ARE_TYPE_REFERENCES var resolvedConstraint = constraint.Resolve(); +#else + var resolvedConstraint = constraint.ConstraintType.Resolve(); +#endif + var resolvedConstraintName = resolvedConstraint.FullNameWithGenericParameters(new[] { method.GenericParameters[0] }, new[] { checkType }); diff --git a/Editor/CodeGen/com.unity.netcode.editor.codegen.asmdef b/Editor/CodeGen/com.unity.netcode.editor.codegen.asmdef index f9a5652..85ccaa4 100644 --- a/Editor/CodeGen/com.unity.netcode.editor.codegen.asmdef +++ b/Editor/CodeGen/com.unity.netcode.editor.codegen.asmdef @@ -7,6 +7,7 @@ "includePlatforms": [ "Editor" ], + "excludePlatforms": [], "allowUnsafeCode": true, "overrideReferences": true, "precompiledReferences": [ @@ -15,5 +16,14 @@ "Mono.Cecil.Pdb.dll", "Mono.Cecil.Rocks.dll" ], - "autoReferenced": false -} \ No newline at end of file + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.nuget.mono-cecil", + "expression": "(0,1.11.4)", + "define": "CECIL_CONSTRAINTS_ARE_TYPE_REFERENCES" + } + ], + "noEngineReferences": false +} diff --git a/Runtime/Configuration/NetworkConfig.cs b/Runtime/Configuration/NetworkConfig.cs index 9606641..208b705 100644 --- a/Runtime/Configuration/NetworkConfig.cs +++ b/Runtime/Configuration/NetworkConfig.cs @@ -53,9 +53,21 @@ namespace Unity.Netcode public uint TickRate = 30; /// - /// The amount of seconds to wait for handshake to complete before timing out a client + /// The amount of seconds for the server to wait for the connection approval handshake to complete before the client is disconnected. + /// + /// If the timeout is reached before approval is completed the client will be disconnected. /// - [Tooltip("The amount of seconds to wait for the handshake to complete before the client times out")] + /// + /// The period begins after the is received on the server. + /// The period ends once the server finishes processing a from the client. + /// + /// This setting is independent of any Transport-level timeouts that may be in effect. It covers the time between + /// the connection being established on the Transport layer, the client sending a + /// , and the server processing that message through . + /// + /// This setting is server-side only. + /// + [Tooltip("The amount of seconds for the server to wait for the connection approval handshake to complete before the client is disconnected")] public int ClientConnectionBufferTimeout = 10; /// diff --git a/Runtime/Core/NetworkManager.cs b/Runtime/Core/NetworkManager.cs index cdb0852..0351951 100644 --- a/Runtime/Core/NetworkManager.cs +++ b/Runtime/Core/NetworkManager.cs @@ -765,12 +765,7 @@ namespace Unity.Netcode #endif LocalClientId = ulong.MaxValue; - PendingClients.Clear(); - m_ConnectedClients.Clear(); - m_ConnectedClientsList.Clear(); - m_ConnectedClientIds.Clear(); - LocalClient = null; - NetworkObject.OrphanChildren.Clear(); + ClearClients(); // Create spawn manager instance SpawnManager = new NetworkSpawnManager(this); @@ -862,6 +857,16 @@ namespace Unity.Netcode NetworkConfig.NetworkTransport.Initialize(this); } + private void ClearClients() + { + PendingClients.Clear(); + m_ConnectedClients.Clear(); + m_ConnectedClientsList.Clear(); + m_ConnectedClientIds.Clear(); + LocalClient = null; + NetworkObject.OrphanChildren.Clear(); + } + /// /// Starts a server /// @@ -1175,6 +1180,8 @@ namespace Unity.Netcode m_ShuttingDown = true; m_StopProcessingMessages = discardMessageQueue; } + + NetworkConfig.NetworkTransport.OnTransportEvent -= HandleRawTransportPoll; } internal void ShutdownInternal() @@ -1299,6 +1306,8 @@ namespace Unity.Netcode IsListening = false; m_ShuttingDown = false; m_StopProcessingMessages = false; + + ClearClients(); } // INetworkUpdateSystem diff --git a/Runtime/Core/NetworkObject.cs b/Runtime/Core/NetworkObject.cs index 241ee8d..a34c6c9 100644 --- a/Runtime/Core/NetworkObject.cs +++ b/Runtime/Core/NetworkObject.cs @@ -352,7 +352,10 @@ namespace Unity.Netcode if (NetworkManager != null && NetworkManager.SpawnManager != null && NetworkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject)) { - NetworkManager.SpawnManager.OnDespawnObject(networkObject, false); + if (this == networkObject) + { + NetworkManager.SpawnManager.OnDespawnObject(networkObject, false); + } } } diff --git a/Runtime/NetworkVariable/Collections/NetworkList.cs b/Runtime/NetworkVariable/Collections/NetworkList.cs index 9a891ec..5e0b8d8 100644 --- a/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -11,6 +11,7 @@ namespace Unity.Netcode public class NetworkList : NetworkVariableSerialization where T : unmanaged, IEquatable { private NativeList m_List = new NativeList(64, Allocator.Persistent); + private NativeList m_ListAtLastReset = new NativeList(64, Allocator.Persistent); private NativeList> m_DirtyEvents = new NativeList>(64, Allocator.Persistent); /// @@ -41,7 +42,11 @@ namespace Unity.Netcode public override void ResetDirty() { base.ResetDirty(); - m_DirtyEvents.Clear(); + if (m_DirtyEvents.Length > 0) + { + m_DirtyEvents.Clear(); + m_ListAtLastReset.CopyFrom(m_List); + } } /// @@ -109,10 +114,10 @@ namespace Unity.Netcode /// public override void WriteField(FastBufferWriter writer) { - writer.WriteValueSafe((ushort)m_List.Length); - for (int i = 0; i < m_List.Length; i++) + writer.WriteValueSafe((ushort)m_ListAtLastReset.Length); + for (int i = 0; i < m_ListAtLastReset.Length; i++) { - Write(writer, m_List[i]); + Write(writer, m_ListAtLastReset[i]); } } @@ -454,6 +459,7 @@ namespace Unity.Netcode public override void Dispose() { m_List.Dispose(); + m_ListAtLastReset.Dispose(); m_DirtyEvents.Dispose(); } } diff --git a/Runtime/Transports/UTP/UnityTransport.cs b/Runtime/Transports/UTP/UnityTransport.cs index 83642df..62b932f 100644 --- a/Runtime/Transports/UTP/UnityTransport.cs +++ b/Runtime/Transports/UTP/UnityTransport.cs @@ -1047,7 +1047,12 @@ namespace Unity.Netcode.Transports.UTP return false; } - return ClientBindAndConnect(); + var succeeded = ClientBindAndConnect(); + if (!succeeded) + { + Shutdown(); + } + return succeeded; } public override bool StartServer() @@ -1057,12 +1062,23 @@ namespace Unity.Netcode.Transports.UTP return false; } + bool succeeded; switch (m_ProtocolType) { case ProtocolType.UnityTransport: - return ServerBindAndListen(ConnectionData.ListenEndPoint); + succeeded = ServerBindAndListen(ConnectionData.ListenEndPoint); + if (!succeeded) + { + Shutdown(); + } + return succeeded; case ProtocolType.RelayUnityTransport: - return StartRelayServer(); + succeeded = StartRelayServer(); + if (!succeeded) + { + Shutdown(); + } + return succeeded; default: return false; } diff --git a/Tests/Runtime/NetworkShowHideTests.cs b/Tests/Runtime/NetworkShowHideTests.cs index 58a46bc..859249b 100644 --- a/Tests/Runtime/NetworkShowHideTests.cs +++ b/Tests/Runtime/NetworkShowHideTests.cs @@ -74,7 +74,7 @@ namespace Unity.Netcode.RuntimeTests int count = 0; do { - yield return new WaitForSeconds(0.1f); + yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5); count++; if (count > 20) @@ -140,18 +140,18 @@ namespace Unity.Netcode.RuntimeTests { var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation( - x => x.NetworkObjectId == m_NetSpawnedObject1.NetworkObjectId, + x => x.NetworkObjectId == m_NetSpawnedObject1.NetworkObjectId && x.IsSpawned, m_ClientNetworkManagers[0], serverClientPlayerResult); m_Object1OnClient0 = serverClientPlayerResult.Result; yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation( - x => x.NetworkObjectId == m_NetSpawnedObject2.NetworkObjectId, + x => x.NetworkObjectId == m_NetSpawnedObject2.NetworkObjectId && x.IsSpawned, m_ClientNetworkManagers[0], serverClientPlayerResult); m_Object2OnClient0 = serverClientPlayerResult.Result; serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation( - x => x.NetworkObjectId == m_NetSpawnedObject3.NetworkObjectId, + x => x.NetworkObjectId == m_NetSpawnedObject3.NetworkObjectId && x.IsSpawned, m_ClientNetworkManagers[0], serverClientPlayerResult); m_Object3OnClient0 = serverClientPlayerResult.Result; @@ -196,11 +196,11 @@ namespace Unity.Netcode.RuntimeTests // hide them on one client Show(mode == 0, false); - yield return new WaitForSeconds(1.0f); + yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5); m_NetSpawnedObject1.GetComponent().MyNetworkVariable.Value = 3; - yield return new WaitForSeconds(1.0f); + yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5); // verify they got hidden yield return CheckVisible(false); @@ -213,5 +213,44 @@ namespace Unity.Netcode.RuntimeTests yield return CheckVisible(true); } } + + [UnityTest] + public IEnumerator NetworkShowHideQuickTest() + { + m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId; + + var spawnedObject1 = UnityEngine.Object.Instantiate(m_PrefabToSpawn); + var spawnedObject2 = UnityEngine.Object.Instantiate(m_PrefabToSpawn); + var spawnedObject3 = UnityEngine.Object.Instantiate(m_PrefabToSpawn); + m_NetSpawnedObject1 = spawnedObject1.GetComponent(); + m_NetSpawnedObject2 = spawnedObject2.GetComponent(); + m_NetSpawnedObject3 = spawnedObject3.GetComponent(); + m_NetSpawnedObject1.NetworkManagerOwner = m_ServerNetworkManager; + m_NetSpawnedObject2.NetworkManagerOwner = m_ServerNetworkManager; + m_NetSpawnedObject3.NetworkManagerOwner = m_ServerNetworkManager; + m_NetSpawnedObject1.Spawn(); + m_NetSpawnedObject2.Spawn(); + m_NetSpawnedObject3.Spawn(); + + for (int mode = 0; mode < 2; mode++) + { + // get the NetworkObject on a client instance + yield return RefreshNetworkObjects(); + + // check object start visible + yield return CheckVisible(true); + + // hide and show them on one client, during the same frame + Show(mode == 0, false); + Show(mode == 0, true); + + yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5); + yield return RefreshNetworkObjects(); + yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5); + + // verify they become visible + yield return CheckVisible(true); + } + } } } diff --git a/package.json b/package.json index e6f580d..231c6c0 100644 --- a/package.json +++ b/package.json @@ -2,22 +2,22 @@ "name": "com.unity.netcode.gameobjects", "displayName": "Netcode for GameObjects", "description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.", - "version": "1.0.0-pre.8", + "version": "1.0.0-pre.9", "unity": "2020.3", "dependencies": { "com.unity.nuget.mono-cecil": "1.10.1", "com.unity.transport": "1.0.0" }, "_upm": { - "changelog": "### Changed\n\n- `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy`. (#1901)\n\n### Removed\n- Removed `SIPTransport` (#1870)\n\n- Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs).\n\n### Fixed\n\n- Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890)\n- Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884)\n- Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883)\n- Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854)\n- Passing generic types to RPCs no longer causes a native crash (#1901)\n- Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877)" + "changelog": "### Fixed\n\n- Fixed Hosting again after failing to host now works correctly (#1938)\n- Fixed NetworkManager to cleanup connected client lists after stopping (#1945)\n- Fixed NetworkHide followed by NetworkShow on the same frame works correctly (#1940)" }, "upmCi": { - "footprint": "7593dccd41bcdc7887dea63f675cdee7400ee3dc" + "footprint": "ed33b1bdf8c343399eadd7640f4e9caa4ed07776" }, "repository": { "url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git", "type": "git", - "revision": "437d82ad0f11faa22e9f2539dddd3c5dda798a36" + "revision": "cdca1eb844973e9f314f6a263bb4c0497d9e396f" }, "samples": [ {