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": [
{