com.unity.netcode.gameobjects@1.0.0-pre.10
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.10] - 2022-06-21 ### Added - Added a new `OnTransportFailure` callback to `NetworkManager`. This callback is invoked when the manager's `NetworkTransport` encounters an unrecoverable error. Transport failures also cause the `NetworkManager` to shut down. Currently, this is only used by `UnityTransport` to signal a timeout of its connection to the Unity Relay servers. (#1994) - Added `NetworkEvent.TransportFailure`, which can be used by implementations of `NetworkTransport` to signal to `NetworkManager` that an unrecoverable error was encountered. (#1994) - Added test to ensure a warning occurs when nesting NetworkObjects in a NetworkPrefab (#1969) - Added `NetworkManager.RemoveNetworkPrefab(...)` to remove a prefab from the prefabs list (#1950) ### Changed - Updated `UnityTransport` dependency on `com.unity.transport` to 1.1.0. (#2025) - (API Breaking) `ConnectionApprovalCallback` is no longer an `event` and will not allow more than 1 handler registered at a time. Also, `ConnectionApprovalCallback` is now a `Func<>` taking `ConnectionApprovalRequest` in and returning `ConnectionApprovalResponse` back out (#1972) ### Removed ### Fixed - Fixed issue where dynamically spawned `NetworkObject`s could throw an exception if the scene of origin handle was zero (0) and the `NetworkObject` was already spawned. (#2017) - Fixed issue where `NetworkObject.Observers` was not being cleared when despawned. (#2009) - Fixed `NetworkAnimator` could not run in the server authoritative mode. (#2003) - Fixed issue where late joining clients would get a soft synchronization error if any in-scene placed NetworkObjects were parented under another `NetworkObject`. (#1985) - Fixed issue where `NetworkBehaviourReference` would throw a type cast exception if using `NetworkBehaviourReference.TryGet` and the component type was not found. (#1984) - Fixed `NetworkSceneManager` was not sending scene event notifications for the currently active scene and any additively loaded scenes when loading a new scene in `LoadSceneMode.Single` mode. (#1975) - Fixed issue where one or more clients disconnecting during a scene event would cause `LoadEventCompleted` or `UnloadEventCompleted` to wait until the `NetworkConfig.LoadSceneTimeOut` period before being triggered. (#1973) - Fixed issues when multiple `ConnectionApprovalCallback`s were registered (#1972) - Fixed a regression in serialization support: `FixedString`, `Vector2Int`, and `Vector3Int` types can now be used in NetworkVariables and RPCs again without requiring a `ForceNetworkSerializeByMemcpy<>` wrapper. (#1961) - Fixed generic types that inherit from NetworkBehaviour causing crashes at compile time. (#1976) - Fixed endless dialog boxes when adding a `NetworkBehaviour` to a `NetworkManager` or vice-versa. (#1947) - Fixed `NetworkAnimator` issue where it was only synchronizing parameters if the layer or state changed or was transitioning between states. (#1946) - Fixed `NetworkAnimator` issue where when it did detect a parameter had changed it would send all parameters as opposed to only the parameters that changed. (#1946) - Fixed `NetworkAnimator` issue where it was not always disposing the `NativeArray` that is allocated when spawned. (#1946) - Fixed `NetworkAnimator` issue where it was not taking the animation speed or state speed multiplier into consideration. (#1946) - Fixed `NetworkAnimator` issue where it was not properly synchronizing late joining clients if they joined while `Animator` was transitioning between states. (#1946) - Fixed `NetworkAnimator` issue where the server was not relaying changes to non-owner clients when a client was the owner. (#1946) - Fixed issue where the `PacketLoss` metric for tools would return the packet loss over a connection lifetime instead of a single frame. (#2004)
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@@ -16,7 +17,12 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
/// </summary>
|
||||
public abstract class NetcodeIntegrationTest
|
||||
{
|
||||
protected static TimeoutHelper s_GlobalTimeoutHelper = new TimeoutHelper(4.0f);
|
||||
/// <summary>
|
||||
/// Used to determine if a NetcodeIntegrationTest is currently running to
|
||||
/// determine how clients will load scenes
|
||||
/// </summary>
|
||||
internal static bool IsRunning { get; private set; }
|
||||
protected static TimeoutHelper s_GlobalTimeoutHelper = new TimeoutHelper(8.0f);
|
||||
protected static WaitForSeconds s_DefaultWaitForTick = new WaitForSeconds(1.0f / k_DefaultTickRate);
|
||||
|
||||
/// <summary>
|
||||
@@ -74,9 +80,11 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
}
|
||||
}
|
||||
|
||||
protected int TotalClients => m_UseHost ? NumberOfClients + 1 : NumberOfClients;
|
||||
protected int TotalClients => m_UseHost ? m_NumberOfClients + 1 : m_NumberOfClients;
|
||||
|
||||
protected const uint k_DefaultTickRate = 30;
|
||||
|
||||
private int m_NumberOfClients;
|
||||
protected abstract int NumberOfClients { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -119,7 +127,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
|
||||
private NetworkManagerInstatiationMode m_NetworkManagerInstatiationMode;
|
||||
|
||||
private bool m_EnableVerboseDebug;
|
||||
protected bool m_EnableVerboseDebug { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to display the various integration test
|
||||
@@ -165,8 +173,11 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetup()
|
||||
{
|
||||
Application.runInBackground = true;
|
||||
m_NumberOfClients = NumberOfClients;
|
||||
IsRunning = true;
|
||||
m_EnableVerboseDebug = OnSetVerboseDebug();
|
||||
|
||||
IntegrationTestSceneHandler.VerboseDebugMode = m_EnableVerboseDebug;
|
||||
VerboseDebug($"Entering {nameof(OneTimeSetup)}");
|
||||
|
||||
m_NetworkManagerInstatiationMode = OnSetIntegrationTestMode();
|
||||
@@ -248,6 +259,61 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
CreateServerAndClients(NumberOfClients);
|
||||
}
|
||||
|
||||
protected virtual void OnNewClientCreated(NetworkManager networkManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void OnNewClientStartedAndConnected(NetworkManager networkManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void AddRemoveNetworkManager(NetworkManager networkManager, bool addNetworkManager)
|
||||
{
|
||||
var clientNetworkManagersList = new List<NetworkManager>(m_ClientNetworkManagers);
|
||||
if (addNetworkManager)
|
||||
{
|
||||
clientNetworkManagersList.Add(networkManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientNetworkManagersList.Remove(networkManager);
|
||||
}
|
||||
m_ClientNetworkManagers = clientNetworkManagersList.ToArray();
|
||||
m_NumberOfClients = clientNetworkManagersList.Count;
|
||||
}
|
||||
|
||||
protected IEnumerator CreateAndStartNewClient()
|
||||
{
|
||||
var networkManager = NetcodeIntegrationTestHelpers.CreateNewClient(m_ClientNetworkManagers.Length);
|
||||
networkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
|
||||
// Notification that the new client (NetworkManager) has been created
|
||||
// in the event any modifications need to be made before starting the client
|
||||
OnNewClientCreated(networkManager);
|
||||
|
||||
NetcodeIntegrationTestHelpers.StartOneClient(networkManager);
|
||||
AddRemoveNetworkManager(networkManager, true);
|
||||
// Wait for the new client to connect
|
||||
yield return WaitForClientsConnectedOrTimeOut();
|
||||
if (s_GlobalTimeoutHelper.TimedOut)
|
||||
{
|
||||
AddRemoveNetworkManager(networkManager, false);
|
||||
Object.Destroy(networkManager.gameObject);
|
||||
}
|
||||
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for the new client to be connected!");
|
||||
ClientNetworkManagerPostStart(networkManager);
|
||||
VerboseDebug($"[{networkManager.name}] Created and connected!");
|
||||
}
|
||||
|
||||
protected IEnumerator StopOneClient(NetworkManager networkManager, bool destroy = false)
|
||||
{
|
||||
NetcodeIntegrationTestHelpers.StopOneClient(networkManager, destroy);
|
||||
AddRemoveNetworkManager(networkManager, false);
|
||||
yield return WaitForConditionOrTimeOut(() => !networkManager.IsConnectedClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the server and clients
|
||||
/// </summary>
|
||||
@@ -315,6 +381,54 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
yield return null;
|
||||
}
|
||||
|
||||
private void ClientNetworkManagerPostStart(NetworkManager networkManager)
|
||||
{
|
||||
networkManager.name = $"NetworkManager - Client - {networkManager.LocalClientId}";
|
||||
Assert.NotNull(networkManager.LocalClient.PlayerObject, $"{nameof(StartServerAndClients)} detected that client {networkManager.LocalClientId} does not have an assigned player NetworkObject!");
|
||||
|
||||
// Get all player instances for the current client NetworkManager instance
|
||||
var clientPlayerClones = Object.FindObjectsOfType<NetworkObject>().Where((c) => c.IsPlayerObject && c.OwnerClientId == networkManager.LocalClientId);
|
||||
// Add this player instance to each client player entry
|
||||
foreach (var playerNetworkObject in clientPlayerClones)
|
||||
{
|
||||
// When the server is not the host this needs to be done
|
||||
if (!m_PlayerNetworkObjects.ContainsKey(playerNetworkObject.NetworkManager.LocalClientId))
|
||||
{
|
||||
m_PlayerNetworkObjects.Add(playerNetworkObject.NetworkManager.LocalClientId, new Dictionary<ulong, NetworkObject>());
|
||||
}
|
||||
if (!m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].ContainsKey(networkManager.LocalClientId))
|
||||
{
|
||||
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(networkManager.LocalClientId, playerNetworkObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ClientNetworkManagerPostStartInit()
|
||||
{
|
||||
// Creates a dictionary for all player instances client and server relative
|
||||
// This provides a simpler way to get a specific player instance relative to a client instance
|
||||
foreach (var networkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
ClientNetworkManagerPostStart(networkManager);
|
||||
}
|
||||
if (m_UseHost)
|
||||
{
|
||||
var clientSideServerPlayerClones = Object.FindObjectsOfType<NetworkObject>().Where((c) => c.IsPlayerObject && c.OwnerClientId == m_ServerNetworkManager.LocalClientId);
|
||||
foreach (var playerNetworkObject in clientSideServerPlayerClones)
|
||||
{
|
||||
// When the server is not the host this needs to be done
|
||||
if (!m_PlayerNetworkObjects.ContainsKey(playerNetworkObject.NetworkManager.LocalClientId))
|
||||
{
|
||||
m_PlayerNetworkObjects.Add(playerNetworkObject.NetworkManager.LocalClientId, new Dictionary<ulong, NetworkObject>());
|
||||
}
|
||||
if (!m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].ContainsKey(m_ServerNetworkManager.LocalClientId))
|
||||
{
|
||||
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(m_ServerNetworkManager.LocalClientId, playerNetworkObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This starts the server and clients as long as <see cref="CanStartServerAndClients"/>
|
||||
/// returns true.
|
||||
@@ -340,8 +454,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
|
||||
// Wait for all clients to connect
|
||||
yield return WaitForClientsConnectedOrTimeOut();
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!");
|
||||
AssertOnTimeout($"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!");
|
||||
|
||||
if (m_UseHost || m_ServerNetworkManager.IsHost)
|
||||
{
|
||||
@@ -357,25 +470,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a dictionary for all player instances client and server relative
|
||||
// This provides a simpler way to get a specific player instance relative to a client instance
|
||||
foreach (var networkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
Assert.NotNull(networkManager.LocalClient.PlayerObject, $"{nameof(StartServerAndClients)} detected that client {networkManager.LocalClientId} does not have an assigned player NetworkObject!");
|
||||
|
||||
// Get all player instances for the current client NetworkManager instance
|
||||
var clientPlayerClones = Object.FindObjectsOfType<NetworkObject>().Where((c) => c.IsPlayerObject && c.OwnerClientId == networkManager.LocalClientId);
|
||||
// Add this player instance to each client player entry
|
||||
foreach (var playerNetworkObject in clientPlayerClones)
|
||||
{
|
||||
// When the server is not the host this needs to be done
|
||||
if (!m_PlayerNetworkObjects.ContainsKey(playerNetworkObject.NetworkManager.LocalClientId))
|
||||
{
|
||||
m_PlayerNetworkObjects.Add(playerNetworkObject.NetworkManager.LocalClientId, new Dictionary<ulong, NetworkObject>());
|
||||
}
|
||||
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(networkManager.LocalClientId, playerNetworkObject);
|
||||
}
|
||||
}
|
||||
ClientNetworkManagerPostStartInit();
|
||||
|
||||
// Notification that at this time the server and client(s) are instantiated,
|
||||
// started, and connected on both sides.
|
||||
@@ -409,11 +504,9 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
/// </summary>
|
||||
protected void DeRegisterSceneManagerHandler()
|
||||
{
|
||||
if (NetcodeIntegrationTestHelpers.ClientSceneHandler != null)
|
||||
{
|
||||
NetcodeIntegrationTestHelpers.ClientSceneHandler.CanClientsLoad -= ClientSceneHandler_CanClientsLoad;
|
||||
NetcodeIntegrationTestHelpers.ClientSceneHandler.CanClientsUnload -= ClientSceneHandler_CanClientsUnload;
|
||||
}
|
||||
IntegrationTestSceneHandler.CanClientsLoad -= ClientSceneHandler_CanClientsLoad;
|
||||
IntegrationTestSceneHandler.CanClientsUnload -= ClientSceneHandler_CanClientsUnload;
|
||||
IntegrationTestSceneHandler.NetworkManagers.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -423,11 +516,9 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
/// </summary>
|
||||
protected void RegisterSceneManagerHandler()
|
||||
{
|
||||
if (NetcodeIntegrationTestHelpers.ClientSceneHandler != null)
|
||||
{
|
||||
NetcodeIntegrationTestHelpers.ClientSceneHandler.CanClientsLoad += ClientSceneHandler_CanClientsLoad;
|
||||
NetcodeIntegrationTestHelpers.ClientSceneHandler.CanClientsUnload += ClientSceneHandler_CanClientsUnload;
|
||||
}
|
||||
IntegrationTestSceneHandler.CanClientsLoad += ClientSceneHandler_CanClientsLoad;
|
||||
IntegrationTestSceneHandler.CanClientsUnload += ClientSceneHandler_CanClientsUnload;
|
||||
NetcodeIntegrationTestHelpers.RegisterSceneManagerHandler(m_ServerNetworkManager, true);
|
||||
}
|
||||
|
||||
private bool ClientSceneHandler_CanClientsUnload()
|
||||
@@ -440,6 +531,11 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
return CanClientsLoad();
|
||||
}
|
||||
|
||||
protected bool OnCanSceneCleanUpUnload(Scene scene)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This shuts down all NetworkManager instances registered via the
|
||||
/// <see cref="NetcodeIntegrationTestHelpers"/> class and cleans up
|
||||
@@ -452,11 +548,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
// Shutdown and clean up both of our NetworkManager instances
|
||||
try
|
||||
{
|
||||
if (NetcodeIntegrationTestHelpers.ClientSceneHandler != null)
|
||||
{
|
||||
NetcodeIntegrationTestHelpers.ClientSceneHandler.CanClientsLoad -= ClientSceneHandler_CanClientsLoad;
|
||||
NetcodeIntegrationTestHelpers.ClientSceneHandler.CanClientsUnload -= ClientSceneHandler_CanClientsUnload;
|
||||
}
|
||||
DeRegisterSceneManagerHandler();
|
||||
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
|
||||
@@ -476,6 +568,8 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
// Cleanup any remaining NetworkObjects
|
||||
DestroySceneNetworkObjects();
|
||||
|
||||
UnloadRemainingScenes();
|
||||
|
||||
// reset the m_ServerWaitForTick for the next test to initialize
|
||||
s_DefaultWaitForTick = new WaitForSeconds(1.0f / k_DefaultTickRate);
|
||||
VerboseDebug($"Exiting {nameof(ShutdownAndCleanUp)}");
|
||||
@@ -517,6 +611,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
[OneTimeTearDown]
|
||||
public void OneTimeTearDown()
|
||||
{
|
||||
IntegrationTestSceneHandler.VerboseDebugMode = false;
|
||||
VerboseDebug($"Entering {nameof(OneTimeTearDown)}");
|
||||
OnOneTimeTearDown();
|
||||
|
||||
@@ -528,7 +623,11 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
// Disable NetcodeIntegrationTest auto-label feature
|
||||
NetcodeIntegrationTestHelpers.RegisterNetcodeIntegrationTest(false);
|
||||
|
||||
UnloadRemainingScenes();
|
||||
|
||||
VerboseDebug($"Exiting {nameof(OneTimeTearDown)}");
|
||||
|
||||
IsRunning = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -783,5 +882,32 @@ namespace Unity.Netcode.TestHelpers.Runtime
|
||||
{
|
||||
m_UseHost = hostOrServer == HostOrServer.Host ? true : false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Just a helper function to avoid having to write the entire assert just to check if you
|
||||
/// timed out.
|
||||
/// </summary>
|
||||
protected void AssertOnTimeout(string timeOutErrorMessage, TimeoutHelper assignedTimeoutHelper = null)
|
||||
{
|
||||
var timeoutHelper = assignedTimeoutHelper != null ? assignedTimeoutHelper : s_GlobalTimeoutHelper;
|
||||
Assert.False(timeoutHelper.TimedOut, timeOutErrorMessage);
|
||||
}
|
||||
|
||||
private void UnloadRemainingScenes()
|
||||
{
|
||||
// Unload any remaining scenes loaded but the test runner scene
|
||||
// Note: Some tests only unload the server-side instance, and this
|
||||
// just assures no currently loaded scenes will impact the next test
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
var scene = SceneManager.GetSceneAt(i);
|
||||
if (!scene.IsValid() || !scene.isLoaded || scene.name.Contains(NetcodeIntegrationTestHelpers.FirstPartOfTestRunnerSceneName) || !OnCanSceneCleanUpUnload(scene))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
VerboseDebug($"Unloading scene {scene.name}-{scene.handle}");
|
||||
var asyncOperation = SceneManager.UnloadSceneAsync(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user