com.unity.netcode.gameobjects@1.0.0-pre.8

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.8] - 2022-04-27

### Changed

- `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList<T>`) 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<T>`. (#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).

### Fixed

- Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890)
- Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884)
- 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 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)
This commit is contained in:
Unity Technologies
2022-04-27 00:00:00 +00:00
parent 60e2dabef4
commit add668dfd2
119 changed files with 4434 additions and 1801 deletions

View File

@@ -3,11 +3,7 @@ using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Unity.Netcode.TestHelpers.Runtime;
#if UNITY_UNET_PRESENT
using Unity.Netcode.Transports.UNET;
#else
using Unity.Netcode.Transports.UTP;
#endif
namespace Unity.Netcode.RuntimeTests
{
@@ -26,15 +22,13 @@ namespace Unity.Netcode.RuntimeTests
m_NetworkManagerGameObject = new GameObject();
m_ClientNetworkManager = m_NetworkManagerGameObject.AddComponent<NetworkManager>();
m_ClientNetworkManager.NetworkConfig = new NetworkConfig();
#if UNITY_UNET_PRESENT
m_TimeoutHelper = new TimeoutHelper(30);
m_ClientNetworkManager.NetworkConfig.NetworkTransport = m_NetworkManagerGameObject.AddComponent<UNetTransport>();
#else
// Default is 1000ms per connection attempt and 60 connection attempts (60s)
// Currently there is no easy way to set these values other than in-editor
m_TimeoutHelper = new TimeoutHelper(70);
m_ClientNetworkManager.NetworkConfig.NetworkTransport = m_NetworkManagerGameObject.AddComponent<UnityTransport>();
#endif
var unityTransport = m_NetworkManagerGameObject.AddComponent<UnityTransport>();
unityTransport.ConnectTimeoutMS = 1000;
unityTransport.MaxConnectAttempts = 1;
m_TimeoutHelper = new TimeoutHelper(2);
m_ClientNetworkManager.NetworkConfig.NetworkTransport = unityTransport;
}
[UnityTest]
@@ -46,10 +40,9 @@ namespace Unity.Netcode.RuntimeTests
// Only start the client (so it will timeout)
m_ClientNetworkManager.StartClient();
#if !UNITY_UNET_PRESENT
// Unity Transport throws an error when it times out
LogAssert.Expect(LogType.Error, "Failed to connect to server.");
#endif
yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => m_WasDisconnected, m_TimeoutHelper);
Assert.False(m_TimeoutHelper.TimedOut, "Timed out waiting for client to timeout waiting to connect!");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b3d771dc2a334464ad96e8c66ac776cc
timeCreated: 1650295945

View File

@@ -9,6 +9,8 @@ namespace Unity.Netcode.RuntimeTests
{
public class DisconnectTests
{
private bool m_ClientDisconnected;
[UnityTest]
public IEnumerator RemoteDisconnectPlayerObjectCleanup()
{
@@ -38,11 +40,14 @@ namespace Unity.Netcode.RuntimeTests
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(server);
// disconnect the remote client
m_ClientDisconnected = false;
server.DisconnectClient(clients[0].LocalClientId);
clients[0].OnClientDisconnectCallback += OnClientDisconnectCallback;
var timeoutHelper = new TimeoutHelper();
yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => m_ClientDisconnected, timeoutHelper);
// wait 1 frame because destroys are delayed
var nextFrameNumber = Time.frameCount + 1;
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
// We need to do this to remove other associated client properties/values from NetcodeIntegrationTestHelpers
NetcodeIntegrationTestHelpers.StopOneClient(clients[0]);
// ensure the object was destroyed
Assert.False(server.SpawnManager.SpawnedObjects.Any(x => x.Value.IsPlayerObject && x.Value.OwnerClientId == clients[0].LocalClientId));
@@ -50,5 +55,10 @@ namespace Unity.Netcode.RuntimeTests
// cleanup
NetcodeIntegrationTestHelpers.Destroy();
}
private void OnClientDisconnectCallback(ulong obj)
{
m_ClientDisconnected = true;
}
}
}

View File

@@ -27,7 +27,7 @@ namespace Unity.Netcode.RuntimeTests
public IEnumerator NamedMessageIsReceivedOnClientWithContent()
{
var messageName = Guid.NewGuid().ToString();
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
@@ -39,7 +39,7 @@ namespace Unity.Netcode.RuntimeTests
}
ulong receivedMessageSender = 0;
var receivedMessageContent = new Guid();
var receivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(
messageName,
(ulong sender, FastBufferReader reader) =>
@@ -51,7 +51,7 @@ namespace Unity.Netcode.RuntimeTests
yield return new WaitForSeconds(0.2f);
Assert.AreEqual(messageContent, receivedMessageContent);
Assert.AreEqual(messageContent.Value, receivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender);
}
@@ -59,7 +59,7 @@ namespace Unity.Netcode.RuntimeTests
public IEnumerator NamedMessageIsReceivedOnMultipleClientsWithContent()
{
var messageName = Guid.NewGuid().ToString();
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
@@ -71,7 +71,7 @@ namespace Unity.Netcode.RuntimeTests
}
ulong firstReceivedMessageSender = 0;
var firstReceivedMessageContent = new Guid();
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(
messageName,
(ulong sender, FastBufferReader reader) =>
@@ -82,7 +82,7 @@ namespace Unity.Netcode.RuntimeTests
});
ulong secondReceivedMessageSender = 0;
var secondReceivedMessageContent = new Guid();
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
SecondClient.CustomMessagingManager.RegisterNamedMessageHandler(
messageName,
(ulong sender, FastBufferReader reader) =>
@@ -94,10 +94,10 @@ namespace Unity.Netcode.RuntimeTests
yield return new WaitForSeconds(0.2f);
Assert.AreEqual(messageContent, firstReceivedMessageContent);
Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender);
Assert.AreEqual(messageContent, secondReceivedMessageContent);
Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender);
}
@@ -105,7 +105,7 @@ namespace Unity.Netcode.RuntimeTests
public IEnumerator WhenSendingNamedMessageToAll_AllClientsReceiveIt()
{
var messageName = Guid.NewGuid().ToString();
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
@@ -114,7 +114,7 @@ namespace Unity.Netcode.RuntimeTests
}
ulong firstReceivedMessageSender = 0;
var firstReceivedMessageContent = new Guid();
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(
messageName,
(ulong sender, FastBufferReader reader) =>
@@ -125,7 +125,7 @@ namespace Unity.Netcode.RuntimeTests
});
ulong secondReceivedMessageSender = 0;
var secondReceivedMessageContent = new Guid();
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
SecondClient.CustomMessagingManager.RegisterNamedMessageHandler(
messageName,
(ulong sender, FastBufferReader reader) =>
@@ -137,10 +137,10 @@ namespace Unity.Netcode.RuntimeTests
yield return new WaitForSeconds(0.2f);
Assert.AreEqual(messageContent, firstReceivedMessageContent);
Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender);
Assert.AreEqual(messageContent, secondReceivedMessageContent);
Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender);
}
@@ -148,7 +148,7 @@ namespace Unity.Netcode.RuntimeTests
public void WhenSendingNamedMessageToNullClientList_ArgumentNullExceptionIsThrown()
{
var messageName = Guid.NewGuid().ToString();
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{

View File

@@ -19,7 +19,7 @@ namespace Unity.Netcode.RuntimeTests
[UnityTest]
public IEnumerator UnnamedMessageIsReceivedOnClientWithContent()
{
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
@@ -30,7 +30,7 @@ namespace Unity.Netcode.RuntimeTests
}
ulong receivedMessageSender = 0;
var receivedMessageContent = new Guid();
var receivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
(ulong sender, FastBufferReader reader) =>
{
@@ -41,14 +41,14 @@ namespace Unity.Netcode.RuntimeTests
yield return new WaitForSeconds(0.2f);
Assert.AreEqual(messageContent, receivedMessageContent);
Assert.AreEqual(messageContent.Value, receivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender);
}
[UnityTest]
public IEnumerator UnnamedMessageIsReceivedOnMultipleClientsWithContent()
{
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
@@ -59,7 +59,7 @@ namespace Unity.Netcode.RuntimeTests
}
ulong firstReceivedMessageSender = 0;
var firstReceivedMessageContent = new Guid();
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
(ulong sender, FastBufferReader reader) =>
{
@@ -69,7 +69,7 @@ namespace Unity.Netcode.RuntimeTests
};
ulong secondReceivedMessageSender = 0;
var secondReceivedMessageContent = new Guid();
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
SecondClient.CustomMessagingManager.OnUnnamedMessage +=
(ulong sender, FastBufferReader reader) =>
{
@@ -80,17 +80,17 @@ namespace Unity.Netcode.RuntimeTests
yield return new WaitForSeconds(0.2f);
Assert.AreEqual(messageContent, firstReceivedMessageContent);
Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender);
Assert.AreEqual(messageContent, secondReceivedMessageContent);
Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender);
}
[UnityTest]
public IEnumerator WhenSendingUnnamedMessageToAll_AllClientsReceiveIt()
{
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
@@ -99,7 +99,7 @@ namespace Unity.Netcode.RuntimeTests
}
ulong firstReceivedMessageSender = 0;
var firstReceivedMessageContent = new Guid();
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
(ulong sender, FastBufferReader reader) =>
{
@@ -109,7 +109,7 @@ namespace Unity.Netcode.RuntimeTests
};
ulong secondReceivedMessageSender = 0;
var secondReceivedMessageContent = new Guid();
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
SecondClient.CustomMessagingManager.OnUnnamedMessage +=
(ulong sender, FastBufferReader reader) =>
{
@@ -120,17 +120,17 @@ namespace Unity.Netcode.RuntimeTests
yield return new WaitForSeconds(0.2f);
Assert.AreEqual(messageContent, firstReceivedMessageContent);
Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender);
Assert.AreEqual(messageContent, secondReceivedMessageContent);
Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value);
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender);
}
[Test]
public void WhenSendingNamedMessageToNullClientList_ArgumentNullExceptionIsThrown()
{
var messageContent = Guid.NewGuid();
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{

View File

@@ -27,12 +27,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
{
var waitForMetricValues = new WaitForEventMetricValues<NetworkMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), FirstClient.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer);
}
yield return waitForMetricValues.WaitForMetricsReceived();
@@ -47,12 +47,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
public IEnumerator TrackNetworkMessageSentMetricToMultipleClients()
{
var waitForMetricValues = new WaitForEventMetricValues<NetworkMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), new List<ulong> { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), new List<ulong> { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer);
}
@@ -65,10 +65,10 @@ namespace Unity.Netcode.RuntimeTests.Metrics
[UnityTest]
public IEnumerator TrackNetworkMessageReceivedMetric()
{
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
LogAssert.Expect(LogType.Log, $"Received from {Server.LocalClientId}");
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(messageName.ToString(), (ulong sender, FastBufferReader payload) =>
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(messageName.Value.ToString(), (ulong sender, FastBufferReader payload) =>
{
Debug.Log($"Received from {sender}");
});
@@ -79,7 +79,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), FirstClient.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer);
}
yield return waitForMetricValues.WaitForMetricsReceived();
@@ -94,12 +94,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
{
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), FirstClient.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer);
}
@@ -109,7 +109,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
Assert.AreEqual(1, namedMessageSentMetricValues.Count);
var namedMessageSent = namedMessageSentMetricValues.First();
Assert.AreEqual(messageName.ToString(), namedMessageSent.Name);
Assert.AreEqual(messageName.Value.ToString(), namedMessageSent.Name);
Assert.AreEqual(FirstClient.LocalClientId, namedMessageSent.Connection.Id);
Assert.AreEqual(FastBufferWriter.GetWriteSize(messageName) + k_NamedMessageOverhead, namedMessageSent.BytesCount);
}
@@ -118,12 +118,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
public IEnumerator TrackNamedMessageSentMetricToMultipleClients()
{
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), new List<ulong> { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), new List<ulong> { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer);
}
@@ -131,7 +131,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
var namedMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound();
Assert.AreEqual(2, namedMessageSentMetricValues.Count);
Assert.That(namedMessageSentMetricValues.Select(x => x.Name), Has.All.EqualTo(messageName.ToString()));
Assert.That(namedMessageSentMetricValues.Select(x => x.Name), Has.All.EqualTo(messageName.Value.ToString()));
Assert.That(namedMessageSentMetricValues.Select(x => x.BytesCount), Has.All.EqualTo(FastBufferWriter.GetWriteSize(messageName) + k_NamedMessageOverhead));
}
@@ -139,12 +139,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
public IEnumerator TrackNamedMessageSentMetricToSelf()
{
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), Server.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), Server.LocalClientId, writer);
}
yield return waitForMetricValues.WaitForMetricsReceived();
@@ -157,10 +157,10 @@ namespace Unity.Netcode.RuntimeTests.Metrics
{
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NamedMessageReceived);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
LogAssert.Expect(LogType.Log, $"Received from {Server.LocalClientId}");
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(messageName.ToString(), (ulong sender, FastBufferReader payload) =>
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(messageName.Value.ToString(), (ulong sender, FastBufferReader payload) =>
{
Debug.Log($"Received from {sender}");
});
@@ -169,7 +169,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), FirstClient.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer);
}
@@ -179,7 +179,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
Assert.AreEqual(1, namedMessageReceivedValues.Count);
var namedMessageReceived = namedMessageReceivedValues.First();
Assert.AreEqual(messageName.ToString(), namedMessageReceived.Name);
Assert.AreEqual(messageName.Value.ToString(), namedMessageReceived.Name);
Assert.AreEqual(Server.LocalClientId, namedMessageReceived.Connection.Id);
Assert.AreEqual(FastBufferWriter.GetWriteSize(messageName) + k_NamedMessageOverhead, namedMessageReceived.BytesCount);
}
@@ -187,7 +187,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
[UnityTest]
public IEnumerator TrackUnnamedMessageSentMetric()
{
var message = Guid.NewGuid();
var message = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(message);
@@ -211,7 +211,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
[UnityTest]
public IEnumerator TrackUnnamedMessageSentMetricToMultipleClients()
{
var message = Guid.NewGuid();
var message = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
@@ -236,7 +236,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
public IEnumerator TrackUnnamedMessageSentMetricToSelf()
{
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{
writer.WriteValueSafe(messageName);
@@ -252,7 +252,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
[UnityTest]
public IEnumerator TrackUnnamedMessageReceivedMetric()
{
var message = Guid.NewGuid();
var message = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageReceived);
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
{

View File

@@ -24,11 +24,6 @@ namespace Unity.Netcode.RuntimeTests.Metrics
: base(HostOrServer.Server)
{}
protected override void OnOneTimeSetup()
{
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.UTP;
}
protected override void OnServerAndClientsCreated()
{
var clientTransport = (UnityTransport)m_ClientNetworkManagers[0].NetworkConfig.NetworkTransport;

View File

@@ -12,13 +12,6 @@ namespace Unity.Netcode.RuntimeTests.Metrics
{
internal class PacketMetricsTests : SingleClientMetricTestBase
{
protected override void OnOneTimeSetup()
{
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.UTP;
base.OnOneTimeSetup();
}
[UnityTest]
public IEnumerator TrackPacketSentMetric()
{

View File

@@ -40,15 +40,6 @@ namespace Unity.Netcode.RuntimeTests.Metrics
m_ClientCount = numberOfClients == ClientCount.OneClient ? 1 : 2;
}
/// <summary>
/// Note: We are using the OnOneTimeSetup to select the transport to use for
/// this test set.
/// </summary>
protected override void OnOneTimeSetup()
{
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.UTP;
}
[UnityTest]
public IEnumerator TrackRttMetricServerToClient()
{

View File

@@ -16,6 +16,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
private static readonly int k_ServerLogSentMessageOverhead = 2 + k_MessageHeaderSize;
private static readonly int k_ServerLogReceivedMessageOverhead = 2;
protected override IEnumerator OnSetup()
{
m_CreateServerFirst = false;
return base.OnSetup();
}
[UnityTest]
public IEnumerator TrackServerLogSentMetric()
{

View File

@@ -20,14 +20,14 @@ namespace Unity.Netcode.RuntimeTests.Metrics
[UnityTest]
public IEnumerator TrackTotalNumberOfBytesSent()
{
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
var observer = new TotalBytesObserver(ClientMetrics.Dispatcher, NetworkMetricTypes.TotalBytesReceived);
try
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), Client.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), Client.LocalClientId, writer);
}
finally
{
@@ -48,14 +48,14 @@ namespace Unity.Netcode.RuntimeTests.Metrics
[UnityTest]
public IEnumerator TrackTotalNumberOfBytesReceived()
{
var messageName = Guid.NewGuid();
var messageName = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
var writer = new FastBufferWriter(1300, Allocator.Temp);
var observer = new TotalBytesObserver(ClientMetrics.Dispatcher, NetworkMetricTypes.TotalBytesReceived);
try
{
writer.WriteValueSafe(messageName);
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), Client.LocalClientId, writer);
Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), Client.LocalClientId, writer);
}
finally
{

View File

@@ -1,7 +1,7 @@
using UnityEngine;
using NUnit.Framework;
using UnityEngine.TestTools;
using Unity.Netcode.TestHelpers.Runtime;
using Unity.Netcode.Transports.UTP;
using Object = UnityEngine.Object;
namespace Unity.Netcode.RuntimeTests
@@ -14,9 +14,9 @@ namespace Unity.Netcode.RuntimeTests
var parent = new GameObject("ParentObject");
var networkManagerObject = new GameObject(nameof(CheckNestedNetworkManager));
var transport = networkManagerObject.AddComponent<SIPTransport>();
var unityTransport = networkManagerObject.AddComponent<UnityTransport>();
var networkManager = networkManagerObject.AddComponent<NetworkManager>();
networkManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport };
networkManager.NetworkConfig = new NetworkConfig() { NetworkTransport = unityTransport };
// Make our NetworkManager's GameObject nested
networkManagerObject.transform.parent = parent.transform;

View File

@@ -38,7 +38,7 @@ namespace Unity.Netcode.RuntimeTests
// destroy the server player
Object.Destroy(serverClientPlayerResult.Result.gameObject);
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfType<DestroyObjectMessage>(m_ClientNetworkManagers[0]);
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeHandled<DestroyObjectMessage>(m_ClientNetworkManagers[0]);
Assert.IsTrue(serverClientPlayerResult.Result == null); // Assert.IsNull doesn't work here
Assert.IsTrue(clientClientPlayerResult.Result == null);

View File

@@ -51,6 +51,8 @@ namespace Unity.Netcode.RuntimeTests
yield return s_DefaultWaitForTick;
// Ensure it's now added to the list
yield return WaitForConditionOrTimeOut(() => m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client to gain ownership!");
Assert.True(m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
Assert.True(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
}

View File

@@ -67,7 +67,7 @@ namespace Unity.Netcode.RuntimeTests
m_OwnershipObject = SpawnObject(m_OwnershipPrefab, m_ServerNetworkManager);
m_OwnershipNetworkObject = m_OwnershipObject.GetComponent<NetworkObject>();
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfType<CreateObjectMessage>(m_ClientNetworkManagers[0]);
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeHandled<CreateObjectMessage>(m_ClientNetworkManagers[0]);
var ownershipNetworkObjectId = m_OwnershipNetworkObject.NetworkObjectId;
Assert.That(ownershipNetworkObjectId, Is.GreaterThan(0));
@@ -95,11 +95,14 @@ namespace Unity.Netcode.RuntimeTests
Assert.That(m_ServerNetworkManager.ConnectedClients.ContainsKey(m_ClientNetworkManagers[0].LocalClientId));
serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 2);
serverObject.ChangeOwnership(clientComponent.NetworkManager.LocalClientId);
yield return s_DefaultWaitForTick;
Assert.That(serverComponent.OnLostOwnershipFired);
Assert.That(serverComponent.OwnerClientId, Is.EqualTo(m_ClientNetworkManagers[0].LocalClientId));
yield return WaitForConditionOrTimeOut(() => clientComponent.OnGainedOwnershipFired);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client to gain ownership!");
Assert.That(clientComponent.OnGainedOwnershipFired);
Assert.That(clientComponent.OwnerClientId, Is.EqualTo(m_ClientNetworkManagers[0].LocalClientId));
@@ -107,10 +110,13 @@ namespace Unity.Netcode.RuntimeTests
clientComponent.ResetFlags();
serverObject.ChangeOwnership(NetworkManager.ServerClientId);
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 2);
yield return s_DefaultWaitForTick;
Assert.That(serverComponent.OnGainedOwnershipFired);
Assert.That(serverComponent.OwnerClientId, Is.EqualTo(m_ServerNetworkManager.LocalClientId));
yield return WaitForConditionOrTimeOut(() => clientComponent.OnLostOwnershipFired);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client to lose ownership!");
Assert.That(clientComponent.OnLostOwnershipFired);
Assert.That(clientComponent.OwnerClientId, Is.EqualTo(m_ServerNetworkManager.LocalClientId));
}
@@ -151,11 +157,22 @@ namespace Unity.Netcode.RuntimeTests
var ownershipNetworkObjectId = m_OwnershipNetworkObject.NetworkObjectId;
Assert.That(ownershipNetworkObjectId, Is.GreaterThan(0));
Assert.That(m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId));
foreach (var clientNetworkManager in m_ClientNetworkManagers)
bool WaitForClientsToSpawnNetworkObject()
{
Assert.That(clientNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId));
foreach (var clientNetworkManager in m_ClientNetworkManagers)
{
if (!clientNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId))
{
return false;
}
}
return true;
}
yield return WaitForConditionOrTimeOut(WaitForClientsToSpawnNetworkObject);
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for all clients to change ownership!");
// Verifies that removing the ownership when the default (server) is already set does not cause a Key Not Found Exception
m_ServerNetworkManager.SpawnManager.RemoveOwnership(m_OwnershipNetworkObject);
var serverObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[ownershipNetworkObjectId];
@@ -237,7 +254,10 @@ namespace Unity.Netcode.RuntimeTests
Assert.That(serverComponent.OnGainedOwnershipFired);
Assert.That(serverComponent.OwnerClientId, Is.EqualTo(m_ServerNetworkManager.LocalClientId));
Assert.That(previousClientComponent.OnLostOwnershipFired);
yield return WaitForConditionOrTimeOut(() => previousClientComponent.OnLostOwnershipFired);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {previousClientComponent.name} to lose ownership!");
// Make sure all client-side versions of the object is once again owned by the server
for (int i = 0; i < NumberOfClients; i++)

View File

@@ -91,6 +91,8 @@ namespace Unity.Netcode.RuntimeTests
Assert.AreEqual(clientSideClientId, clientSideClientPlayerObject.OwnerClientId);
}
private bool m_ClientDisconnected;
[UnityTest]
public IEnumerator TestConnectAndDisconnect()
{
@@ -120,11 +122,22 @@ namespace Unity.Netcode.RuntimeTests
// test when client disconnects, player object no longer available.
var nbConnectedClients = m_ServerNetworkManager.ConnectedClients.Count;
m_ClientDisconnected = false;
newClientNetworkManager.OnClientDisconnectCallback += ClientNetworkManager_OnClientDisconnectCallback;
m_ServerNetworkManager.DisconnectClient(newClientLocalClientId);
yield return WaitForConditionOrTimeOut(() => m_ClientDisconnected);
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client to disconnect");
// Call this to clean up NetcodeIntegrationTestHelpers
NetcodeIntegrationTestHelpers.StopOneClient(newClientNetworkManager);
yield return WaitForConditionOrTimeOut(() => m_ServerNetworkManager.ConnectedClients.Count == nbConnectedClients - 1);
Assert.AreEqual(m_ServerNetworkManager.ConnectedClients.Count, nbConnectedClients - 1);
serverSideNewClientPlayer = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(newClientLocalClientId);
Assert.Null(serverSideNewClientPlayer);
}
private void ClientNetworkManager_OnClientDisconnectCallback(ulong obj)
{
m_ClientDisconnected = true;
}
}
}

View File

@@ -0,0 +1,277 @@
#if COM_UNITY_MODULES_PHYSICS
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Netcode.Components;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Unity.Netcode.TestHelpers.Runtime;
namespace Unity.Netcode.RuntimeTests
{
public class NetworkTransformOwnershipTests : NetcodeIntegrationTest
{
protected override int NumberOfClients => 1;
private GameObject m_ClientNetworkTransformPrefab;
private GameObject m_NetworkTransformPrefab;
protected override void OnServerAndClientsCreated()
{
VerifyObjectIsSpawnedOnClient.ResetObjectTable();
m_ClientNetworkTransformPrefab = CreateNetworkObjectPrefab("OwnerAuthorityTest");
var clientNetworkTransform = m_ClientNetworkTransformPrefab.AddComponent<TestClientNetworkTransform>();
clientNetworkTransform.Interpolate = false;
var rigidBody = m_ClientNetworkTransformPrefab.AddComponent<Rigidbody>();
rigidBody.useGravity = false;
m_ClientNetworkTransformPrefab.AddComponent<NetworkRigidbody>();
m_ClientNetworkTransformPrefab.AddComponent<SphereCollider>();
m_ClientNetworkTransformPrefab.AddComponent<VerifyObjectIsSpawnedOnClient>();
m_NetworkTransformPrefab = CreateNetworkObjectPrefab("ServerAuthorityTest");
var networkTransform = m_NetworkTransformPrefab.AddComponent<NetworkTransform>();
rigidBody = m_NetworkTransformPrefab.AddComponent<Rigidbody>();
rigidBody.useGravity = false;
m_NetworkTransformPrefab.AddComponent<NetworkRigidbody>();
m_NetworkTransformPrefab.AddComponent<SphereCollider>();
m_NetworkTransformPrefab.AddComponent<VerifyObjectIsSpawnedOnClient>();
networkTransform.Interpolate = false;
base.OnServerAndClientsCreated();
}
public enum StartingOwnership
{
HostStartsAsOwner,
ClientStartsAsOwner,
}
/// <summary>
/// This verifies that when authority is owner authoritative the owner's
/// Rigidbody is kinematic and the non-owner's is not.
/// This also verifies that we can switch between owners and that only the
/// owner can update the transform while non-owners cannot.
/// </summary>
/// <param name="spawnWithHostOwnership">determines who starts as the owner (true): host | (false): client</param>
[UnityTest]
public IEnumerator OwnerAuthoritativeTest([Values] StartingOwnership startingOwnership)
{
// Get the current ownership layout
var networkManagerOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ServerNetworkManager : m_ClientNetworkManagers[0];
var networkManagerNonOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ClientNetworkManagers[0] : m_ServerNetworkManager;
// Spawn the m_ClientNetworkTransformPrefab and wait for the client-side to spawn the object
var serverSideInstance = SpawnObject(m_ClientNetworkTransformPrefab, networkManagerOwner);
yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.GetClientsThatSpawnedThisPrefab().Contains(m_ClientNetworkManagers[0].LocalClientId));
// Get owner relative instances
var ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerOwner.LocalClientId);
var nonOwnerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerNonOwner.LocalClientId);
Assert.NotNull(ownerInstance);
Assert.NotNull(nonOwnerInstance);
// Make sure the owner is not kinematic and the non-owner(s) are kinematic
Assert.True(nonOwnerInstance.GetComponent<Rigidbody>().isKinematic, $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} is not kinematic when it should be!");
Assert.False(ownerInstance.GetComponent<Rigidbody>().isKinematic, $"{networkManagerOwner.name}'s object instance {ownerInstance.name} is kinematic when it should not be!");
// Owner changes transform values
var valueSetByOwner = Vector3.one * 2;
ownerInstance.transform.position = valueSetByOwner;
ownerInstance.transform.localScale = valueSetByOwner;
var rotation = new Quaternion();
rotation.eulerAngles = valueSetByOwner;
ownerInstance.transform.rotation = rotation;
var transformToTest = nonOwnerInstance.transform;
yield return WaitForConditionOrTimeOut(() => transformToTest.position == valueSetByOwner && transformToTest.localScale == valueSetByOwner && transformToTest.rotation == rotation);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change its transform!\n" +
$"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" +
$"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" +
$"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}");
// Verify non-owners cannot change transform values
nonOwnerInstance.transform.position = Vector3.zero;
yield return s_DefaultWaitForTick;
Assert.True(nonOwnerInstance.transform.position == valueSetByOwner, $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} was allowed to change its position! Expected: {Vector3.one} Is Currently:{nonOwnerInstance.transform.position}");
// Change ownership and wait for the non-owner to reflect the change
VerifyObjectIsSpawnedOnClient.ResetObjectTable();
m_ServerNetworkManager.SpawnManager.ChangeOwnership(serverSideInstance.GetComponent<NetworkObject>(), networkManagerNonOwner.LocalClientId);
yield return WaitForConditionOrTimeOut(() => nonOwnerInstance.GetComponent<NetworkObject>().OwnerClientId == networkManagerNonOwner.LocalClientId);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change ownership!");
// Re-assign the ownership references and wait for the non-owner instance to be notified of ownership change
networkManagerOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ClientNetworkManagers[0] : m_ServerNetworkManager;
networkManagerNonOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ServerNetworkManager : m_ClientNetworkManagers[0];
ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerOwner.LocalClientId);
Assert.NotNull(ownerInstance);
yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerNonOwner.LocalClientId) != null);
nonOwnerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerNonOwner.LocalClientId);
Assert.NotNull(nonOwnerInstance);
// Make sure the owner is not kinematic and the non-owner(s) are kinematic
Assert.False(ownerInstance.GetComponent<Rigidbody>().isKinematic, $"{networkManagerOwner.name}'s object instance {ownerInstance.name} is kinematic when it should not be!");
Assert.True(nonOwnerInstance.GetComponent<Rigidbody>().isKinematic, $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} is not kinematic when it should be!");
// Have the new owner change transform values and wait for those values to be applied on the non-owner side.
valueSetByOwner = Vector3.one * 50;
ownerInstance.transform.position = valueSetByOwner;
ownerInstance.transform.localScale = valueSetByOwner;
rotation.eulerAngles = valueSetByOwner;
ownerInstance.transform.rotation = rotation;
transformToTest = nonOwnerInstance.transform;
yield return WaitForConditionOrTimeOut(() => transformToTest.position == valueSetByOwner && transformToTest.localScale == valueSetByOwner && transformToTest.rotation == rotation);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change its transform!\n" +
$"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" +
$"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" +
$"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}");
// The last check is to verify non-owners cannot change transform values after ownership has changed
nonOwnerInstance.transform.position = Vector3.zero;
yield return s_DefaultWaitForTick;
Assert.True(nonOwnerInstance.transform.position == valueSetByOwner, $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} was allowed to change its position! Expected: {Vector3.one} Is Currently:{nonOwnerInstance.transform.position}");
}
/// <summary>
/// This verifies that when authority is server authoritative the
/// client's Rigidbody is kinematic and the server is not.
/// This also verifies only the server can apply updates to the
/// transform while the clients cannot.
/// </summary>
[UnityTest]
public IEnumerator ServerAuthoritativeTest()
{
// Spawn the m_NetworkTransformPrefab and wait for the client-side to spawn the object
var serverSideInstance = SpawnObject(m_NetworkTransformPrefab, m_ServerNetworkManager);
yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.GetClientsThatSpawnedThisPrefab().Contains(m_ClientNetworkManagers[0].LocalClientId));
var ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(m_ServerNetworkManager.LocalClientId);
var nonOwnerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(m_ClientNetworkManagers[0].LocalClientId);
// Make sure the owner is not kinematic and the non-owner(s) are kinematic
Assert.False(ownerInstance.GetComponent<Rigidbody>().isKinematic, $"{m_ServerNetworkManager.name}'s object instance {ownerInstance.name} is kinematic when it should not be!");
Assert.True(nonOwnerInstance.GetComponent<Rigidbody>().isKinematic, $"{m_ClientNetworkManagers[0].name}'s object instance {nonOwnerInstance.name} is not kinematic when it should be!");
// Server changes transform values
var valueSetByOwner = Vector3.one * 2;
ownerInstance.transform.position = valueSetByOwner;
ownerInstance.transform.localScale = valueSetByOwner;
var rotation = new Quaternion();
rotation.eulerAngles = valueSetByOwner;
ownerInstance.transform.rotation = rotation;
var transformToTest = nonOwnerInstance.transform;
yield return WaitForConditionOrTimeOut(() => transformToTest.position == valueSetByOwner && transformToTest.localScale == valueSetByOwner && transformToTest.rotation == rotation);
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {m_ClientNetworkManagers[0].name}'s object instance {nonOwnerInstance.name} to change its transform!\n" +
$"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" +
$"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" +
$"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}");
// The last check is to verify clients cannot change transform values
nonOwnerInstance.transform.position = Vector3.zero;
yield return s_DefaultWaitForTick;
Assert.True(nonOwnerInstance.transform.position == valueSetByOwner, $"{m_ClientNetworkManagers[0].name}'s object instance {nonOwnerInstance.name} was allowed to change its position! Expected: {Vector3.one} Is Currently:{nonOwnerInstance.transform.position}");
}
/// <summary>
/// NetworkTransformOwnershipTests helper behaviour
/// </summary>
public class VerifyObjectIsSpawnedOnClient : NetworkBehaviour
{
private static Dictionary<ulong, VerifyObjectIsSpawnedOnClient> s_NetworkManagerRelativeSpawnedObjects = new Dictionary<ulong, VerifyObjectIsSpawnedOnClient>();
public static void ResetObjectTable()
{
s_NetworkManagerRelativeSpawnedObjects.Clear();
}
public override void OnGainedOwnership()
{
if (!s_NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId))
{
s_NetworkManagerRelativeSpawnedObjects.Add(NetworkManager.LocalClientId, this);
}
base.OnGainedOwnership();
}
public override void OnLostOwnership()
{
if (!s_NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId))
{
s_NetworkManagerRelativeSpawnedObjects.Add(NetworkManager.LocalClientId, this);
}
base.OnLostOwnership();
}
public static List<ulong> GetClientsThatSpawnedThisPrefab()
{
return s_NetworkManagerRelativeSpawnedObjects.Keys.ToList();
}
public static VerifyObjectIsSpawnedOnClient GetClientInstance(ulong clientId)
{
if (s_NetworkManagerRelativeSpawnedObjects.ContainsKey(clientId))
{
return s_NetworkManagerRelativeSpawnedObjects[clientId];
}
return null;
}
public override void OnNetworkSpawn()
{
// This makes sure that the NetworkManager relative NetworkObject instances don't collide with each other
// and skew the expected changes to the transforms
foreach (var entry in s_NetworkManagerRelativeSpawnedObjects)
{
Physics.IgnoreCollision(entry.Value.GetComponent<SphereCollider>(), GetComponent<SphereCollider>());
}
if (!s_NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId))
{
s_NetworkManagerRelativeSpawnedObjects.Add(NetworkManager.LocalClientId, this);
}
base.OnNetworkSpawn();
}
public override void OnNetworkDespawn()
{
if (s_NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId))
{
s_NetworkManagerRelativeSpawnedObjects.Remove(NetworkManager.LocalClientId);
}
base.OnNetworkDespawn();
}
}
/// <summary>
/// Until we can better locate the ClientNetworkTransform
/// This will have to be used to verify the ownership authority
/// </summary>
[DisallowMultipleComponent]
public class TestClientNetworkTransform : NetworkTransform
{
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
CanCommitToTransform = IsOwner;
}
protected override void Update()
{
CanCommitToTransform = IsOwner;
base.Update();
if (NetworkManager.Singleton != null && (NetworkManager.Singleton.IsConnectedClient || NetworkManager.Singleton.IsListening))
{
if (CanCommitToTransform)
{
TryCommitTransformToServer(transform, NetworkManager.LocalTime.Time);
}
}
}
protected override bool OnIsServerAuthoritatitive()
{
return false;
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2f8cf0e06334cb4f9f7d4ca3c2d19e3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -22,6 +22,11 @@ namespace Unity.Netcode.RuntimeTests
ReadyToReceivePositionUpdate = true;
}
public (bool isDirty, bool isPositionDirty, bool isRotationDirty, bool isScaleDirty) ApplyState()
{
return ApplyLocalNetworkState(transform);
}
}
// [TestFixture(true, true)]
@@ -172,6 +177,80 @@ namespace Unity.Netcode.RuntimeTests
#endif
}
/// <summary>
/// Validates that rotation checks don't produce false positive
/// results when rolling over between 0 and 360 degrees
/// </summary>
[UnityTest]
public IEnumerator TestRotationThresholdDeltaCheck()
{
// Get the client player's NetworkTransform for both instances
var authoritativeNetworkTransform = m_ServerSideClientPlayer.GetComponent<NetworkTransformTestComponent>();
var otherSideNetworkTransform = m_ClientSideClientPlayer.GetComponent<NetworkTransformTestComponent>();
otherSideNetworkTransform.RotAngleThreshold = authoritativeNetworkTransform.RotAngleThreshold = 5.0f;
var halfThreshold = authoritativeNetworkTransform.RotAngleThreshold * 0.5001f;
var serverRotation = authoritativeNetworkTransform.transform.rotation;
var serverEulerRotation = serverRotation.eulerAngles;
// Verify rotation is not marked dirty when rotated by half of the threshold
serverEulerRotation.y += halfThreshold;
serverRotation.eulerAngles = serverEulerRotation;
authoritativeNetworkTransform.transform.rotation = serverRotation;
var results = authoritativeNetworkTransform.ApplyState();
Assert.IsFalse(results.isRotationDirty, $"Rotation is dirty when rotation threshold is {authoritativeNetworkTransform.RotAngleThreshold} degrees and only adjusted by {halfThreshold} degrees!");
yield return s_DefaultWaitForTick;
// Verify rotation is marked dirty when rotated by another half threshold value
serverEulerRotation.y += halfThreshold;
serverRotation.eulerAngles = serverEulerRotation;
authoritativeNetworkTransform.transform.rotation = serverRotation;
results = authoritativeNetworkTransform.ApplyState();
Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by the threshold value: {authoritativeNetworkTransform.RotAngleThreshold} degrees!");
yield return s_DefaultWaitForTick;
//Reset rotation back to zero on all axis
serverRotation.eulerAngles = serverEulerRotation = Vector3.zero;
authoritativeNetworkTransform.transform.rotation = serverRotation;
yield return s_DefaultWaitForTick;
// Rotate by 360 minus halfThreshold (which is really just negative halfThreshold) and verify rotation is not marked dirty
serverEulerRotation.y = 360 - halfThreshold;
serverRotation.eulerAngles = serverEulerRotation;
authoritativeNetworkTransform.transform.rotation = serverRotation;
results = authoritativeNetworkTransform.ApplyState();
Assert.IsFalse(results.isRotationDirty, $"Rotation is dirty when rotation threshold is {authoritativeNetworkTransform.RotAngleThreshold} degrees and only adjusted by " +
$"{Mathf.DeltaAngle(0, serverEulerRotation.y)} degrees!");
serverEulerRotation.y -= halfThreshold;
serverRotation.eulerAngles = serverEulerRotation;
authoritativeNetworkTransform.transform.rotation = serverRotation;
results = authoritativeNetworkTransform.ApplyState();
Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by {Mathf.DeltaAngle(0, serverEulerRotation.y)} degrees!");
//Reset rotation back to zero on all axis
serverRotation.eulerAngles = serverEulerRotation = Vector3.zero;
authoritativeNetworkTransform.transform.rotation = serverRotation;
yield return s_DefaultWaitForTick;
serverEulerRotation.y -= halfThreshold;
serverRotation.eulerAngles = serverEulerRotation;
authoritativeNetworkTransform.transform.rotation = serverRotation;
results = authoritativeNetworkTransform.ApplyState();
Assert.IsFalse(results.isRotationDirty, $"Rotation is dirty when rotation threshold is {authoritativeNetworkTransform.RotAngleThreshold} degrees and only adjusted by " +
$"{Mathf.DeltaAngle(0, serverEulerRotation.y)} degrees!");
serverEulerRotation.y -= halfThreshold;
serverRotation.eulerAngles = serverEulerRotation;
authoritativeNetworkTransform.transform.rotation = serverRotation;
results = authoritativeNetworkTransform.ApplyState();
Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by {Mathf.DeltaAngle(0, serverEulerRotation.y)} degrees!");
}
/*
* ownership change
* test teleport with interpolation

View File

@@ -273,9 +273,9 @@ namespace Unity.Netcode.RuntimeTests
{
public readonly NetworkVariable<int> TheScalar = new NetworkVariable<int>();
public readonly NetworkList<int> TheList = new NetworkList<int>();
public readonly NetworkList<FixedString128Bytes> TheLargeList = new NetworkList<FixedString128Bytes>();
public readonly NetworkList<ForceNetworkSerializeByMemcpy<FixedString128Bytes>> TheLargeList = new NetworkList<ForceNetworkSerializeByMemcpy<FixedString128Bytes>>();
public readonly NetworkVariable<FixedString32Bytes> FixedString32 = new NetworkVariable<FixedString32Bytes>();
public readonly NetworkVariable<ForceNetworkSerializeByMemcpy<FixedString32Bytes>> FixedString32 = new NetworkVariable<ForceNetworkSerializeByMemcpy<FixedString32Bytes>>();
private void ListChanged(NetworkListEvent<int> e)
{
@@ -306,7 +306,8 @@ namespace Unity.Netcode.RuntimeTests
[TestFixture(false)]
public class NetworkVariableTests : NetcodeIntegrationTest
{
private const string k_FixedStringTestValue = "abcdefghijklmnopqrstuvwxyz";
private const string k_StringTestValue = "abcdefghijklmnopqrstuvwxyz";
private static readonly FixedString32Bytes k_FixedStringTestValue = k_StringTestValue;
protected override int NumberOfClients => 2;
private const uint k_TestUInt = 0x12345678;

View File

@@ -8,29 +8,16 @@ using Unity.Netcode.TestHelpers.Runtime;
namespace Unity.Netcode.RuntimeTests
{
public class NetworkRigidbodyDynamicTest : NetworkRigidbodyTestBase
{
public override bool Kinematic => false;
}
public class NetworkRigidbodyKinematicTest : NetworkRigidbodyTestBase
{
public override bool Kinematic => true;
}
public abstract class NetworkRigidbodyTestBase : NetcodeIntegrationTest
public class NetworkRigidbodyTest : NetcodeIntegrationTest
{
protected override int NumberOfClients => 1;
public abstract bool Kinematic { get; }
protected override void OnCreatePlayerPrefab()
{
m_PlayerPrefab.AddComponent<NetworkTransform>();
m_PlayerPrefab.AddComponent<Rigidbody>();
m_PlayerPrefab.AddComponent<NetworkRigidbody>();
m_PlayerPrefab.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
m_PlayerPrefab.GetComponent<Rigidbody>().isKinematic = Kinematic;
}
/// <summary>
@@ -55,8 +42,8 @@ namespace Unity.Netcode.RuntimeTests
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);
// server rigidbody has authority and should have a kinematic mode of false
Assert.True(serverPlayer.GetComponent<Rigidbody>().isKinematic == Kinematic, "serverPlayer kinematic");
// server rigidbody has authority and should not be kinematic
Assert.True(serverPlayer.GetComponent<Rigidbody>().isKinematic == false, "serverPlayer kinematic");
Assert.AreEqual(RigidbodyInterpolation.Interpolate, serverPlayer.GetComponent<Rigidbody>().interpolation, "server equal interpolate");
// client rigidbody has no authority and should have a kinematic mode of true
@@ -68,7 +55,8 @@ namespace Unity.Netcode.RuntimeTests
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);
Assert.IsTrue(serverPlayer.GetComponent<Rigidbody>().isKinematic == Kinematic, "serverPlayer second kinematic");
// When despawned, we should always be kinematic (i.e. don't apply physics when despawned)
Assert.IsTrue(serverPlayer.GetComponent<Rigidbody>().isKinematic == true, "serverPlayer second kinematic");
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine.TestTools;
using Unity.Netcode.TestHelpers.Runtime;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Unity.Netcode.RuntimeTests
@@ -13,6 +14,7 @@ namespace Unity.Netcode.RuntimeTests
public class RpcTestNB : NetworkBehaviour
{
public event Action<ulong, ServerRpcParams> OnServer_Rpc;
public event Action<Vector3, Vector3[]> OnTypedServer_Rpc;
public event Action OnClient_Rpc;
[ServerRpc]
@@ -26,6 +28,12 @@ namespace Unity.Netcode.RuntimeTests
{
OnClient_Rpc();
}
[ServerRpc]
public void MyTypedServerRpc(Vector3 param1, Vector3[] param2)
{
OnTypedServer_Rpc(param1, param2);
}
}
protected override int NumberOfClients => 1;
@@ -46,9 +54,13 @@ namespace Unity.Netcode.RuntimeTests
// Setup state
bool hasReceivedServerRpc = false;
bool hasReceivedTypedServerRpc = false;
bool hasReceivedClientRpcRemotely = false;
bool hasReceivedClientRpcLocally = false;
var vector3 = new Vector3(1, 2, 3);
Vector3[] vector3s = new[] { new Vector3(4, 5, 6), new Vector3(7, 8, 9) };
localClienRpcTestNB.OnClient_Rpc += () =>
{
Debug.Log("ClientRpc received on client object");
@@ -75,9 +87,22 @@ namespace Unity.Netcode.RuntimeTests
hasReceivedClientRpcLocally = true;
};
serverClientRpcTestNB.OnTypedServer_Rpc += (param1, param2) =>
{
Debug.Log("TypedServerRpc received on server object");
Assert.AreEqual(param1, vector3);
Assert.AreEqual(param2.Length, vector3s.Length);
Assert.AreEqual(param2[0], vector3s[0]);
Assert.AreEqual(param2[1], vector3s[1]);
hasReceivedTypedServerRpc = true;
};
// Send ServerRpc
localClienRpcTestNB.MyServerRpc(m_ClientNetworkManagers[0].LocalClientId);
// Send TypedServerRpc
localClienRpcTestNB.MyTypedServerRpc(vector3, vector3s);
// Send ClientRpc
serverClientRpcTestNB.MyClientRpc();
@@ -86,6 +111,11 @@ namespace Unity.Netcode.RuntimeTests
var serverMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager);
serverMessageHookEntry.AssignMessageType<ServerRpcMessage>();
messageHookList.Add(serverMessageHookEntry);
var typedServerMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager);
typedServerMessageHookEntry.AssignMessageType<ServerRpcMessage>();
messageHookList.Add(typedServerMessageHookEntry);
foreach (var client in m_ClientNetworkManagers)
{
var clientMessageHookEntry = new MessageHookEntry(client);
@@ -97,9 +127,10 @@ namespace Unity.Netcode.RuntimeTests
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for messages: {rpcMessageHooks.GetHooksStillWaiting()}");
// Make sure RPCs propagated all the way up and were called on the relative destination class instance
yield return WaitForConditionOrTimeOut(() => hasReceivedServerRpc && hasReceivedClientRpcLocally && hasReceivedClientRpcRemotely);
yield return WaitForConditionOrTimeOut(() => hasReceivedServerRpc && hasReceivedClientRpcLocally && hasReceivedClientRpcRemotely && hasReceivedTypedServerRpc);
Assert.True(hasReceivedServerRpc, "ServerRpc was not received");
Assert.True(hasReceivedTypedServerRpc, "TypedServerRpc was not received");
Assert.True(hasReceivedClientRpcLocally, "ClientRpc was not locally received on the server");
Assert.True(hasReceivedClientRpcRemotely, "ClientRpc was not remotely received on the client");
}

View File

@@ -6,69 +6,75 @@ using Unity.Netcode.TestHelpers.Runtime;
namespace Unity.Netcode.RuntimeTests
{
public class StopStartRuntimeTests
public class StopStartRuntimeTests : NetcodeIntegrationTest
{
protected override int NumberOfClients => 1;
protected override void OnOneTimeSetup()
{
m_UseHost = false;
base.OnOneTimeSetup();
}
[UnityTest]
public IEnumerator WhenShuttingDownAndRestarting_SDKRestartsSuccessfullyAndStaysRunning()
{ // create server and client instances
NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
{
// shutdown the server
m_ServerNetworkManager.Shutdown();
try
{
// wait 1 frame because shutdowns are delayed
var nextFrameNumber = Time.frameCount + 1;
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
// create prefab
var gameObject = new GameObject("PlayerObject");
var networkObject = gameObject.AddComponent<NetworkObject>();
networkObject.DontDestroyWithOwner = true;
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
// Verify the shutdown occurred
Assert.IsFalse(m_ServerNetworkManager.IsServer);
Assert.IsFalse(m_ServerNetworkManager.IsListening);
Assert.IsFalse(m_ServerNetworkManager.IsHost);
Assert.IsFalse(m_ServerNetworkManager.IsClient);
server.NetworkConfig.PlayerPrefab = gameObject;
m_ServerNetworkManager.StartServer();
// Verify the server started
Assert.IsTrue(m_ServerNetworkManager.IsServer);
Assert.IsTrue(m_ServerNetworkManager.IsListening);
for (int i = 0; i < clients.Length; i++)
{
clients[i].NetworkConfig.PlayerPrefab = gameObject;
}
// Wait several frames / one full network tick
yield return s_DefaultWaitForTick;
// start server and connect clients
NetcodeIntegrationTestHelpers.Start(false, server, clients);
// Verify the server is still running
Assert.IsTrue(m_ServerNetworkManager.IsServer);
Assert.IsTrue(m_ServerNetworkManager.IsListening);
}
// wait for connection on client side
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients);
[UnityTest]
public IEnumerator WhenShuttingDownTwiceAndRestarting_SDKRestartsSuccessfullyAndStaysRunning()
{
// shutdown the server
m_ServerNetworkManager.Shutdown();
// wait for connection on server side
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(server);
// wait 1 frame because shutdowns are delayed
var nextFrameNumber = Time.frameCount + 1;
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
// shutdown the server
server.Shutdown();
// Verify the shutdown occurred
Assert.IsFalse(m_ServerNetworkManager.IsServer);
Assert.IsFalse(m_ServerNetworkManager.IsListening);
Assert.IsFalse(m_ServerNetworkManager.IsHost);
Assert.IsFalse(m_ServerNetworkManager.IsClient);
// wait 1 frame because shutdowns are delayed
var nextFrameNumber = Time.frameCount + 1;
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
// Shutdown the server again.
m_ServerNetworkManager.Shutdown();
// Verify the shutdown occurred
Assert.IsFalse(server.IsServer);
Assert.IsFalse(server.IsListening);
Assert.IsFalse(server.IsHost);
Assert.IsFalse(server.IsClient);
m_ServerNetworkManager.StartServer();
// Verify the server started
Assert.IsTrue(m_ServerNetworkManager.IsServer);
Assert.IsTrue(m_ServerNetworkManager.IsListening);
server.StartServer();
// Verify the server started
Assert.IsTrue(server.IsServer);
Assert.IsTrue(server.IsListening);
// Wait several frames / one full network tick
yield return s_DefaultWaitForTick;
// Wait several frames
nextFrameNumber = Time.frameCount + 10;
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
// Verify the server is still running
Assert.IsTrue(server.IsServer);
Assert.IsTrue(server.IsListening);
}
finally
{
// cleanup
NetcodeIntegrationTestHelpers.Destroy();
}
// Verify the server is still running
Assert.IsTrue(m_ServerNetworkManager.IsServer);
Assert.IsTrue(m_ServerNetworkManager.IsListening);
}
}
}

View File

@@ -89,8 +89,13 @@ namespace Unity.Netcode.RuntimeTests
// compares the two client times, only difference should be based on buffering.
m_Client1State.AssertCheckDifference(m_Client2State, 0.2 - tickInterval, (0.1 - tickInterval), tickInterval * 2 + frameInterval * 2 + k_AdditionalTimeTolerance);
}
}
protected override IEnumerator OnTearDown()
{
// Always "shutdown in a tear-down" otherwise you can cause all proceeding tests to fail
ShutdownAndCleanUp();
yield return base.OnTearDown();
}
// This is from NetcodeIntegrationTest but we need a custom version of this to modifiy the config

View File

@@ -57,12 +57,15 @@ namespace Unity.Netcode.RuntimeTests
{
protected override int NumberOfClients => 1;
private ulong m_ClientId0;
private GameObject m_PrefabToSpawn;
private NetworkObject m_AsNetworkObject;
private NetworkObject m_SpawnedAsNetworkObject;
private NetworkObject m_SpawnedObjectOnClient;
private NetworkObject m_BaseAsNetworkObject;
private NetworkObject m_BaseOnClient;
protected override void OnServerAndClientsCreated()
{
m_PrefabToSpawn = CreateNetworkObjectPrefab("InterpTestObject");
@@ -74,41 +77,59 @@ namespace Unity.Netcode.RuntimeTests
{
var clientId = m_ClientNetworkManagers[0].LocalClientId;
yield return WaitForConditionOrTimeOut(() => s_GlobalNetworkObjects.ContainsKey(clientId) &&
s_GlobalNetworkObjects[clientId].ContainsKey(m_AsNetworkObject.NetworkObjectId));
s_GlobalNetworkObjects[clientId].ContainsKey(m_BaseAsNetworkObject.NetworkObjectId) &&
s_GlobalNetworkObjects[clientId].ContainsKey(m_SpawnedAsNetworkObject.NetworkObjectId));
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client side {nameof(NetworkObject)} ID of {m_AsNetworkObject.NetworkObjectId}");
m_SpawnedObjectOnClient = s_GlobalNetworkObjects[clientId][m_AsNetworkObject.NetworkObjectId];
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client side {nameof(NetworkObject)} ID of {m_SpawnedAsNetworkObject.NetworkObjectId}");
m_BaseOnClient = s_GlobalNetworkObjects[clientId][m_BaseAsNetworkObject.NetworkObjectId];
// make sure the objects are set with the right network manager
m_BaseOnClient.NetworkManagerOwner = m_ClientNetworkManagers[0];
m_SpawnedObjectOnClient = s_GlobalNetworkObjects[clientId][m_SpawnedAsNetworkObject.NetworkObjectId];
// make sure the objects are set with the right network manager
m_SpawnedObjectOnClient.NetworkManagerOwner = m_ClientNetworkManagers[0];
}
[UnityTest]
public IEnumerator TransformInterpolationTest()
{
m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId;
// create an object
var spawnedObject = Object.Instantiate(m_PrefabToSpawn);
var baseObject = Object.Instantiate(m_PrefabToSpawn);
baseObject.GetComponent<NetworkObject>().NetworkManagerOwner = m_ServerNetworkManager;
baseObject.GetComponent<NetworkObject>().Spawn();
m_AsNetworkObject = spawnedObject.GetComponent<NetworkObject>();
m_AsNetworkObject.NetworkManagerOwner = m_ServerNetworkManager;
m_SpawnedAsNetworkObject = spawnedObject.GetComponent<NetworkObject>();
m_SpawnedAsNetworkObject.NetworkManagerOwner = m_ServerNetworkManager;
m_AsNetworkObject.TrySetParent(baseObject);
m_BaseAsNetworkObject = baseObject.GetComponent<NetworkObject>();
m_BaseAsNetworkObject.NetworkManagerOwner = m_ServerNetworkManager;
m_AsNetworkObject.Spawn();
m_SpawnedAsNetworkObject.TrySetParent(baseObject);
m_SpawnedAsNetworkObject.Spawn();
yield return RefreshNetworkObjects();
m_AsNetworkObject.TrySetParent(baseObject);
m_SpawnedAsNetworkObject.TrySetParent(baseObject);
baseObject.GetComponent<TransformInterpolationObject>().IsFixed = true;
spawnedObject.GetComponent<TransformInterpolationObject>().IsMoving = true;
// Give two seconds for the object to settle
yield return new WaitForSeconds(2.0f);
const float maxPlacementError = 0.01f;
// Wait for the base object to place itself on both instances
while (m_BaseOnClient.transform.position.y < 1000 - maxPlacementError ||
m_BaseOnClient.transform.position.y > 1000 + maxPlacementError ||
baseObject.transform.position.y < 1000 - maxPlacementError ||
baseObject.transform.position.y > 1000 + maxPlacementError)
{
yield return new WaitForSeconds(0.01f);
}
m_SpawnedObjectOnClient.GetComponent<TransformInterpolationObject>().CheckPosition = true;

View File

@@ -1,53 +0,0 @@
using System;
using System.Text;
using NUnit.Framework;
using UnityEngine;
using Unity.Netcode.TestHelpers.Runtime;
namespace Unity.Netcode.RuntimeTests
{
public class SIPTransportTests
{
[Test]
public void SendReceiveData()
{
SIPTransport server = new GameObject("Server").AddComponent<SIPTransport>();
SIPTransport client = new GameObject("Client").AddComponent<SIPTransport>();
server.Initialize();
server.StartServer();
client.Initialize();
client.StartClient();
NetworkEvent serverEvent = server.PollEvent(out ulong clientId, out _, out _);
NetworkEvent clientEvent = client.PollEvent(out ulong serverId, out _, out _);
// Make sure both connected
Assert.True(serverEvent == NetworkEvent.Connect);
Assert.True(clientEvent == NetworkEvent.Connect);
// Send data
server.Send(clientId, new ArraySegment<byte>(Encoding.ASCII.GetBytes("Hello Client")), NetworkDelivery.ReliableSequenced);
client.Send(serverId, new ArraySegment<byte>(Encoding.ASCII.GetBytes("Hello Server")), NetworkDelivery.ReliableSequenced);
serverEvent = server.PollEvent(out ulong newClientId, out ArraySegment<byte> serverPayload, out _);
clientEvent = client.PollEvent(out ulong newServerId, out ArraySegment<byte> clientPayload, out _);
// Make sure we got data
Assert.True(serverEvent == NetworkEvent.Data);
Assert.True(clientEvent == NetworkEvent.Data);
// Make sure the ID is correct
Assert.True(newClientId == clientId);
Assert.True(newServerId == serverId);
// Make sure the payload was correct
Assert.That(serverPayload, Is.EquivalentTo(Encoding.ASCII.GetBytes("Hello Server")));
Assert.That(clientPayload, Is.EquivalentTo(Encoding.ASCII.GetBytes("Hello Client")));
server.Shutdown();
client.Shutdown();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: e3fe3777ca6a4f4392d6281d148d0d3c
timeCreated: 1620385694

View File

@@ -31,6 +31,11 @@
"name": "com.unity.multiplayer.tools",
"expression": "1.0.0-pre.7",
"define": "MULTIPLAYER_TOOLS_1_0_0_PRE_7"
},
{
"name": "com.unity.modules.physics",
"expression": "",
"define": "COM_UNITY_MODULES_PHYSICS"
}
]
}
}