From 48184055146f1c4471e9215ddcad1d31ac452d00 Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity> Date: Wed, 26 Jan 2022 00:00:00 +0000 Subject: [PATCH] com.unity.netcode.gameobjects@1.0.0-pre.5 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.0.0-pre.5] - 2022-01-26 ### Added - Added `PreviousValue` in `NetworkListEvent`, when `Value` has changed (#1528) ### Changed - NetworkManager's GameObject is no longer allowed to be nested under one or more GameObject(s).(#1484) - NetworkManager DontDestroy property was removed and now NetworkManager always is migrated into the DontDestroyOnLoad scene. (#1484) ### Fixed - Fixed network tick value sometimes being duplicated or skipped. (#1614) - Fixed The ClientNetworkTransform sample script to allow for owner changes at runtime. (#1606) --- CHANGELOG.md | 19 +++ Editor/NetworkManagerEditor.cs | 4 - Editor/NetworkManagerHelper.cs | 108 ++++++++++++++++++ Editor/NetworkManagerHelper.cs.meta | 11 ++ README.md | 2 +- Runtime/Core/NetworkManager.cs | 64 +++++++++-- .../Collections/NetworkList.cs | 20 +++- .../SceneManagement/NetworkSceneManager.cs | 16 +-- Runtime/Timing/NetworkTime.cs | 5 + .../Scripts/ClientNetworkTransform.cs | 1 + .../NetworkManagerConfigurationTests.cs | 38 ++++++ .../NetworkManagerConfigurationTests.cs.meta | 11 ++ Tests/Editor/Timing/NetworkTimeTests.cs | 33 ++++++ Tests/Runtime/NestedNetworkManagerTests.cs | 37 ++++++ .../Runtime/NestedNetworkManagerTests.cs.meta | 11 ++ Tests/Runtime/NetworkVariableTests.cs | 56 ++++++++- package.json | 6 +- 17 files changed, 403 insertions(+), 39 deletions(-) create mode 100644 Editor/NetworkManagerHelper.cs create mode 100644 Editor/NetworkManagerHelper.cs.meta create mode 100644 Tests/Editor/NetworkManagerConfigurationTests.cs create mode 100644 Tests/Editor/NetworkManagerConfigurationTests.cs.meta create mode 100644 Tests/Runtime/NestedNetworkManagerTests.cs create mode 100644 Tests/Runtime/NestedNetworkManagerTests.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b925fc..6e1835c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ 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.5] - 2022-01-26 + +### Added + +- Added `PreviousValue` in `NetworkListEvent`, when `Value` has changed (#1528) + +### Changed + +- NetworkManager's GameObject is no longer allowed to be nested under one or more GameObject(s).(#1484) +- NetworkManager DontDestroy property was removed and now NetworkManager always is migrated into the DontDestroyOnLoad scene. (#1484) + +### Fixed + +- Fixed network tick value sometimes being duplicated or skipped. (#1614) +- Fixed The ClientNetworkTransform sample script to allow for owner changes at runtime. (#1606) + ## [1.0.0-pre.4] - 2021-01-04 ### Added @@ -29,10 +45,13 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed KeyNotFound exception when removing ownership of a newly spawned NetworkObject that is already owned by the server. (#1500) - Fixed NetworkManager.LocalClient not being set when starting as a host. (#1511) - Fixed a few memory leak cases when shutting down NetworkManager during Incoming Message Queue processing. (#1323) +- Fixed network tick value sometimes being duplicated or skipped. (#1614) ### Changed - The SDK no longer limits message size to 64k. (The transport may still impose its own limits, but the SDK no longer does.) (#1384) - Updated com.unity.collections to 1.1.0 (#1451) +- NetworkManager's GameObject is no longer allowed to be nested under one or more GameObject(s).(#1484) +- NetworkManager DontDestroy property was removed and now NetworkManager always is migrated into the DontDestroyOnLoad scene. (#1484) ## [1.0.0-pre.3] - 2021-10-22 diff --git a/Editor/NetworkManagerEditor.cs b/Editor/NetworkManagerEditor.cs index 6cb2ccd..f343402 100644 --- a/Editor/NetworkManagerEditor.cs +++ b/Editor/NetworkManagerEditor.cs @@ -15,7 +15,6 @@ public class NetworkManagerEditor : UnityEditor.Editor private static GUIStyle s_HelpBoxStyle; // Properties - private SerializedProperty m_DontDestroyOnLoadProperty; private SerializedProperty m_RunInBackgroundProperty; private SerializedProperty m_LogLevelProperty; @@ -85,7 +84,6 @@ private void Initialize() m_NetworkManager = (NetworkManager)target; // Base properties - m_DontDestroyOnLoadProperty = serializedObject.FindProperty(nameof(NetworkManager.DontDestroy)); m_RunInBackgroundProperty = serializedObject.FindProperty(nameof(NetworkManager.RunInBackground)); m_LogLevelProperty = serializedObject.FindProperty(nameof(NetworkManager.LogLevel)); m_NetworkConfigProperty = serializedObject.FindProperty(nameof(NetworkManager.NetworkConfig)); @@ -112,7 +110,6 @@ private void Initialize() private void CheckNullProperties() { // Base properties - m_DontDestroyOnLoadProperty = serializedObject.FindProperty(nameof(NetworkManager.DontDestroy)); m_RunInBackgroundProperty = serializedObject.FindProperty(nameof(NetworkManager.RunInBackground)); m_LogLevelProperty = serializedObject.FindProperty(nameof(NetworkManager.LogLevel)); m_NetworkConfigProperty = serializedObject.FindProperty(nameof(NetworkManager.NetworkConfig)); @@ -223,7 +220,6 @@ public override void OnInspectorGUI() if (!m_NetworkManager.IsServer && !m_NetworkManager.IsClient) { serializedObject.Update(); - EditorGUILayout.PropertyField(m_DontDestroyOnLoadProperty); EditorGUILayout.PropertyField(m_RunInBackgroundProperty); EditorGUILayout.PropertyField(m_LogLevelProperty); EditorGUILayout.Space(); diff --git a/Editor/NetworkManagerHelper.cs b/Editor/NetworkManagerHelper.cs new file mode 100644 index 0000000..d30dd86 --- /dev/null +++ b/Editor/NetworkManagerHelper.cs @@ -0,0 +1,108 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace Unity.Netcode.Editor +{ +#if UNITY_EDITOR + /// + /// Specialized editor specific NetworkManager code + /// + public class NetworkManagerHelper : NetworkManager.INetworkManagerHelper + { + internal static NetworkManagerHelper Singleton; + + // This is primarily to handle multiInstance scenarios where more than 1 NetworkManager could exist + private static Dictionary s_LastKnownNetworkManagerParents = new Dictionary(); + + /// + /// Initializes the singleton instance and registers for: + /// Hierarchy changed notification: to notify the user when they nest a NetworkManager + /// Play mode state change notification: to capture when entering or exiting play mode (currently only exiting) + /// + [InitializeOnLoadMethod] + private static void InitializeOnload() + { + Singleton = new NetworkManagerHelper(); + NetworkManager.NetworkManagerHelper = Singleton; + + EditorApplication.playModeStateChanged -= EditorApplication_playModeStateChanged; + EditorApplication.hierarchyChanged -= EditorApplication_hierarchyChanged; + + EditorApplication.playModeStateChanged += EditorApplication_playModeStateChanged; + EditorApplication.hierarchyChanged += EditorApplication_hierarchyChanged; + } + + private static void EditorApplication_playModeStateChanged(PlayModeStateChange playModeStateChange) + { + switch (playModeStateChange) + { + case PlayModeStateChange.ExitingEditMode: + { + s_LastKnownNetworkManagerParents.Clear(); + break; + } + } + } + + private static void EditorApplication_hierarchyChanged() + { + var allNetworkManagers = Resources.FindObjectsOfTypeAll(); + foreach (var networkManager in allNetworkManagers) + { + networkManager.NetworkManagerCheckForParent(); + } + } + + /// + /// Handles notifying the user, via display dialog window, that they have nested a NetworkManager. + /// When in edit mode it provides the option to automatically fix the issue + /// When in play mode it just notifies the user when entering play mode as well as when the user + /// tries to start a network session while a NetworkManager is still nested. + /// + public bool NotifyUserOfNestedNetworkManager(NetworkManager networkManager, bool ignoreNetworkManagerCache = false, bool editorTest = false) + { + var gameObject = networkManager.gameObject; + var transform = networkManager.transform; + var isParented = transform.root != transform; + + var message = NetworkManager.GenerateNestedNetworkManagerMessage(transform); + if (s_LastKnownNetworkManagerParents.ContainsKey(networkManager) && !ignoreNetworkManagerCache) + { + // If we have already notified the user, then don't notify them again + if (s_LastKnownNetworkManagerParents[networkManager] == transform.root) + { + return isParented; + } + else // If we are no longer a child, then we can remove ourself from this list + if (transform.root == gameObject.transform) + { + s_LastKnownNetworkManagerParents.Remove(networkManager); + } + } + if (!EditorApplication.isUpdating && isParented) + { + if (!EditorApplication.isPlaying && !editorTest) + { + message += $"Click 'Auto-Fix' to automatically remove it from {transform.root.gameObject.name} or 'Manual-Fix' to fix it yourself in the hierarchy view."; + if (EditorUtility.DisplayDialog("Invalid Nested NetworkManager", message, "Auto-Fix", "Manual-Fix")) + { + transform.parent = null; + isParented = false; + } + } + else + { + Debug.LogError(message); + } + + if (!s_LastKnownNetworkManagerParents.ContainsKey(networkManager) && isParented) + { + s_LastKnownNetworkManagerParents.Add(networkManager, networkManager.transform.root); + } + } + return isParented; + } + } +#endif +} diff --git a/Editor/NetworkManagerHelper.cs.meta b/Editor/NetworkManagerHelper.cs.meta new file mode 100644 index 0000000..995a44d --- /dev/null +++ b/Editor/NetworkManagerHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b26b53dc28ae1b5488bbbecc3e499bbc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md index 51e6bb0..91b440f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Forums](https://img.shields.io/badge/unity--forums-multiplayer-blue)](https://forum.unity.com/forums/multiplayer.26/) [![Discord](https://img.shields.io/discord/449263083769036810.svg?label=discord&logo=discord&color=informational)](https://discord.gg/FM8SE9E) [![Website](https://img.shields.io/badge/docs-website-informational.svg)](https://docs-multiplayer.unity3d.com/) [![Api](https://img.shields.io/badge/docs-api-informational.svg)](https://docs-multiplayer.unity3d.com/docs/mlapi-api/introduction) -Netcode for GameObjects provides networking capabilities to GameObject & MonoBehaviour Unity workflows. The framework is interoperable with many low-level transports, including the official [Unity Transport Package](https://docs.unity3d.com/Packages/com.unity.transport@1.0/manual/index.html). +Netcode for GameObjects provides networking capabilities to GameObject & MonoBehaviour Unity workflows. The framework is interoperable with many low-level transports, including the official [Unity Transport Package](https://docs-multiplayer.unity3d.com/transport/1.0.0/introduction). ### Getting Started Visit the [Multiplayer Docs Site](https://docs-multiplayer.unity3d.com/) for package & API documentation, as well as information about several samples which leverage the Netcode for GameObjects package. diff --git a/Runtime/Core/NetworkManager.cs b/Runtime/Core/NetworkManager.cs index 097d9bb..65a54fc 100644 --- a/Runtime/Core/NetworkManager.cs +++ b/Runtime/Core/NetworkManager.cs @@ -197,11 +197,6 @@ public GameObject GetNetworkPrefabOverride(GameObject gameObject) public NetworkTime ServerTime => NetworkTickSystem?.ServerTime ?? default; - /// - /// Gets or sets if the NetworkManager should be marked as DontDestroyOnLoad - /// - [HideInInspector] public bool DontDestroy = true; - /// /// Gets or sets if the application should be set to run in background /// @@ -490,6 +485,13 @@ private void OnValidate() private void Initialize(bool server) { + // Don't allow the user to start a network session if the NetworkManager is + // still parented under another GameObject + if (NetworkManagerCheckForParent(true)) + { + return; + } + if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) { NetworkLog.LogInfo(nameof(Initialize)); @@ -941,11 +943,6 @@ public void SetSingleton() private void OnEnable() { - if (DontDestroy) - { - DontDestroyOnLoad(gameObject); - } - if (RunInBackground) { Application.runInBackground = true; @@ -955,6 +952,11 @@ private void OnEnable() { SetSingleton(); } + + if (!NetworkManagerCheckForParent()) + { + DontDestroyOnLoad(gameObject); + } } private void Awake() @@ -962,6 +964,48 @@ private void Awake() UnityEngine.SceneManagement.SceneManager.sceneUnloaded += OnSceneUnloaded; } + /// + /// Handle runtime detection for parenting the NetworkManager's GameObject under another GameObject + /// + private void OnTransformParentChanged() + { + NetworkManagerCheckForParent(); + } + + /// + /// Determines if the NetworkManager's GameObject is parented under another GameObject and + /// notifies the user that this is not allowed for the NetworkManager. + /// + internal bool NetworkManagerCheckForParent(bool ignoreNetworkManagerCache = false) + { +#if UNITY_EDITOR + var isParented = NetworkManagerHelper.NotifyUserOfNestedNetworkManager(this, ignoreNetworkManagerCache); +#else + var isParented = transform.root != transform; + if (isParented) + { + throw new Exception(GenerateNestedNetworkManagerMessage(transform)); + } +#endif + return isParented; + } + + static internal string GenerateNestedNetworkManagerMessage(Transform transform) + { + return $"{transform.name} is nested under {transform.root.name}. NetworkManager cannot be nested.\n"; + } + +#if UNITY_EDITOR + static internal INetworkManagerHelper NetworkManagerHelper; + /// + /// Interface for NetworkManagerHelper + /// + internal interface INetworkManagerHelper + { + bool NotifyUserOfNestedNetworkManager(NetworkManager networkManager, bool ignoreNetworkManagerCache = false, bool editorTest = false); + } +#endif + // Ensures that the NetworkManager is cleaned up before OnDestroy is run on NetworkObjects and NetworkBehaviours when unloading a scene with a NetworkManager private void OnSceneUnloaded(Scene scene) { diff --git a/Runtime/NetworkVariable/Collections/NetworkList.cs b/Runtime/NetworkVariable/Collections/NetworkList.cs index 8cae300..fb480d4 100644 --- a/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -272,18 +272,22 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) { reader.ReadValueSafe(out int index); reader.ReadValueSafe(out T value); - if (index < m_List.Length) + if (index >= m_List.Length) { - m_List[index] = value; + throw new Exception("Shouldn't be here, index is higher than list length"); } + var previousValue = m_List[index]; + m_List[index] = value; + if (OnListChanged != null) { OnListChanged(new NetworkListEvent { Type = eventType, Index = index, - Value = value + Value = value, + PreviousValue = previousValue }); } @@ -293,7 +297,8 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) { Type = eventType, Index = index, - Value = value + Value = value, + PreviousValue = previousValue }); } } @@ -368,7 +373,7 @@ public void Clear() public bool Contains(T item) { int index = NativeArrayExtensions.IndexOf(m_List, item); - return index == -1; + return index != -1; } /// @@ -528,6 +533,11 @@ public enum EventType : byte /// public T Value; + /// + /// The previous value when "Value" has changed, if available. + /// + public T PreviousValue; + /// /// the index changed, added or removed if available /// diff --git a/Runtime/SceneManagement/NetworkSceneManager.cs b/Runtime/SceneManagement/NetworkSceneManager.cs index ec1ef0a..c40b7b5 100644 --- a/Runtime/SceneManagement/NetworkSceneManager.cs +++ b/Runtime/SceneManagement/NetworkSceneManager.cs @@ -565,20 +565,8 @@ internal NetworkSceneManager(NetworkManager networkManager) GenerateScenesInBuild(); - // If NetworkManager has this set to true, then we can get the DDOL (DontDestroyOnLoad) from its GaemObject - if (networkManager.DontDestroy) - { - DontDestroyOnLoadScene = networkManager.gameObject.scene; - } - else - { - // Otherwise, we have to create a GameObject and move it into the DDOL in order to - // register the DDOL scene handle with NetworkSceneManager - var myDDOLObject = new GameObject("DDOL-NWSM"); - UnityEngine.Object.DontDestroyOnLoad(myDDOLObject); - DontDestroyOnLoadScene = myDDOLObject.scene; - UnityEngine.Object.Destroy(myDDOLObject); - } + // Since NetworkManager is now always migrated to the DDOL we will use this to get the DDOL scene + DontDestroyOnLoadScene = networkManager.gameObject.scene; ServerSceneHandleToClientSceneHandle.Add(DontDestroyOnLoadScene.handle, DontDestroyOnLoadScene.handle); ScenesLoaded.Add(DontDestroyOnLoadScene.handle, DontDestroyOnLoadScene); diff --git a/Runtime/Timing/NetworkTime.cs b/Runtime/Timing/NetworkTime.cs index f247189..0f0f1d9 100644 --- a/Runtime/Timing/NetworkTime.cs +++ b/Runtime/Timing/NetworkTime.cs @@ -114,6 +114,11 @@ private void UpdateCache() { double d = m_TimeSec / m_TickInterval; m_CachedTick = (int)d; + // This check is needed due to double division imprecision of large numbers + if ((d - m_CachedTick) >= 0.999999999999) + { + m_CachedTick++; + } m_CachedTickOffset = ((d - Math.Truncate(d)) * m_TickInterval); // This handles negative time, decreases tick by 1 and makes offset positive. diff --git a/Samples~/ClientNetworkTransform/Scripts/ClientNetworkTransform.cs b/Samples~/ClientNetworkTransform/Scripts/ClientNetworkTransform.cs index e1bdca9..824f1a3 100644 --- a/Samples~/ClientNetworkTransform/Scripts/ClientNetworkTransform.cs +++ b/Samples~/ClientNetworkTransform/Scripts/ClientNetworkTransform.cs @@ -26,6 +26,7 @@ public override void OnNetworkSpawn() protected override void Update() { + CanCommitToTransform = IsOwner; base.Update(); if (NetworkManager.Singleton != null && (NetworkManager.Singleton.IsConnectedClient || NetworkManager.Singleton.IsListening)) { diff --git a/Tests/Editor/NetworkManagerConfigurationTests.cs b/Tests/Editor/NetworkManagerConfigurationTests.cs new file mode 100644 index 0000000..7f36b2c --- /dev/null +++ b/Tests/Editor/NetworkManagerConfigurationTests.cs @@ -0,0 +1,38 @@ +using NUnit.Framework; +using UnityEngine; +using Unity.Netcode.Editor; +using UnityEngine.TestTools; + +namespace Unity.Netcode.EditorTests +{ + public class NetworkManagerConfigurationTests + { + /// + /// Does a simple check to make sure the nested network manager will + /// notify the user when in the editor. This is just a unit test to + /// validate this is functioning + /// + [Test] + public void NestedNetworkManagerCheck() + { + var parent = new GameObject("ParentObject"); + var networkManagerObject = new GameObject(nameof(NestedNetworkManagerCheck)); + var networkManager = networkManagerObject.AddComponent(); + + // Make our NetworkManager's GameObject nested + networkManagerObject.transform.parent = parent.transform; + + // Pre-generate the error message we are expecting to see + var messageToCheck = NetworkManager.GenerateNestedNetworkManagerMessage(networkManagerObject.transform); + + // Trap for the nested NetworkManager exception + LogAssert.Expect(LogType.Error, messageToCheck); + + // Since this is an in-editor test, we must force this invocation + NetworkManagerHelper.Singleton.NotifyUserOfNestedNetworkManager(networkManager, false, true); + + // Clean up + Object.DestroyImmediate(parent); + } + } +} diff --git a/Tests/Editor/NetworkManagerConfigurationTests.cs.meta b/Tests/Editor/NetworkManagerConfigurationTests.cs.meta new file mode 100644 index 0000000..5929d99 --- /dev/null +++ b/Tests/Editor/NetworkManagerConfigurationTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b84044fccbd3cd49908f0efd5719347 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/Timing/NetworkTimeTests.cs b/Tests/Editor/Timing/NetworkTimeTests.cs index c7a3850..be53a0d 100644 --- a/Tests/Editor/Timing/NetworkTimeTests.cs +++ b/Tests/Editor/Timing/NetworkTimeTests.cs @@ -198,6 +198,39 @@ private void NetworkTimeAdvanceTestInternal(IEnumerable steps, uint tickR Assert.IsTrue(Approximately(startTime.Time, (startTime2 - dif).Time, maxAcceptableTotalOffset)); } + [Test] + public void NetworkTickAdvanceTest() + { + var shortSteps = Enumerable.Repeat(1 / 30f, 1000); + NetworkTickAdvanceTestInternal(shortSteps, 30, 0.0f, 0.0f); + } + + private NetworkTickSystem m_TickSystem; + private NetworkTimeSystem m_TimeSystem; + private int m_PreviousTick; + + private void NetworkTickAdvanceTestInternal(IEnumerable steps, uint tickRate, float start, float start2 = 0f) + { + m_PreviousTick = 0; + m_TickSystem = new NetworkTickSystem(tickRate, start, start2); + m_TimeSystem = NetworkTimeSystem.ServerTimeSystem(); + + m_TickSystem.Tick += TickUpdate; + foreach (var step in steps) + { + m_TimeSystem.Advance(step); + m_TickSystem.UpdateTick(m_TimeSystem.LocalTime, m_TimeSystem.ServerTime); + } + } + + private void TickUpdate() + { + // Make sure our tick is precisely 1 + m_PreviousTick + Assert.IsTrue(m_TickSystem.LocalTime.Tick == m_PreviousTick + 1); + // Assign the m_PreviousTick value for next tick check + m_PreviousTick = m_TickSystem.LocalTime.Tick; + } + private static bool Approximately(double a, double b, double epsilon = 0.000001d) { var dif = Math.Abs(a - b); diff --git a/Tests/Runtime/NestedNetworkManagerTests.cs b/Tests/Runtime/NestedNetworkManagerTests.cs new file mode 100644 index 0000000..9e0ea70 --- /dev/null +++ b/Tests/Runtime/NestedNetworkManagerTests.cs @@ -0,0 +1,37 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.TestTools; +using Unity.Netcode; +using Unity.Netcode.RuntimeTests; +using Object = UnityEngine.Object; + +namespace TestProject.RuntimeTests +{ + public class NestedNetworkManagerTests + { + [UnityTest] + public IEnumerator CheckNestedNetworkManager() + { + var parent = new GameObject("ParentObject"); + var networkManagerObject = new GameObject(nameof(CheckNestedNetworkManager)); + + // Make our NetworkManager's GameObject nested + networkManagerObject.transform.parent = parent.transform; + + // Pre-generate the error message we are expecting to see + var messageToCheck = NetworkManager.GenerateNestedNetworkManagerMessage(networkManagerObject.transform); + var transport = networkManagerObject.AddComponent(); + var networkManager = networkManagerObject.AddComponent(); + networkManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; + // Trap for the nested NetworkManager exception + LogAssert.Expect(LogType.Error, messageToCheck); + + yield return new WaitForSeconds(0.02f); + + // Clean up + Object.Destroy(parent); + + yield return null; + } + } +} diff --git a/Tests/Runtime/NestedNetworkManagerTests.cs.meta b/Tests/Runtime/NestedNetworkManagerTests.cs.meta new file mode 100644 index 0000000..0cff7a3 --- /dev/null +++ b/Tests/Runtime/NestedNetworkManagerTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 738f6d8fc9319fe42a986c2f43989642 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime/NetworkVariableTests.cs b/Tests/Runtime/NetworkVariableTests.cs index 4325a7e..306ec31 100644 --- a/Tests/Runtime/NetworkVariableTests.cs +++ b/Tests/Runtime/NetworkVariableTests.cs @@ -224,8 +224,8 @@ public IEnumerator NetworkListContains([Values(true, false)] bool useHost) { return m_Player1OnServer.TheList.Count == 1 && m_Player1OnClient1.TheList.Count == 1 && - m_Player1OnServer.TheList.Contains(k_TestKey1) && - m_Player1OnClient1.TheList.Contains(k_TestKey1); + m_Player1OnServer.TheList.Contains(k_TestVal1) && + m_Player1OnClient1.TheList.Contains(k_TestVal1); } ); } @@ -328,6 +328,58 @@ public IEnumerator NetworkListArrayOperator([Values(true, false)] bool useHost) ); } + + [UnityTest] + public IEnumerator NetworkListValueUpdate([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheList.Add(k_TestVal1); + }, + () => + { + return m_Player1OnServer.TheList.Count == 1 && + m_Player1OnClient1.TheList.Count == 1 && + m_Player1OnServer.TheList[0] == k_TestVal1 && + m_Player1OnClient1.TheList[0] == k_TestVal1; + } + ); + + var testSucceeded = false; + + void TestValueUpdatedCallback(NetworkListEvent changedEvent) + { + testSucceeded = changedEvent.PreviousValue == k_TestVal1 && + changedEvent.Value == k_TestVal3; + } + + try + { + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheList[0] = k_TestVal3; + m_Player1OnClient1.TheList.OnListChanged += TestValueUpdatedCallback; + }, + () => + { + return m_Player1OnServer.TheList.Count == 1 && + m_Player1OnClient1.TheList.Count == 1 && + m_Player1OnServer.TheList[0] == k_TestVal3 && + m_Player1OnClient1.TheList[0] == k_TestVal3; + } + ); + } + finally + { + m_Player1OnClient1.TheList.OnListChanged -= TestValueUpdatedCallback; + } + + Assert.That(testSucceeded); + } + [Test] public void NetworkListIEnumerator([Values(true, false)] bool useHost) { diff --git a/package.json b/package.json index b858cf0..6139d91 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "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.4", + "version": "1.0.0-pre.5", "unity": "2020.3", "dependencies": { "com.unity.modules.animation": "1.0.0", @@ -12,12 +12,12 @@ "com.unity.collections": "1.1.0" }, "upmCi": { - "footprint": "28fd203207af71c78d6aaba679e94c5ead807529" + "footprint": "770504b1f691c766a300b616c1d8106335265f3c" }, "repository": { "url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git", "type": "git", - "revision": "b14204cd059fb90f4a64319824105619f317d591" + "revision": "d1f990d97b80d49ce12fce7357cbd5f6b794ce01" }, "samples": [ {