com.unity.netcode.gameobjects@1.0.0-pre.6
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.6] - 2022-03-02 ### Added - NetworkAnimator now properly synchrhonizes all animation layers as well as runtime-adjusted weighting between them (#1765) - Added first set of tests for NetworkAnimator - parameter syncing, trigger set / reset, override network animator (#1735) ### Changed ### Fixed - Fixed an issue where sometimes the first client to connect to the server could see messages from the server as coming from itself. (#1683) - Fixed an issue where clients seemed to be able to send messages to ClientId 1, but these messages would actually still go to the server (id 0) instead of that client. (#1683) - Improved clarity of error messaging when a client attempts to send a message to a destination other than the server, which isn't allowed. (#1683) - Disallowed async keyword in RPCs (#1681) - Fixed an issue where Alpha release versions of Unity (version 2022.2.0a5 and later) will not compile due to the UNet Transport no longer existing (#1678) - Fixed messages larger than 64k being written with incorrectly truncated message size in header (#1686) (credit: @kaen) - Fixed overloading RPC methods causing collisions and failing on IL2CPP targets. (#1694) - Fixed spawn flow to propagate `IsSceneObject` down to children NetworkObjects, decouple implicit relationship between object spawning & `IsSceneObject` flag (#1685) - Fixed error when serializing ConnectionApprovalMessage with scene management disabled when one or more objects is hidden via the CheckObjectVisibility delegate (#1720) - Fixed CheckObjectVisibility delegate not being properly invoked for connecting clients when Scene Management is enabled. (#1680) - Fixed NetworkList to properly call INetworkSerializable's NetworkSerialize() method (#1682) - Fixed NetworkVariables containing more than 1300 bytes of data (such as large NetworkLists) no longer cause an OverflowException (the limit on data size is now whatever limit the chosen transport imposes on fragmented NetworkDelivery mechanisms) (#1725) - Fixed ServerRpcParams and ClientRpcParams must be the last parameter of an RPC in order to function properly. Added a compile-time check to ensure this is the case and trigger an error if they're placed elsewhere (#1721) - Fixed FastBufferReader being created with a length of 1 if provided an input of length 0 (#1724) - Fixed The NetworkConfig's checksum hash includes the NetworkTick so that clients with a different tickrate than the server are identified and not allowed to connect (#1728) - Fixed OwnedObjects not being properly modified when using ChangeOwnership (#1731) - Improved performance in NetworkAnimator (#1735) - Removed the "always sync" network animator (aka "autosend") parameters (#1746)
This commit is contained in:
@@ -15,6 +15,7 @@ namespace Unity.Netcode.EditorTests
|
||||
public int B;
|
||||
public int C;
|
||||
public static bool Deserialized;
|
||||
public static bool Handled;
|
||||
public static List<TestMessage> DeserializedValues = new List<TestMessage>();
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
@@ -22,11 +23,17 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
Deserialized = true;
|
||||
reader.ReadValueSafe(out TestMessage value);
|
||||
DeserializedValues.Add(value);
|
||||
reader.ReadValueSafe(out this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
Handled = true;
|
||||
DeserializedValues.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +46,7 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessage),
|
||||
Handler = TestMessage.Receive
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessage>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -51,6 +58,7 @@ namespace Unity.Netcode.EditorTests
|
||||
public void SetUp()
|
||||
{
|
||||
TestMessage.Deserialized = false;
|
||||
TestMessage.Handled = false;
|
||||
TestMessage.DeserializedValues.Clear();
|
||||
|
||||
m_MessagingSystem = new MessagingSystem(new NopMessageSender(), this, new TestMessageProvider());
|
||||
@@ -94,6 +102,7 @@ namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
m_MessagingSystem.HandleMessage(messageHeader, reader, 0, 0, 0);
|
||||
Assert.IsTrue(TestMessage.Deserialized);
|
||||
Assert.IsTrue(TestMessage.Handled);
|
||||
Assert.AreEqual(1, TestMessage.DeserializedValues.Count);
|
||||
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);
|
||||
}
|
||||
@@ -129,7 +138,8 @@ namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
m_MessagingSystem.HandleIncomingData(0, new ArraySegment<byte>(writer.ToArray()), 0);
|
||||
Assert.IsFalse(TestMessage.Deserialized);
|
||||
Assert.IsEmpty(TestMessage.DeserializedValues); ;
|
||||
Assert.IsFalse(TestMessage.Handled);
|
||||
Assert.IsEmpty(TestMessage.DeserializedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,6 +172,7 @@ namespace Unity.Netcode.EditorTests
|
||||
m_MessagingSystem.HandleIncomingData(0, new ArraySegment<byte>(writer.ToArray()), 0);
|
||||
m_MessagingSystem.ProcessIncomingMessageQueue();
|
||||
Assert.IsTrue(TestMessage.Deserialized);
|
||||
Assert.IsTrue(TestMessage.Handled);
|
||||
Assert.AreEqual(1, TestMessage.DeserializedValues.Count);
|
||||
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);
|
||||
}
|
||||
@@ -199,10 +210,12 @@ namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
m_MessagingSystem.HandleIncomingData(0, new ArraySegment<byte>(writer.ToArray()), 0);
|
||||
Assert.IsFalse(TestMessage.Deserialized);
|
||||
Assert.IsFalse(TestMessage.Handled);
|
||||
Assert.IsEmpty(TestMessage.DeserializedValues);
|
||||
|
||||
m_MessagingSystem.ProcessIncomingMessageQueue();
|
||||
Assert.IsTrue(TestMessage.Deserialized);
|
||||
Assert.IsTrue(TestMessage.Handled);
|
||||
Assert.AreEqual(2, TestMessage.DeserializedValues.Count);
|
||||
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);
|
||||
Assert.AreEqual(message2, TestMessage.DeserializedValues[1]);
|
||||
|
||||
@@ -5,21 +5,23 @@ namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class MessageRegistrationTests
|
||||
{
|
||||
|
||||
private struct TestMessageOne : INetworkMessage
|
||||
{
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,15 +30,18 @@ namespace Unity.Netcode.EditorTests
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
private class TestMessageProviderOne : IMessageProvider
|
||||
@@ -48,12 +53,12 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageOne),
|
||||
Handler = TestMessageOne.Receive
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageOne>
|
||||
},
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageTwo),
|
||||
Handler = TestMessageTwo.Receive
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageTwo>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -64,15 +69,18 @@ namespace Unity.Netcode.EditorTests
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
private class TestMessageProviderTwo : IMessageProvider
|
||||
@@ -84,26 +92,28 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageThree),
|
||||
Handler = TestMessageThree.Receive
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageThree>
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestMessageFour : INetworkMessage
|
||||
{
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
private class TestMessageProviderThree : IMessageProvider
|
||||
@@ -115,7 +125,7 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageFour),
|
||||
Handler = TestMessageFour.Receive
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageFour>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -158,21 +168,17 @@ namespace Unity.Netcode.EditorTests
|
||||
using (systemTwo)
|
||||
using (systemThree)
|
||||
{
|
||||
MessagingSystem.MessageHandler handlerOne = TestMessageOne.Receive;
|
||||
MessagingSystem.MessageHandler handlerTwo = TestMessageTwo.Receive;
|
||||
MessagingSystem.MessageHandler handlerThree = TestMessageThree.Receive;
|
||||
MessagingSystem.MessageHandler handlerFour = TestMessageFour.Receive;
|
||||
MessagingSystem.MessageHandler handlerOne = MessagingSystem.ReceiveMessage<TestMessageOne>;
|
||||
MessagingSystem.MessageHandler handlerTwo = MessagingSystem.ReceiveMessage<TestMessageTwo>;
|
||||
MessagingSystem.MessageHandler handlerThree = MessagingSystem.ReceiveMessage<TestMessageThree>;
|
||||
MessagingSystem.MessageHandler handlerFour = MessagingSystem.ReceiveMessage<TestMessageFour>;
|
||||
|
||||
var foundHandlerOne = systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageOne))];
|
||||
|
||||
Assert.AreEqual(handlerOne,
|
||||
systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageOne))]);
|
||||
Assert.AreEqual(handlerTwo,
|
||||
systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageTwo))]);
|
||||
Assert.AreEqual(handlerThree,
|
||||
systemTwo.MessageHandlers[systemTwo.GetMessageType(typeof(TestMessageThree))]);
|
||||
Assert.AreEqual(handlerFour,
|
||||
systemThree.MessageHandlers[systemThree.GetMessageType(typeof(TestMessageFour))]);
|
||||
Assert.AreEqual(handlerOne, systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageOne))]);
|
||||
Assert.AreEqual(handlerTwo, systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageTwo))]);
|
||||
Assert.AreEqual(handlerThree, systemTwo.MessageHandlers[systemTwo.GetMessageType(typeof(TestMessageThree))]);
|
||||
Assert.AreEqual(handlerFour, systemThree.MessageHandlers[systemThree.GetMessageType(typeof(TestMessageFour))]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,18 @@ namespace Unity.Netcode.EditorTests
|
||||
public int B;
|
||||
public int C;
|
||||
public static bool Serialized;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
Serialized = true;
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -45,7 +49,7 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessage),
|
||||
Handler = TestMessage.Receive
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessage>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -86,7 +90,7 @@ namespace Unity.Netcode.EditorTests
|
||||
public void WhenSendingMessage_SerializeIsCalled()
|
||||
{
|
||||
var message = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
Assert.IsTrue(TestMessage.Serialized);
|
||||
}
|
||||
|
||||
@@ -94,7 +98,7 @@ namespace Unity.Netcode.EditorTests
|
||||
public void WhenSendingMessage_NothingIsSentBeforeProcessingSendQueue()
|
||||
{
|
||||
var message = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
Assert.IsEmpty(m_MessageSender.MessageQueue);
|
||||
}
|
||||
|
||||
@@ -102,7 +106,7 @@ namespace Unity.Netcode.EditorTests
|
||||
public void WhenProcessingSendQueue_MessageIsSent()
|
||||
{
|
||||
var message = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
Assert.AreEqual(1, m_MessageSender.MessageQueue.Count);
|
||||
@@ -112,9 +116,9 @@ namespace Unity.Netcode.EditorTests
|
||||
public void WhenSendingMultipleMessages_MessagesAreBatched()
|
||||
{
|
||||
var message = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
Assert.AreEqual(1, m_MessageSender.MessageQueue.Count);
|
||||
@@ -127,7 +131,7 @@ namespace Unity.Netcode.EditorTests
|
||||
var size = UnsafeUtility.SizeOf<TestMessage>() + 2; // MessageHeader packed with this message will be 2 bytes
|
||||
for (var i = 0; i < 1300 / size; ++i)
|
||||
{
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
}
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
@@ -141,7 +145,7 @@ namespace Unity.Netcode.EditorTests
|
||||
var size = UnsafeUtility.SizeOf<TestMessage>() + 2; // MessageHeader packed with this message will be 2 bytes
|
||||
for (var i = 0; i < (1300 / size) + 1; ++i)
|
||||
{
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
}
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
@@ -155,7 +159,7 @@ namespace Unity.Netcode.EditorTests
|
||||
var size = UnsafeUtility.SizeOf<TestMessage>() + 2; // MessageHeader packed with this message will be 2 bytes
|
||||
for (var i = 0; i < (1300 / size) + 1; ++i)
|
||||
{
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.ReliableFragmentedSequenced, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, m_Clients);
|
||||
}
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
@@ -166,9 +170,9 @@ namespace Unity.Netcode.EditorTests
|
||||
public void WhenSwitchingDelivery_NewBatchesAreCreated()
|
||||
{
|
||||
var message = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Unreliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Unreliable, m_Clients);
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
Assert.AreEqual(2, m_MessageSender.MessageQueue.Count);
|
||||
@@ -178,9 +182,9 @@ namespace Unity.Netcode.EditorTests
|
||||
public void WhenSwitchingChannel_NewBatchesAreNotCreated()
|
||||
{
|
||||
var message = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
Assert.AreEqual(1, m_MessageSender.MessageQueue.Count);
|
||||
@@ -191,8 +195,8 @@ namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
var message = GetMessage();
|
||||
var message2 = GetMessage();
|
||||
m_MessagingSystem.SendMessage(message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(message2, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients);
|
||||
m_MessagingSystem.SendMessage(ref message2, NetworkDelivery.Reliable, m_Clients);
|
||||
|
||||
m_MessagingSystem.ProcessSendQueues();
|
||||
var reader = new FastBufferReader(m_MessageSender.MessageQueue[0], Allocator.Temp);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
fileFormatVersion: 2
|
||||
guid: e12c4be6e89f459aa2826abba8c8d301
|
||||
timeCreated: 1628799671
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -3,7 +3,7 @@ using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using Random = System.Random;
|
||||
|
||||
namespace Unity.Netcode
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public abstract class BaseFastBufferReaderWriterTest
|
||||
{
|
||||
|
||||
@@ -346,6 +346,52 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingAReaderFromAnEmptyArraySegment_LengthIsZero()
|
||||
{
|
||||
var bytes = new byte[] { };
|
||||
var input = new ArraySegment<byte>(bytes, 0, 0);
|
||||
using var reader = new FastBufferReader(input, Allocator.Temp);
|
||||
Assert.AreEqual(0, reader.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingAReaderFromAnEmptyArray_LengthIsZero()
|
||||
{
|
||||
var input = new byte[] { };
|
||||
using var reader = new FastBufferReader(input, Allocator.Temp);
|
||||
Assert.AreEqual(0, reader.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingAReaderFromAnEmptyNativeArray_LengthIsZero()
|
||||
{
|
||||
var input = new NativeArray<byte>(0, Allocator.Temp);
|
||||
using var reader = new FastBufferReader(input, Allocator.Temp);
|
||||
Assert.AreEqual(0, reader.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingAReaderFromAnEmptyFastBufferWriter_LengthIsZero()
|
||||
{
|
||||
var input = new FastBufferWriter(0, Allocator.Temp);
|
||||
using var reader = new FastBufferReader(input, Allocator.Temp);
|
||||
Assert.AreEqual(0, reader.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingAReaderFromAnEmptyBuffer_LengthIsZero()
|
||||
{
|
||||
var input = new byte[] { };
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = input)
|
||||
{
|
||||
using var reader = new FastBufferReader(ptr, Allocator.Temp, 0);
|
||||
Assert.AreEqual(0, reader.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCallingReadByteWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown()
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Unity.Netcode.EditorTests
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal int SendMessage(in SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId)
|
||||
internal int SendMessage(ref SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId)
|
||||
{
|
||||
if (!m_PassBackResponses)
|
||||
{
|
||||
@@ -106,19 +106,15 @@ namespace Unity.Netcode.EditorTests
|
||||
message.Serialize(writer);
|
||||
using var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
var context = new NetworkContext { SenderId = 0, Timestamp = 0.0f, SystemOwner = new Tuple<SnapshotSystem, ulong>(m_RecvSnapshot, 0) };
|
||||
SnapshotDataMessage.Receive(reader, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Spawns.Dispose();
|
||||
message.Despawns.Dispose();
|
||||
message.Entries.Dispose();
|
||||
var newMessage = new SnapshotDataMessage();
|
||||
newMessage.Deserialize(reader, ref context);
|
||||
newMessage.Handle(ref context);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal int SendMessageRecvSide(in SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId)
|
||||
internal int SendMessageRecvSide(ref SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId)
|
||||
{
|
||||
if (m_PassBackResponses)
|
||||
{
|
||||
@@ -126,13 +122,9 @@ namespace Unity.Netcode.EditorTests
|
||||
message.Serialize(writer);
|
||||
using var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
var context = new NetworkContext { SenderId = 0, Timestamp = 0.0f, SystemOwner = new Tuple<SnapshotSystem, ulong>(m_SendSnapshot, 1) };
|
||||
SnapshotDataMessage.Receive(reader, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Spawns.Dispose();
|
||||
message.Despawns.Dispose();
|
||||
message.Entries.Dispose();
|
||||
var newMessage = new SnapshotDataMessage();
|
||||
newMessage.Deserialize(reader, ref context);
|
||||
newMessage.Handle(ref context);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -369,4 +361,3 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
"Unity.Netcode.Editor",
|
||||
"Unity.Netcode.Components",
|
||||
"Unity.Multiplayer.MetricTypes",
|
||||
"Unity.Multiplayer.NetStats"
|
||||
"Unity.Multiplayer.NetStats",
|
||||
"Unity.Multiplayer.Tools.MetricTypes",
|
||||
"Unity.Multiplayer.Tools.NetStats"
|
||||
],
|
||||
"optionalUnityReferences": [
|
||||
"TestAssemblies"
|
||||
@@ -15,18 +17,7 @@
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false,
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.multiplayer.tools",
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public abstract class BaseMultiInstanceTest
|
||||
{
|
||||
private const string k_FirstPartOfTestRunnerSceneName = "InitTestScene";
|
||||
|
||||
protected GameObject m_PlayerPrefab;
|
||||
protected NetworkManager m_ServerNetworkManager;
|
||||
protected NetworkManager[] m_ClientNetworkManagers;
|
||||
|
||||
protected abstract int NbClients { get; }
|
||||
|
||||
protected bool m_BypassStartAndWaitForClients = false;
|
||||
|
||||
[UnitySetUp]
|
||||
public virtual IEnumerator Setup()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, _ => { });
|
||||
}
|
||||
|
||||
[UnityTearDown]
|
||||
public virtual IEnumerator Teardown()
|
||||
{
|
||||
// Shutdown and clean up both of our NetworkManager instances
|
||||
try
|
||||
{
|
||||
MultiInstanceHelpers.Destroy();
|
||||
}
|
||||
catch (Exception e) { throw e; }
|
||||
finally
|
||||
{
|
||||
if (m_PlayerPrefab != null)
|
||||
{
|
||||
Object.Destroy(m_PlayerPrefab);
|
||||
m_PlayerPrefab = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure any NetworkObject with a GlobalObjectIdHash value of 0 is destroyed
|
||||
// If we are tearing down, we don't want to leave NetworkObjects hanging around
|
||||
var networkObjects = Object.FindObjectsOfType<NetworkObject>().ToList();
|
||||
foreach (var networkObject in networkObjects)
|
||||
{
|
||||
Object.DestroyImmediate(networkObject);
|
||||
}
|
||||
|
||||
// wait for next frame so everything is destroyed, so following tests can execute from clean environment
|
||||
int nextFrameNumber = Time.frameCount + 1;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We want to exclude the TestRunner scene on the host-server side so it won't try to tell clients to
|
||||
/// synchronize to this scene when they connect
|
||||
/// </summary>
|
||||
private static bool VerifySceneIsValidForClientsToLoad(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
|
||||
{
|
||||
// exclude test runner scene
|
||||
if (sceneName.StartsWith(k_FirstPartOfTestRunnerSceneName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This registers scene validation callback for the server to prevent it from telling connecting
|
||||
/// clients to synchronize (i.e. load) the test runner scene. This will also register the test runner
|
||||
/// scene and its handle for both client(s) and server-host.
|
||||
/// </summary>
|
||||
public static void SceneManagerValidationAndTestRunnerInitialization(NetworkManager networkManager)
|
||||
{
|
||||
// If VerifySceneBeforeLoading is not already set, then go ahead and set it so the host/server
|
||||
// will not try to synchronize clients to the TestRunner scene. We only need to do this for the server.
|
||||
if (networkManager.IsServer && networkManager.SceneManager.VerifySceneBeforeLoading == null)
|
||||
{
|
||||
networkManager.SceneManager.VerifySceneBeforeLoading = VerifySceneIsValidForClientsToLoad;
|
||||
// If a unit/integration test does not handle this on their own, then Ignore the validation warning
|
||||
networkManager.SceneManager.DisableValidationWarnings(true);
|
||||
}
|
||||
|
||||
// Register the test runner scene so it will be able to synchronize NetworkObjects without logging a
|
||||
// warning about using the currently active scene
|
||||
var scene = SceneManager.GetActiveScene();
|
||||
// As long as this is a test runner scene (or most likely a test runner scene)
|
||||
if (scene.name.StartsWith(k_FirstPartOfTestRunnerSceneName))
|
||||
{
|
||||
// Register the test runner scene just so we avoid another warning about not being able to find the
|
||||
// scene to synchronize NetworkObjects. Next, add the currently active test runner scene to the scenes
|
||||
// loaded and register the server to client scene handle since host-server shares the test runner scene
|
||||
// with the clients.
|
||||
networkManager.SceneManager.GetAndAddNewlyLoadedSceneByName(scene.name);
|
||||
networkManager.SceneManager.ServerSceneHandleToClientSceneHandle.Add(scene.handle, scene.handle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility to spawn some clients and a server and set them up
|
||||
/// </summary>
|
||||
/// <param name="nbClients"></param>
|
||||
/// <param name="updatePlayerPrefab">Update the prefab with whatever is needed before players spawn</param>
|
||||
/// <param name="targetFrameRate">The targetFrameRate of the Unity engine to use while this multi instance test is running. Will be reset on teardown.</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerator StartSomeClientsAndServerWithPlayers(bool useHost, int nbClients, Action<GameObject> updatePlayerPrefab = null, int targetFrameRate = 60)
|
||||
{
|
||||
// Make sure any NetworkObject with a GlobalObjectIdHash value of 0 is destroyed
|
||||
// If we are tearing down, we don't want to leave NetworkObjects hanging around
|
||||
var networkObjects = Object.FindObjectsOfType<NetworkObject>().ToList();
|
||||
var networkObjectsList = networkObjects.Where(c => c.GlobalObjectIdHash == 0);
|
||||
foreach (var netObject in networkObjects)
|
||||
{
|
||||
Object.DestroyImmediate(netObject);
|
||||
}
|
||||
|
||||
// Create multiple NetworkManager instances
|
||||
if (!MultiInstanceHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients, targetFrameRate))
|
||||
{
|
||||
Debug.LogError("Failed to create instances");
|
||||
Assert.Fail("Failed to create instances");
|
||||
}
|
||||
|
||||
m_ClientNetworkManagers = clients;
|
||||
m_ServerNetworkManager = server;
|
||||
|
||||
// Create playerPrefab
|
||||
m_PlayerPrefab = new GameObject("Player");
|
||||
NetworkObject networkObject = m_PlayerPrefab.AddComponent<NetworkObject>();
|
||||
/*
|
||||
* Normally we would only allow player prefabs to be set to a prefab. Not runtime created objects.
|
||||
* In order to prevent having a Resource folder full of a TON of prefabs that we have to maintain,
|
||||
* MultiInstanceHelper has a helper function that lets you mark a runtime created object to be
|
||||
* treated as a prefab by the Netcode. That's how we can get away with creating the player prefab
|
||||
* at runtime without it being treated as a SceneObject or causing other conflicts with the Netcode.
|
||||
*/
|
||||
// Make it a prefab
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
|
||||
if (updatePlayerPrefab != null)
|
||||
{
|
||||
updatePlayerPrefab(m_PlayerPrefab); // update player prefab with whatever is needed before players are spawned
|
||||
}
|
||||
|
||||
// Set the player prefab
|
||||
server.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
|
||||
for (int i = 0; i < clients.Length; i++)
|
||||
{
|
||||
clients[i].NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
}
|
||||
|
||||
if (!m_BypassStartAndWaitForClients)
|
||||
{
|
||||
// Start the instances and pass in our SceneManagerInitialization action that is invoked immediately after host-server
|
||||
// is started and after each client is started.
|
||||
if (!MultiInstanceHelpers.Start(useHost, server, clients, SceneManagerValidationAndTestRunnerInitialization))
|
||||
{
|
||||
Debug.LogError("Failed to start instances");
|
||||
Assert.Fail("Failed to start instances");
|
||||
}
|
||||
|
||||
// Wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
|
||||
|
||||
// Wait for connection on server side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, useHost ? nbClients + 1 : nbClients));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 789a3189410645aca48f11a51c823418
|
||||
timeCreated: 1621620979
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -11,24 +12,24 @@ namespace Unity.Netcode.RuntimeTests
|
||||
/// </summary>
|
||||
internal class NetworkVariableTestComponent : NetworkBehaviour
|
||||
{
|
||||
private NetworkVariable<bool> m_NetworkVariableBool;
|
||||
private NetworkVariable<byte> m_NetworkVariableByte;
|
||||
private NetworkVariable<Color> m_NetworkVariableColor;
|
||||
private NetworkVariable<Color32> m_NetworkVariableColor32;
|
||||
private NetworkVariable<double> m_NetworkVariableDouble;
|
||||
private NetworkVariable<float> m_NetworkVariableFloat;
|
||||
private NetworkVariable<int> m_NetworkVariableInt;
|
||||
private NetworkVariable<long> m_NetworkVariableLong;
|
||||
private NetworkVariable<sbyte> m_NetworkVariableSByte;
|
||||
private NetworkVariable<Quaternion> m_NetworkVariableQuaternion;
|
||||
private NetworkVariable<short> m_NetworkVariableShort;
|
||||
private NetworkVariable<Vector4> m_NetworkVariableVector4;
|
||||
private NetworkVariable<Vector3> m_NetworkVariableVector3;
|
||||
private NetworkVariable<Vector2> m_NetworkVariableVector2;
|
||||
private NetworkVariable<Ray> m_NetworkVariableRay;
|
||||
private NetworkVariable<ulong> m_NetworkVariableULong;
|
||||
private NetworkVariable<uint> m_NetworkVariableUInt;
|
||||
private NetworkVariable<ushort> m_NetworkVariableUShort;
|
||||
private NetworkVariable<bool> m_NetworkVariableBool = new NetworkVariable<bool>();
|
||||
private NetworkVariable<byte> m_NetworkVariableByte = new NetworkVariable<byte>();
|
||||
private NetworkVariable<Color> m_NetworkVariableColor = new NetworkVariable<Color>();
|
||||
private NetworkVariable<Color32> m_NetworkVariableColor32 = new NetworkVariable<Color32>();
|
||||
private NetworkVariable<double> m_NetworkVariableDouble = new NetworkVariable<double>();
|
||||
private NetworkVariable<float> m_NetworkVariableFloat = new NetworkVariable<float>();
|
||||
private NetworkVariable<int> m_NetworkVariableInt = new NetworkVariable<int>();
|
||||
private NetworkVariable<long> m_NetworkVariableLong = new NetworkVariable<long>();
|
||||
private NetworkVariable<sbyte> m_NetworkVariableSByte = new NetworkVariable<sbyte>();
|
||||
private NetworkVariable<Quaternion> m_NetworkVariableQuaternion = new NetworkVariable<Quaternion>();
|
||||
private NetworkVariable<short> m_NetworkVariableShort = new NetworkVariable<short>();
|
||||
private NetworkVariable<Vector4> m_NetworkVariableVector4 = new NetworkVariable<Vector4>();
|
||||
private NetworkVariable<Vector3> m_NetworkVariableVector3 = new NetworkVariable<Vector3>();
|
||||
private NetworkVariable<Vector2> m_NetworkVariableVector2 = new NetworkVariable<Vector2>();
|
||||
private NetworkVariable<Ray> m_NetworkVariableRay = new NetworkVariable<Ray>();
|
||||
private NetworkVariable<ulong> m_NetworkVariableULong = new NetworkVariable<ulong>();
|
||||
private NetworkVariable<uint> m_NetworkVariableUInt = new NetworkVariable<uint>();
|
||||
private NetworkVariable<ushort> m_NetworkVariableUShort = new NetworkVariable<ushort>();
|
||||
|
||||
|
||||
public NetworkVariableHelper<bool> Bool_Var;
|
||||
|
||||
13
Tests/Runtime/Components/NetworkVisibilityComponent.cs
Normal file
13
Tests/Runtime/Components/NetworkVisibilityComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkVisibilityComponent : NetworkBehaviour
|
||||
{
|
||||
public void Hide()
|
||||
{
|
||||
GetComponent<NetworkObject>().CheckObjectVisibility += HandleCheckObjectVisibility;
|
||||
}
|
||||
|
||||
protected virtual bool HandleCheckObjectVisibility(ulong clientId) => false;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c920be150fd14ad4ca1936e1a259417c
|
||||
guid: 7c8284d1c5a9f4c3783a16e314376ea3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -4,6 +4,7 @@ using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -12,13 +13,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator RemoteDisconnectPlayerObjectCleanup()
|
||||
{
|
||||
// create server and client instances
|
||||
MultiInstanceHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
|
||||
NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
|
||||
|
||||
// create prefab
|
||||
var gameObject = new GameObject("PlayerObject");
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
networkObject.DontDestroyWithOwner = true;
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
|
||||
server.NetworkConfig.PlayerPrefab = gameObject;
|
||||
|
||||
@@ -28,13 +29,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
// start server and connect clients
|
||||
MultiInstanceHelpers.Start(false, server, clients);
|
||||
NetcodeIntegrationTestHelpers.Start(false, server, clients);
|
||||
|
||||
// wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients);
|
||||
|
||||
// wait for connection on server side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(server));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(server);
|
||||
|
||||
// disconnect the remote client
|
||||
server.DisconnectClient(clients[0].LocalClientId);
|
||||
@@ -47,7 +48,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Assert.False(server.SpawnManager.SpawnedObjects.Any(x => x.Value.IsPlayerObject && x.Value.OwnerClientId == clients[0].LocalClientId));
|
||||
|
||||
// cleanup
|
||||
MultiInstanceHelpers.Destroy();
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.Transports.UNET;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to instantiate a NetworkManager
|
||||
/// This also provides the ability to:
|
||||
/// --- instantiate GameObjects with NetworkObject components that returns a Guid for accessing it later.
|
||||
/// --- add NetworkBehaviour components to the instantiated GameObjects
|
||||
/// --- spawn a NetworkObject using its parent GameObject's Guid
|
||||
/// Call StartNetworkManager in the constructor of your runtime unit test class.
|
||||
/// Call ShutdownNetworkManager in the destructor of your runtime unit test class.
|
||||
///
|
||||
/// Includes a useful "BuffersMatch" method that allows you to compare two buffers (returns true if they match false if not)
|
||||
/// </summary>
|
||||
public static class NetworkManagerHelper
|
||||
{
|
||||
public static NetworkManager NetworkManagerObject { get; internal set; }
|
||||
public static GameObject NetworkManagerGameObject { get; internal set; }
|
||||
|
||||
internal static Dictionary<Guid, GameObject> InstantiatedGameObjects = new Dictionary<Guid, GameObject>();
|
||||
internal static Dictionary<Guid, NetworkObject> InstantiatedNetworkObjects = new Dictionary<Guid, NetworkObject>();
|
||||
internal static NetworkManagerOperatingMode CurrentNetworkManagerMode;
|
||||
|
||||
/// <summary>
|
||||
/// This provides the ability to start NetworkManager in various modes
|
||||
/// </summary>
|
||||
public enum NetworkManagerOperatingMode
|
||||
{
|
||||
None,
|
||||
Host,
|
||||
Server,
|
||||
Client,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called upon the RpcQueueTests being instantiated.
|
||||
/// This creates an instance of the NetworkManager to be used during unit tests.
|
||||
/// Currently, the best method to run unit tests is by starting in host mode as you can
|
||||
/// send messages to yourself (i.e. Host-Client to Host-Server and vice versa).
|
||||
/// As such, the default setting is to start in Host mode.
|
||||
/// </summary>
|
||||
/// <param name="managerMode">parameter to specify which mode you want to start the NetworkManager</param>
|
||||
/// <param name="networkConfig">parameter to specify custom NetworkConfig settings</param>
|
||||
/// <returns>true if it was instantiated or is already instantiate otherwise false means it failed to instantiate</returns>
|
||||
public static bool StartNetworkManager(out NetworkManager networkManager, NetworkManagerOperatingMode managerMode = NetworkManagerOperatingMode.Host, NetworkConfig networkConfig = null)
|
||||
{
|
||||
// If we are changing the current manager mode and the current manager mode is not "None", then stop the NetworkManager mode
|
||||
if (CurrentNetworkManagerMode != managerMode && CurrentNetworkManagerMode != NetworkManagerOperatingMode.None)
|
||||
{
|
||||
StopNetworkManagerMode();
|
||||
}
|
||||
|
||||
if (NetworkManagerGameObject == null)
|
||||
{
|
||||
NetworkManagerGameObject = new GameObject(nameof(NetworkManager));
|
||||
NetworkManagerObject = NetworkManagerGameObject.AddComponent<NetworkManager>();
|
||||
|
||||
if (NetworkManagerObject == null)
|
||||
{
|
||||
networkManager = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log($"{nameof(NetworkManager)} Instantiated.");
|
||||
|
||||
var unetTransport = NetworkManagerGameObject.AddComponent<UNetTransport>();
|
||||
if (networkConfig == null)
|
||||
{
|
||||
networkConfig = new NetworkConfig
|
||||
{
|
||||
EnableSceneManagement = false,
|
||||
};
|
||||
}
|
||||
|
||||
NetworkManagerObject.NetworkConfig = networkConfig;
|
||||
|
||||
unetTransport.ConnectAddress = "127.0.0.1";
|
||||
unetTransport.ConnectPort = 7777;
|
||||
unetTransport.ServerListenPort = 7777;
|
||||
unetTransport.MessageBufferSize = 65535;
|
||||
unetTransport.MaxConnections = 100;
|
||||
unetTransport.MessageSendMode = UNetTransport.SendMode.Immediately;
|
||||
NetworkManagerObject.NetworkConfig.NetworkTransport = unetTransport;
|
||||
|
||||
// Starts the network manager in the mode specified
|
||||
StartNetworkManagerMode(managerMode);
|
||||
}
|
||||
|
||||
networkManager = NetworkManagerObject;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a GameObject with a NetworkObject component
|
||||
/// </summary>
|
||||
/// <param name="nameOfGameObject">the name of the object</param>
|
||||
/// <returns></returns>
|
||||
public static Guid AddGameNetworkObject(string nameOfGameObject)
|
||||
{
|
||||
var gameObjectId = Guid.NewGuid();
|
||||
|
||||
// Create the player object that we will spawn as a host
|
||||
var gameObject = new GameObject(nameOfGameObject);
|
||||
|
||||
Assert.IsNotNull(gameObject);
|
||||
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
|
||||
Assert.IsNotNull(networkObject);
|
||||
|
||||
Assert.IsFalse(InstantiatedGameObjects.ContainsKey(gameObjectId));
|
||||
Assert.IsFalse(InstantiatedNetworkObjects.ContainsKey(gameObjectId));
|
||||
|
||||
InstantiatedGameObjects.Add(gameObjectId, gameObject);
|
||||
InstantiatedNetworkObjects.Add(gameObjectId, networkObject);
|
||||
|
||||
return gameObjectId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to add a component to the GameObject with a NetoworkObject component
|
||||
/// </summary>
|
||||
/// <typeparam name="T">NetworkBehaviour component being added to the GameObject</typeparam>
|
||||
/// <param name="gameObjectIdentifier">ID returned to reference the game object</param>
|
||||
/// <returns></returns>
|
||||
public static T AddComponentToObject<T>(Guid gameObjectIdentifier) where T : NetworkBehaviour
|
||||
{
|
||||
Assert.IsTrue(InstantiatedGameObjects.ContainsKey(gameObjectIdentifier));
|
||||
return InstantiatedGameObjects[gameObjectIdentifier].AddComponent<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawn the NetworkObject, so Rpcs can flow
|
||||
/// </summary>
|
||||
/// <param name="gameObjectIdentifier">ID returned to reference the game object</param>
|
||||
public static void SpawnNetworkObject(Guid gameObjectIdentifier)
|
||||
{
|
||||
Assert.IsTrue(InstantiatedNetworkObjects.ContainsKey(gameObjectIdentifier));
|
||||
if (!InstantiatedNetworkObjects[gameObjectIdentifier].IsSpawned)
|
||||
{
|
||||
InstantiatedNetworkObjects[gameObjectIdentifier].Spawn();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the NetworkManager in the current mode specified by managerMode
|
||||
/// </summary>
|
||||
/// <param name="managerMode">the mode to start the NetworkManager as</param>
|
||||
private static void StartNetworkManagerMode(NetworkManagerOperatingMode managerMode)
|
||||
{
|
||||
CurrentNetworkManagerMode = managerMode;
|
||||
switch (CurrentNetworkManagerMode)
|
||||
{
|
||||
case NetworkManagerOperatingMode.Host:
|
||||
{
|
||||
// Starts the host
|
||||
NetworkManagerObject.StartHost();
|
||||
break;
|
||||
}
|
||||
case NetworkManagerOperatingMode.Server:
|
||||
{
|
||||
// Starts the server
|
||||
NetworkManagerObject.StartServer();
|
||||
break;
|
||||
}
|
||||
case NetworkManagerOperatingMode.Client:
|
||||
{
|
||||
// Starts the client
|
||||
NetworkManagerObject.StartClient();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we started an netcode session
|
||||
if (CurrentNetworkManagerMode != NetworkManagerOperatingMode.None)
|
||||
{
|
||||
// With some unit tests the Singleton can still be from a previous unit test
|
||||
// depending upon the order of operations that occurred.
|
||||
if (NetworkManager.Singleton != NetworkManagerObject)
|
||||
{
|
||||
NetworkManagerObject.SetSingleton();
|
||||
}
|
||||
|
||||
// Only log this if we started an netcode session
|
||||
Debug.Log($"{CurrentNetworkManagerMode} started.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the current mode of the NetworkManager
|
||||
/// </summary>
|
||||
private static void StopNetworkManagerMode()
|
||||
{
|
||||
NetworkManagerObject.Shutdown();
|
||||
|
||||
Debug.Log($"{CurrentNetworkManagerMode} stopped.");
|
||||
CurrentNetworkManagerMode = NetworkManagerOperatingMode.None;
|
||||
}
|
||||
|
||||
// This is called, even if we assert and exit early from a test
|
||||
public static void ShutdownNetworkManager()
|
||||
{
|
||||
// clean up any game objects created with custom unit testing components
|
||||
foreach (var entry in InstantiatedGameObjects)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(entry.Value);
|
||||
}
|
||||
|
||||
InstantiatedGameObjects.Clear();
|
||||
|
||||
if (NetworkManagerGameObject != null)
|
||||
{
|
||||
Debug.Log($"{nameof(NetworkManager)} shutdown.");
|
||||
|
||||
StopNetworkManagerMode();
|
||||
UnityEngine.Object.DestroyImmediate(NetworkManagerGameObject);
|
||||
Debug.Log($"{nameof(NetworkManager)} destroyed.");
|
||||
}
|
||||
NetworkManagerGameObject = null;
|
||||
NetworkManagerObject = null;
|
||||
}
|
||||
|
||||
public static bool BuffersMatch(int indexOffset, long targetSize, byte[] sourceArray, byte[] originalArray)
|
||||
{
|
||||
long largeInt64Blocks = targetSize >> 3; // Divide by 8
|
||||
int originalArrayOffset = 0;
|
||||
// process by 8 byte blocks if we can
|
||||
for (long i = 0; i < largeInt64Blocks; i++)
|
||||
{
|
||||
if (BitConverter.ToInt64(sourceArray, indexOffset) != BitConverter.ToInt64(originalArray, originalArrayOffset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
indexOffset += 8;
|
||||
originalArrayOffset += 8;
|
||||
}
|
||||
|
||||
long offset = largeInt64Blocks * 8;
|
||||
long remainder = targetSize - offset;
|
||||
|
||||
// 4 byte block
|
||||
if (remainder >= 4)
|
||||
{
|
||||
if (BitConverter.ToInt32(sourceArray, indexOffset) != BitConverter.ToInt32(originalArray, originalArrayOffset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
indexOffset += 4;
|
||||
originalArrayOffset += 4;
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
// Remainder of bytes < 4
|
||||
if (targetSize - offset > 0)
|
||||
{
|
||||
for (long i = 0; i < (targetSize - offset); i++)
|
||||
{
|
||||
if (sourceArray[indexOffset + i] != originalArray[originalArrayOffset + i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Will automatically register for the NetworkVariable OnValueChanged
|
||||
/// delegate handler. It then will expose that single delegate invocation
|
||||
/// to anything that registers for this NetworkVariableHelper's instance's OnValueChanged event.
|
||||
/// This allows us to register any NetworkVariable type as well as there are basically two "types of types":
|
||||
/// IEquatable<T>
|
||||
/// ValueType
|
||||
/// From both we can then at least determine if the value indeed changed
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal class NetworkVariableHelper<T> : NetworkVariableBaseHelper where T : unmanaged
|
||||
{
|
||||
private readonly NetworkVariable<T> m_NetworkVariable;
|
||||
public delegate void OnMyValueChangedDelegateHandler(T previous, T next);
|
||||
public event OnMyValueChangedDelegateHandler OnValueChanged;
|
||||
|
||||
/// <summary>
|
||||
/// IEquatable<T> Equals Check
|
||||
/// </summary>
|
||||
private void CheckVariableChanged(IEquatable<T> previous, IEquatable<T> next)
|
||||
{
|
||||
if (!previous.Equals(next))
|
||||
{
|
||||
ValueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ValueType Equals Check
|
||||
/// </summary>
|
||||
private void CheckVariableChanged(ValueType previous, ValueType next)
|
||||
{
|
||||
if (!previous.Equals(next))
|
||||
{
|
||||
ValueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// INetworkVariable's OnVariableChanged delegate callback
|
||||
/// </summary>
|
||||
/// <param name="previous"></param>
|
||||
/// <param name="next"></param>
|
||||
private void OnVariableChanged(T previous, T next)
|
||||
{
|
||||
if (previous is ValueType testValueType)
|
||||
{
|
||||
CheckVariableChanged(previous, next);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckVariableChanged(previous as IEquatable<T>, next as IEquatable<T>);
|
||||
}
|
||||
|
||||
OnValueChanged?.Invoke(previous, next);
|
||||
}
|
||||
|
||||
public NetworkVariableHelper(NetworkVariableBase networkVariable) : base(networkVariable)
|
||||
{
|
||||
m_NetworkVariable = networkVariable as NetworkVariable<T>;
|
||||
m_NetworkVariable.OnValueChanged = OnVariableChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The BaseNetworkVariableHelper keeps track of:
|
||||
/// The number of instances and associates the instance with the NetworkVariable
|
||||
/// The number of times a specific NetworkVariable instance had its value changed (i.e. !Equal)
|
||||
/// Note: This could be expanded for future tests focuses around NetworkVariables
|
||||
/// </summary>
|
||||
internal class NetworkVariableBaseHelper
|
||||
{
|
||||
private static Dictionary<NetworkVariableBaseHelper, NetworkVariableBase> s_Instances;
|
||||
private static Dictionary<NetworkVariableBase, int> s_InstanceChangedCount;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the total number of registered INetworkVariables
|
||||
/// </summary>
|
||||
public static int InstanceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Instances != null)
|
||||
{
|
||||
return s_Instances.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns total number of changes that occurred for all registered INetworkVariables
|
||||
/// </summary>
|
||||
public static int VarChangedCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_InstanceChangedCount != null)
|
||||
{
|
||||
var changeCount = 0;
|
||||
foreach (var keyPair in s_InstanceChangedCount)
|
||||
{
|
||||
changeCount += keyPair.Value;
|
||||
}
|
||||
return changeCount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the child class NetworkVariableHelper when a value changed
|
||||
/// </summary>
|
||||
protected void ValueChanged()
|
||||
{
|
||||
if (s_Instances.ContainsKey(this))
|
||||
{
|
||||
if (s_InstanceChangedCount.ContainsKey(s_Instances[this]))
|
||||
{
|
||||
s_InstanceChangedCount[s_Instances[this]]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkVariableBaseHelper(NetworkVariableBase networkVariable)
|
||||
{
|
||||
if (s_Instances == null)
|
||||
{
|
||||
s_Instances = new Dictionary<NetworkVariableBaseHelper, NetworkVariableBase>();
|
||||
}
|
||||
|
||||
if (s_InstanceChangedCount == null)
|
||||
{
|
||||
s_InstanceChangedCount = new Dictionary<NetworkVariableBase, int>();
|
||||
}
|
||||
|
||||
// Register new instance and associated INetworkVariable
|
||||
if (!s_Instances.ContainsKey(this))
|
||||
{
|
||||
s_Instances.Add(this, networkVariable);
|
||||
if (!s_InstanceChangedCount.ContainsKey(networkVariable))
|
||||
{
|
||||
s_InstanceChangedCount.Add(networkVariable, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -41,47 +42,23 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
}
|
||||
|
||||
public class HiddenVariableTests : BaseMultiInstanceTest
|
||||
public class HiddenVariableTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 4;
|
||||
protected override int NumberOfClients => 4;
|
||||
|
||||
private NetworkObject m_NetSpawnedObject;
|
||||
private List<NetworkObject> m_NetSpawnedObjectOnClient = new List<NetworkObject>();
|
||||
private GameObject m_TestNetworkPrefab;
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(useHost: true, nbClients: NbClients,
|
||||
updatePlayerPrefab: playerPrefab =>
|
||||
{
|
||||
var networkTransform = playerPrefab.AddComponent<HiddenVariableTest>();
|
||||
m_TestNetworkPrefab = PreparePrefab();
|
||||
});
|
||||
m_PlayerPrefab.AddComponent<HiddenVariableTest>();
|
||||
}
|
||||
|
||||
public GameObject PreparePrefab()
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
var prefabToSpawn = new GameObject("MyTestObject");
|
||||
var networkObjectPrefab = prefabToSpawn.AddComponent<NetworkObject>();
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObjectPrefab);
|
||||
prefabToSpawn.AddComponent<HiddenVariableObject>();
|
||||
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
clientNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
}
|
||||
return prefabToSpawn;
|
||||
}
|
||||
|
||||
public IEnumerator WaitForConnectedCount(int targetCount)
|
||||
{
|
||||
var endTime = Time.realtimeSinceStartup + 1.0;
|
||||
while (m_ServerNetworkManager.ConnectedClientsList.Count < targetCount && Time.realtimeSinceStartup < endTime)
|
||||
{
|
||||
yield return new WaitForSeconds(0.01f);
|
||||
}
|
||||
m_TestNetworkPrefab = CreateNetworkObjectPrefab("MyTestObject");
|
||||
m_TestNetworkPrefab.AddComponent<HiddenVariableObject>();
|
||||
}
|
||||
|
||||
public IEnumerator WaitForSpawnCount(int targetCount)
|
||||
@@ -131,12 +108,11 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
foreach (var netMan in m_ClientNetworkManagers)
|
||||
{
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(
|
||||
MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.NetworkObjectId == m_NetSpawnedObject.NetworkObjectId,
|
||||
netMan,
|
||||
serverClientPlayerResult));
|
||||
serverClientPlayerResult);
|
||||
m_NetSpawnedObjectOnClient.Add(serverClientPlayerResult.Result);
|
||||
}
|
||||
}
|
||||
@@ -151,22 +127,17 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
Debug.Log("Running test");
|
||||
|
||||
var spawnedObject = Object.Instantiate(m_TestNetworkPrefab);
|
||||
m_NetSpawnedObject = spawnedObject.GetComponent<NetworkObject>();
|
||||
m_NetSpawnedObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
yield return WaitForConnectedCount(NbClients);
|
||||
Debug.Log("Clients connected");
|
||||
|
||||
// ==== Spawn object with ownership on one client
|
||||
var client = m_ServerNetworkManager.ConnectedClientsList[1];
|
||||
var otherClient = m_ServerNetworkManager.ConnectedClientsList[2];
|
||||
m_NetSpawnedObject.SpawnWithOwnership(client.ClientId);
|
||||
m_NetSpawnedObject = SpawnObject(m_TestNetworkPrefab, m_ClientNetworkManagers[1]).GetComponent<NetworkObject>();
|
||||
|
||||
yield return RefreshGameObects();
|
||||
|
||||
// === Check spawn occured
|
||||
yield return WaitForSpawnCount(NbClients + 1);
|
||||
Debug.Assert(HiddenVariableObject.SpawnCount == NbClients + 1);
|
||||
yield return WaitForSpawnCount(NumberOfClients + 1);
|
||||
Debug.Assert(HiddenVariableObject.SpawnCount == NumberOfClients + 1);
|
||||
Debug.Log("Objects spawned");
|
||||
|
||||
// ==== Set the NetworkVariable value to 2
|
||||
|
||||
184
Tests/Runtime/IntegrationTestExamples.cs
Normal file
184
Tests/Runtime/IntegrationTestExamples.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class IntegrationTestUpdated : NetcodeIntegrationTest
|
||||
{
|
||||
private GameObject m_MyNetworkPrefab;
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_MyNetworkPrefab = CreateNetworkObjectPrefab("Object");
|
||||
m_MyNetworkPrefab.AddComponent<NetworkVisibilityComponent>();
|
||||
}
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
SpawnObject(m_MyNetworkPrefab, m_ServerNetworkManager);
|
||||
yield return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator MyFirstIntegationTest()
|
||||
{
|
||||
// Check the condition for this test and automatically handle varying processing
|
||||
// environments and conditions
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Object.FindObjectsOfType<NetworkVisibilityComponent>().Where(
|
||||
(c) => c.IsSpawned).Count() == 2);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for instances " +
|
||||
"to be detected!");
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture(HostOrServer.Host)]
|
||||
[TestFixture(HostOrServer.Server)]
|
||||
public class IntegrationTestExtended : NetcodeIntegrationTest
|
||||
{
|
||||
private GameObject m_MyNetworkPrefab;
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_MyNetworkPrefab = CreateNetworkObjectPrefab("Object");
|
||||
m_MyNetworkPrefab.AddComponent<NetworkVisibilityComponent>();
|
||||
}
|
||||
|
||||
public IntegrationTestExtended(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
SpawnObject(m_MyNetworkPrefab, m_ServerNetworkManager);
|
||||
yield return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator MyFirstIntegationTest()
|
||||
{
|
||||
// Check the condition for this test and automatically handle varying processing
|
||||
// environments and conditions
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Object.FindObjectsOfType<NetworkVisibilityComponent>().Where(
|
||||
(c) => c.IsSpawned).Count() == 2);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for instances " +
|
||||
"to be detected!");
|
||||
}
|
||||
}
|
||||
|
||||
public class ExampleTestComponent : NetworkBehaviour
|
||||
{
|
||||
}
|
||||
|
||||
public class IntegrationTestPlayers : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 5;
|
||||
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<ExampleTestComponent>();
|
||||
}
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClientRelativePlayers()
|
||||
{
|
||||
// Check that all instances have the ExampleTestComponent
|
||||
foreach (var clientRelativePlayers in m_PlayerNetworkObjects)
|
||||
{
|
||||
foreach (var playerInstance in clientRelativePlayers.Value)
|
||||
{
|
||||
var player = playerInstance.Value;
|
||||
Assert.NotNull(player.GetComponent<ExampleTestComponent>());
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm Player ID 1 on Client ID 4 is not the local player
|
||||
Assert.IsFalse(m_PlayerNetworkObjects[4][1].IsLocalPlayer);
|
||||
// Confirm Player ID 4 on Client ID 4 is the local player
|
||||
Assert.IsTrue(m_PlayerNetworkObjects[4][4].IsLocalPlayer);
|
||||
// Confirm Player ID 0 on Client ID 0 (host) NetworkManager is the server
|
||||
Assert.IsTrue(m_PlayerNetworkObjects[0][0].NetworkManager.IsServer);
|
||||
// Confirm Player ID 0 on Client ID 4 (client) NetworkManager is not the server
|
||||
Assert.IsFalse(m_PlayerNetworkObjects[4][0].NetworkManager.IsServer);
|
||||
}
|
||||
}
|
||||
|
||||
public class SpawnTest : NetworkBehaviour
|
||||
{
|
||||
public static int TotalSpawned;
|
||||
public override void OnNetworkSpawn() { TotalSpawned++; }
|
||||
public override void OnNetworkDespawn() { TotalSpawned--; }
|
||||
}
|
||||
public class IntegrationTestSpawning : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 2;
|
||||
private GameObject m_NetworkPrefabToSpawn;
|
||||
private int m_NumberToSpawn = 5;
|
||||
|
||||
protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode()
|
||||
{
|
||||
return NetworkManagerInstatiationMode.AllTests;
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_NetworkPrefabToSpawn = CreateNetworkObjectPrefab("TrackingTest");
|
||||
m_NetworkPrefabToSpawn.gameObject.AddComponent<SpawnTest>();
|
||||
}
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
SpawnObjects(m_NetworkPrefabToSpawn, m_ServerNetworkManager, m_NumberToSpawn);
|
||||
return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
[Order(1)]
|
||||
public IEnumerator TestRelativeNetworkObjects()
|
||||
{
|
||||
var expected = m_NumberToSpawn * TotalClients;
|
||||
// Wait for all clients to have spawned all instances
|
||||
yield return WaitForConditionOrTimeOut(() => SpawnTest.TotalSpawned == expected);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all to " +
|
||||
$"spawn! Total Spawned: {SpawnTest.TotalSpawned}");
|
||||
|
||||
var client1Relative = s_GlobalNetworkObjects[1].Values.Where((c) =>
|
||||
c.gameObject.GetComponent<SpawnTest>() != null);
|
||||
foreach (var networkObject in client1Relative)
|
||||
{
|
||||
var testComp = networkObject.GetComponent<SpawnTest>();
|
||||
// Confirm each one is owned by the server
|
||||
Assert.IsTrue(testComp.IsOwnedByServer, $"{testComp.name} is not owned" +
|
||||
$" by the server!");
|
||||
}
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
[Order(2)]
|
||||
public IEnumerator TestDespawnNetworkObjects()
|
||||
{
|
||||
var serverRelative = s_GlobalNetworkObjects[0].Values.Where((c) =>
|
||||
c.gameObject.GetComponent<SpawnTest>() != null).ToList();
|
||||
foreach (var networkObject in serverRelative)
|
||||
{
|
||||
networkObject.Despawn();
|
||||
}
|
||||
// Wait for all clients to have spawned all instances
|
||||
yield return WaitForConditionOrTimeOut(() => SpawnTest.TotalSpawned == 0);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all to " +
|
||||
$"despawn! Total Spawned: {SpawnTest.TotalSpawned}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 218bb185a48c6f9449e1c74f4855a774
|
||||
guid: 5a64e8d7b2082a9409b53f83d0c4e537
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -5,16 +5,24 @@ using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NamedMessageTests : BaseMultiInstanceTest
|
||||
public class NamedMessageTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 2;
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
private NetworkManager FirstClient => m_ClientNetworkManagers[0];
|
||||
private NetworkManager SecondClient => m_ClientNetworkManagers[1];
|
||||
|
||||
protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode()
|
||||
{
|
||||
// Don't spin up and shutdown NetworkManager instances for each test
|
||||
// within this set of integration tests.
|
||||
return NetworkManagerInstatiationMode.AllTests;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NamedMessageIsReceivedOnClientWithContent()
|
||||
{
|
||||
|
||||
@@ -5,12 +5,13 @@ using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class UnnamedMessageTests : BaseMultiInstanceTest
|
||||
public class UnnamedMessageTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 2;
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
private NetworkManager FirstClient => m_ClientNetworkManagers[0];
|
||||
private NetworkManager SecondClient => m_ClientNetworkManagers[1];
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
private static readonly int k_NamedMessageOverhead = (int)k_MessageNameHashSize + k_MessageHeaderSize;
|
||||
private static readonly int k_UnnamedMessageOverhead = k_MessageHeaderSize;
|
||||
|
||||
protected override int NbClients => 2;
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNetworkMessageSentMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NetworkMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NetworkMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent);
|
||||
|
||||
var messageName = Guid.NewGuid();
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
@@ -38,17 +38,15 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
var networkMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound();
|
||||
Assert.AreEqual(1, networkMessageSentMetricValues.Count);
|
||||
|
||||
var networkMessageEvent = networkMessageSentMetricValues.First();
|
||||
Assert.AreEqual(nameof(NamedMessage), networkMessageEvent.Name);
|
||||
Assert.AreEqual(FirstClient.LocalClientId, networkMessageEvent.Connection.Id);
|
||||
// We should have 1 NamedMessage and some potential SnapshotMessage
|
||||
Assert.That(networkMessageSentMetricValues, Has.Exactly(1).Matches<NetworkMessageEvent>(x => x.Name == nameof(NamedMessage)));
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNetworkMessageSentMetricToMultipleClients()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NetworkMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NetworkMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent);
|
||||
var messageName = Guid.NewGuid();
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
@@ -74,7 +72,9 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
Debug.Log($"Received from {sender}");
|
||||
});
|
||||
var waitForMetricValues = new WaitForMetricValues<NetworkMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageReceived);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NetworkMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageReceived,
|
||||
metric => metric.Name == nameof(NamedMessage));
|
||||
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(messageName);
|
||||
@@ -85,16 +85,14 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
var networkMessageReceivedValues = waitForMetricValues.AssertMetricValuesHaveBeenFound();
|
||||
Assert.AreEqual(1, networkMessageReceivedValues.Count(x => x.Name.Equals(nameof(NamedMessage))));
|
||||
|
||||
var namedMessageReceived = networkMessageReceivedValues.First();
|
||||
Assert.AreEqual(Server.LocalClientId, namedMessageReceived.Connection.Id);
|
||||
// We should have 1 NamedMessage and some potential SnapshotMessage
|
||||
Assert.That(networkMessageReceivedValues, Has.Exactly(1).Matches<NetworkMessageEvent>(x => x.Name == nameof(NamedMessage)));
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNamedMessageSentMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
|
||||
|
||||
var messageName = Guid.NewGuid();
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
@@ -119,7 +117,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNamedMessageSentMetricToMultipleClients()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
|
||||
var messageName = Guid.NewGuid();
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
@@ -140,7 +138,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNamedMessageSentMetricToSelf()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent);
|
||||
var messageName = Guid.NewGuid();
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
@@ -157,7 +155,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNamedMessageReceivedMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NamedMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NamedMessageReceived);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NamedMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NamedMessageReceived);
|
||||
|
||||
var messageName = Guid.NewGuid();
|
||||
|
||||
@@ -198,7 +196,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
}
|
||||
|
||||
|
||||
var waitForMetricValues = new WaitForMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
|
||||
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
@@ -214,7 +212,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
public IEnumerator TrackUnnamedMessageSentMetricToMultipleClients()
|
||||
{
|
||||
var message = Guid.NewGuid();
|
||||
var waitForMetricValues = new WaitForMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(message);
|
||||
@@ -237,7 +235,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackUnnamedMessageSentMetricToSelf()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent);
|
||||
var messageName = Guid.NewGuid();
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
@@ -255,7 +253,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
public IEnumerator TrackUnnamedMessageReceivedMetric()
|
||||
{
|
||||
var message = Guid.NewGuid();
|
||||
var waitForMetricValues = new WaitForMetricValues<UnnamedMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageReceived);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<UnnamedMessageEvent>(FirstClientMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageReceived);
|
||||
using (var writer = new FastBufferWriter(1300, Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(message);
|
||||
|
||||
@@ -4,6 +4,8 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.NetStats;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
|
||||
@@ -1,52 +1,43 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
internal class NetworkObjectMetricsTests : SingleClientMetricTestBase
|
||||
{
|
||||
private const string k_NewNetworkObjectName = "TestNetworkObjectToSpawn";
|
||||
private NetworkObject m_NewNetworkPrefab;
|
||||
// Keep less than 23 chars to avoid issues if compared against a 32-byte fixed string
|
||||
// since it will have "(Clone)" appended
|
||||
private const string k_NewNetworkObjectName = "MetricObject";
|
||||
private GameObject m_NewNetworkPrefab;
|
||||
|
||||
protected override Action<GameObject> UpdatePlayerPrefab => _ =>
|
||||
/// <summary>
|
||||
/// Use OnServerAndClientsCreated to create any additional prefabs that you might need
|
||||
/// </summary>
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
var gameObject = new GameObject(k_NewNetworkObjectName);
|
||||
m_NewNetworkPrefab = gameObject.AddComponent<NetworkObject>();
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(m_NewNetworkPrefab);
|
||||
|
||||
var networkPrefab = new NetworkPrefab { Prefab = gameObject };
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(networkPrefab);
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
client.NetworkConfig.NetworkPrefabs.Add(networkPrefab);
|
||||
}
|
||||
};
|
||||
base.OnServerAndClientsCreated();
|
||||
m_NewNetworkPrefab = CreateNetworkObjectPrefab(k_NewNetworkObjectName);
|
||||
}
|
||||
|
||||
private NetworkObject SpawnNetworkObject()
|
||||
{
|
||||
// Spawn another network object so we can hide multiple.
|
||||
var gameObject = UnityEngine.Object.Instantiate(m_NewNetworkPrefab); // new GameObject(NewNetworkObjectName);
|
||||
var networkObject = gameObject.GetComponent<NetworkObject>();
|
||||
networkObject.NetworkManagerOwner = Server;
|
||||
networkObject.Spawn();
|
||||
|
||||
return networkObject;
|
||||
return SpawnObject(m_NewNetworkPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNetworkObjectSpawnSentMetric()
|
||||
{
|
||||
var waitForMetricEvent = new WaitForMetricValues<ObjectSpawnedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedSent);
|
||||
var waitForMetricEvent = new WaitForEventMetricValues<ObjectSpawnedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedSent);
|
||||
|
||||
SpawnNetworkObject();
|
||||
var spawnedObject = SpawnNetworkObject();
|
||||
|
||||
yield return waitForMetricEvent.WaitForMetricsReceived();
|
||||
|
||||
@@ -55,26 +46,27 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
|
||||
var objectSpawned = objectSpawnedSentMetricValues.Last();
|
||||
Assert.AreEqual(Client.LocalClientId, objectSpawned.Connection.Id);
|
||||
Assert.AreEqual($"{k_NewNetworkObjectName}(Clone)", objectSpawned.NetworkId.Name);
|
||||
Assert.AreEqual(spawnedObject.name, objectSpawned.NetworkId.Name);
|
||||
Assert.AreNotEqual(0, objectSpawned.BytesCount);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNetworkObjectSpawnReceivedMetric()
|
||||
{
|
||||
var waitForMetricEvent = new WaitForMetricValues<ObjectSpawnedEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedReceived);
|
||||
var waitForMetricEvent = new WaitForEventMetricValues<ObjectSpawnedEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedReceived);
|
||||
|
||||
var networkObject = SpawnNetworkObject();
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
yield return waitForMetricEvent.WaitForMetricsReceived();
|
||||
|
||||
var objectSpawnedReceivedMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound();
|
||||
Assert.AreEqual(1, objectSpawnedReceivedMetricValues.Count);
|
||||
|
||||
var clientSideObject = s_GlobalNetworkObjects[1][networkObject.NetworkObjectId];
|
||||
var objectSpawned = objectSpawnedReceivedMetricValues.First();
|
||||
Assert.AreEqual(Server.LocalClientId, objectSpawned.Connection.Id);
|
||||
Assert.AreEqual(networkObject.NetworkObjectId, objectSpawned.NetworkId.NetworkId);
|
||||
Assert.AreEqual($"{k_NewNetworkObjectName}(Clone)", objectSpawned.NetworkId.Name);
|
||||
Assert.AreEqual(clientSideObject.name, objectSpawned.NetworkId.Name);
|
||||
Assert.AreNotEqual(0, objectSpawned.BytesCount);
|
||||
}
|
||||
|
||||
@@ -83,20 +75,22 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
var networkObject = SpawnNetworkObject();
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
var waitForMetricEvent = new WaitForMetricValues<ObjectDestroyedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedSent);
|
||||
var waitForMetricEvent = new WaitForEventMetricValues<ObjectDestroyedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedSent);
|
||||
var objectName = networkObject.name;
|
||||
|
||||
Server.SpawnManager.OnDespawnObject(networkObject, true);
|
||||
|
||||
yield return s_DefaultWaitForTick;
|
||||
yield return waitForMetricEvent.WaitForMetricsReceived();
|
||||
|
||||
var objectDestroyedSentMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound();
|
||||
Assert.AreEqual(2, objectDestroyedSentMetricValues.Count); // As there's a client and server, this event is emitted twice.
|
||||
Assert.AreEqual(2, objectDestroyedSentMetricValues.Count);
|
||||
|
||||
var objectDestroyed = objectDestroyedSentMetricValues.Last();
|
||||
Assert.AreEqual(Client.LocalClientId, objectDestroyed.Connection.Id);
|
||||
Assert.AreEqual($"{k_NewNetworkObjectName}(Clone)", objectDestroyed.NetworkId.Name);
|
||||
Assert.AreEqual(objectName, objectDestroyed.NetworkId.Name);
|
||||
Assert.AreNotEqual(0, objectDestroyed.BytesCount);
|
||||
}
|
||||
|
||||
@@ -105,11 +99,14 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
var networkObject = SpawnNetworkObject();
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
var waitForMetricEvent = new WaitForMetricValues<ObjectDestroyedEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedReceived);
|
||||
var waitForMetricEvent = new WaitForEventMetricValues<ObjectDestroyedEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedReceived);
|
||||
var objectId = networkObject.NetworkObjectId;
|
||||
var objectName = s_GlobalNetworkObjects[1][objectId].name;
|
||||
|
||||
Server.SpawnManager.OnDespawnObject(networkObject, true);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
yield return waitForMetricEvent.WaitForMetricsReceived();
|
||||
|
||||
@@ -118,8 +115,8 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
|
||||
var objectDestroyed = objectDestroyedReceivedMetricValues.First();
|
||||
Assert.AreEqual(Server.LocalClientId, objectDestroyed.Connection.Id);
|
||||
Assert.AreEqual(networkObject.NetworkObjectId, objectDestroyed.NetworkId.NetworkId);
|
||||
Assert.AreEqual($"{k_NewNetworkObjectName}(Clone)", objectDestroyed.NetworkId.Name);
|
||||
Assert.AreEqual(objectId, objectDestroyed.NetworkId.NetworkId);
|
||||
Assert.AreEqual(objectName, objectDestroyed.NetworkId.Name);
|
||||
Assert.AreNotEqual(0, objectDestroyed.BytesCount);
|
||||
}
|
||||
|
||||
@@ -128,16 +125,16 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
var networkObject1 = SpawnNetworkObject();
|
||||
var networkObject2 = SpawnNetworkObject();
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
NetworkObject.NetworkHide(new List<NetworkObject> { networkObject1, networkObject2 }, Client.LocalClientId);
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
var waitForMetricEvent = new WaitForMetricValues<ObjectSpawnedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedSent);
|
||||
var waitForMetricEvent = new WaitForEventMetricValues<ObjectSpawnedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedSent);
|
||||
|
||||
NetworkObject.NetworkShow(new List<NetworkObject> { networkObject1, networkObject2 }, Client.LocalClientId);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
yield return waitForMetricEvent.WaitForMetricsReceived();
|
||||
|
||||
@@ -166,12 +163,12 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
var networkObject1 = SpawnNetworkObject();
|
||||
var networkObject2 = SpawnNetworkObject();
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
var waitForMetricEvent = new WaitForMetricValues<ObjectDestroyedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedSent);
|
||||
var waitForMetricEvent = new WaitForEventMetricValues<ObjectDestroyedEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedSent);
|
||||
|
||||
NetworkObject.NetworkHide(new List<NetworkObject> { networkObject1, networkObject2 }, Client.LocalClientId);
|
||||
|
||||
yield return s_DefaultWaitForTick;
|
||||
yield return waitForMetricEvent.WaitForMetricsReceived();
|
||||
|
||||
var objectDestroyedSentMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound();
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
internal class NetworkVariableMetricsTests : SingleClientMetricTestBase
|
||||
{
|
||||
protected override Action<GameObject> UpdatePlayerPrefab => prefab => prefab.AddComponent<NetworkVariableComponent>();
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<NetworkVariableComponent>();
|
||||
base.OnCreatePlayerPrefab();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNetworkVariableDeltaSentMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NetworkVariableEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkVariableDeltaSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NetworkVariableEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkVariableDeltaSent);
|
||||
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
@@ -32,7 +34,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackNetworkVariableDeltaReceivedMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForMetricValues<NetworkVariableEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkVariableDeltaReceived);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<NetworkVariableEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkVariableDeltaReceived);
|
||||
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@ using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
@@ -17,11 +18,11 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
// Header is dynamically sized due to packing, will be 2 bytes for all test messages.
|
||||
private const int k_MessageHeaderSize = 2;
|
||||
|
||||
protected override Action<GameObject> UpdatePlayerPrefab => _ =>
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
var gameObject = new GameObject(k_NewNetworkObjectName);
|
||||
m_NewNetworkPrefab = gameObject.AddComponent<NetworkObject>();
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(m_NewNetworkPrefab);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(m_NewNetworkPrefab);
|
||||
|
||||
var networkPrefab = new NetworkPrefab { Prefab = gameObject };
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(networkPrefab);
|
||||
@@ -29,7 +30,8 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
client.NetworkConfig.NetworkPrefabs.Add(networkPrefab);
|
||||
}
|
||||
};
|
||||
base.OnServerAndClientsCreated();
|
||||
}
|
||||
|
||||
private NetworkObject SpawnNetworkObject()
|
||||
{
|
||||
@@ -49,7 +51,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
|
||||
var waitForMetricValues = new WaitForMetricValues<OwnershipChangeEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.OwnershipChangeSent);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<OwnershipChangeEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.OwnershipChangeSent);
|
||||
|
||||
networkObject.ChangeOwnership(1);
|
||||
|
||||
@@ -70,7 +72,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
|
||||
var waitForMetricValues = new WaitForMetricValues<OwnershipChangeEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.OwnershipChangeReceived);
|
||||
var waitForMetricValues = new WaitForEventMetricValues<OwnershipChangeEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.OwnershipChangeReceived);
|
||||
|
||||
networkObject.ChangeOwnership(1);
|
||||
|
||||
|
||||
62
Tests/Runtime/Metrics/PacketMetricsTests.cs
Normal file
62
Tests/Runtime/Metrics/PacketMetricsTests.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_4
|
||||
using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
internal class PacketMetricsTests : SingleClientMetricTestBase
|
||||
{
|
||||
|
||||
protected override void OnOneTimeSetup()
|
||||
{
|
||||
#if UTP_ADAPTER
|
||||
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.UTP;
|
||||
#else
|
||||
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.SIP;
|
||||
#endif
|
||||
base.OnOneTimeSetup();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackPacketSentMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForCounterMetricValue(ServerMetrics.Dispatcher, NetworkMetricTypes.PacketsSent, metric => metric > 0);
|
||||
|
||||
using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(1337);
|
||||
Server.CustomMessagingManager.SendUnnamedMessageToAll(writer);
|
||||
}
|
||||
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
var totalPacketCount = waitForMetricValues.AssertMetricValueHaveBeenFound();
|
||||
Assert.That(totalPacketCount, Is.InRange(1, 4));
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackPacketReceivedMetric()
|
||||
{
|
||||
var waitForMetricValues = new WaitForCounterMetricValue(ClientMetrics.Dispatcher, NetworkMetricTypes.PacketsReceived, metric => metric > 0);
|
||||
|
||||
using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(1337);
|
||||
Server.CustomMessagingManager.SendUnnamedMessageToAll(writer);
|
||||
}
|
||||
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
var totalPacketCount = waitForMetricValues.AssertMetricValueHaveBeenFound();
|
||||
Assert.That(totalPacketCount, Is.InRange(1, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
3
Tests/Runtime/Metrics/PacketMetricsTests.cs.meta
Normal file
3
Tests/Runtime/Metrics/PacketMetricsTests.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84a4884f4ea744a9944284d56b29531b
|
||||
timeCreated: 1644269306
|
||||
@@ -1,28 +1,27 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
internal class RpcMetricsTests : SingleClientMetricTestBase
|
||||
{
|
||||
protected override Action<GameObject> UpdatePlayerPrefab => prefab => prefab.AddComponent<RpcTestComponent>();
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<RpcTestComponent>();
|
||||
base.OnCreatePlayerPrefab();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackRpcSentMetricOnServer()
|
||||
{
|
||||
var clientPlayer = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == Client.LocalClientId, Server, clientPlayer));
|
||||
var waitForMetricValues = new WaitForEventMetricValues<RpcEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent);
|
||||
|
||||
var waitForMetricValues = new WaitForMetricValues<RpcEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent);
|
||||
|
||||
clientPlayer.Result.GetComponent<RpcTestComponent>().MyClientRpc();
|
||||
m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][Client.LocalClientId].GetComponent<RpcTestComponent>().MyClientRpc();
|
||||
|
||||
yield return waitForMetricValues.WaitForMetricsReceived();
|
||||
|
||||
@@ -39,12 +38,9 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackRpcSentMetricOnClient()
|
||||
{
|
||||
var clientPlayer = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == Client.LocalClientId, Client, clientPlayer));
|
||||
var waitForClientMetricsValues = new WaitForEventMetricValues<RpcEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.RpcSent);
|
||||
|
||||
var waitForClientMetricsValues = new WaitForMetricValues<RpcEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.RpcSent);
|
||||
|
||||
clientPlayer.Result.GetComponent<RpcTestComponent>().MyServerRpc();
|
||||
m_PlayerNetworkObjects[Client.LocalClientId][Client.LocalClientId].GetComponent<RpcTestComponent>().MyServerRpc();
|
||||
|
||||
yield return waitForClientMetricsValues.WaitForMetricsReceived();
|
||||
|
||||
@@ -61,12 +57,8 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackRpcReceivedMetricOnServer()
|
||||
{
|
||||
var clientPlayer = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == Client.LocalClientId, Client, clientPlayer));
|
||||
|
||||
var waitForServerMetricsValues = new WaitForMetricValues<RpcEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcReceived);
|
||||
|
||||
clientPlayer.Result.GetComponent<RpcTestComponent>().MyServerRpc();
|
||||
var waitForServerMetricsValues = new WaitForEventMetricValues<RpcEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcReceived);
|
||||
m_PlayerNetworkObjects[Client.LocalClientId][Client.LocalClientId].GetComponent<RpcTestComponent>().MyServerRpc();
|
||||
|
||||
yield return waitForServerMetricsValues.WaitForMetricsReceived();
|
||||
|
||||
@@ -83,16 +75,13 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackRpcReceivedMetricOnClient()
|
||||
{
|
||||
var clientPlayer = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == Client.LocalClientId, Server, clientPlayer));
|
||||
var waitForClientMetricsValues = new WaitForEventMetricValues<RpcEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.RpcReceived);
|
||||
|
||||
var waitForServerMetricsValues = new WaitForMetricValues<RpcEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcReceived);
|
||||
m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][Client.LocalClientId].GetComponent<RpcTestComponent>().MyClientRpc();
|
||||
|
||||
clientPlayer.Result.GetComponent<RpcTestComponent>().MyClientRpc();
|
||||
yield return waitForClientMetricsValues.WaitForMetricsReceived();
|
||||
|
||||
yield return waitForServerMetricsValues.WaitForMetricsReceived();
|
||||
|
||||
var clientRpcReceivedValues = waitForServerMetricsValues.AssertMetricValuesHaveBeenFound();
|
||||
var clientRpcReceivedValues = waitForClientMetricsValues.AssertMetricValuesHaveBeenFound();
|
||||
Assert.AreEqual(1, clientRpcReceivedValues.Count);
|
||||
|
||||
var rpcReceived = clientRpcReceivedValues.First();
|
||||
|
||||
101
Tests/Runtime/Metrics/RttMetricsTests.cs
Normal file
101
Tests/Runtime/Metrics/RttMetricsTests.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_4
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
/// <summary>
|
||||
/// Note: This is one way to easily identify each specific test.
|
||||
/// Since the test only tested 1 and then 2 clients, I made this
|
||||
/// and enum, but you can always remove the enum in the constructor,
|
||||
/// replace it with an int, and then test from 1 to 9 clients.
|
||||
/// Just an example of how you can accomplish the same task using
|
||||
/// the NetcodeIntegrationTest
|
||||
/// </summary>
|
||||
[TestFixture(ClientCount.OneClient)]
|
||||
[TestFixture(ClientCount.TwoClients)]
|
||||
internal class RttMetricsTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => m_ClientCount;
|
||||
|
||||
public enum ClientCount
|
||||
{
|
||||
OneClient,
|
||||
TwoClients
|
||||
}
|
||||
|
||||
private int m_ClientCount;
|
||||
|
||||
public RttMetricsTests(ClientCount numberOfClients)
|
||||
{
|
||||
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()
|
||||
{
|
||||
#if UTP_ADAPTER
|
||||
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.UTP;
|
||||
#else
|
||||
m_NetworkTransport = NetcodeIntegrationTestHelpers.InstanceTransport.SIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackRttMetricServerToClient()
|
||||
{
|
||||
var waitForMetricValues = new WaitForGaugeMetricValues((m_ServerNetworkManager.NetworkMetrics as NetworkMetrics).Dispatcher, NetworkMetricTypes.RttToServer);
|
||||
|
||||
using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(1337);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer);
|
||||
}
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => waitForMetricValues.MetricFound());
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"{nameof(TrackRttMetricServerToClient)} timed out waiting for metric to be found for {m_ClientCount} clients!");
|
||||
|
||||
var rttValue = waitForMetricValues.AssertMetricValueHaveBeenFound();
|
||||
Assert.AreEqual(0f, rttValue);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackRttMetricClientToServer()
|
||||
{
|
||||
var clientGaugeMetricValues = new List<WaitForGaugeMetricValues>();
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
clientGaugeMetricValues.Add(new WaitForGaugeMetricValues((client.NetworkMetrics as NetworkMetrics).Dispatcher, NetworkMetricTypes.RttToServer, metric => metric > 0f));
|
||||
}
|
||||
|
||||
using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp))
|
||||
{
|
||||
writer.WriteValueSafe(1337);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer);
|
||||
}
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => clientGaugeMetricValues.Where((c) => c.MetricFound()).Count() == NumberOfClients);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"{nameof(TrackRttMetricClientToServer)} timed out waiting for metric to be found for {m_ClientCount} clients!");
|
||||
|
||||
foreach (var clientGaugeMetricValue in clientGaugeMetricValues)
|
||||
{
|
||||
var rttValue = clientGaugeMetricValue.AssertMetricValueHaveBeenFound();
|
||||
Assert.That(rttValue, Is.GreaterThanOrEqualTo(1f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
3
Tests/Runtime/Metrics/RttMetricsTests.cs.meta
Normal file
3
Tests/Runtime/Metrics/RttMetricsTests.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 452fbcb436d24291ba7db3a68e3e50ac
|
||||
timeCreated: 1644269321
|
||||
@@ -4,8 +4,8 @@ using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
@@ -19,10 +19,13 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackServerLogSentMetric()
|
||||
{
|
||||
var waitForSentMetric = new WaitForMetricValues<ServerLogEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.ServerLogSent);
|
||||
var waitForSentMetric = new WaitForEventMetricValues<ServerLogEvent>(ClientMetrics.Dispatcher, NetworkMetricTypes.ServerLogSent);
|
||||
|
||||
var message = Guid.NewGuid().ToString();
|
||||
Client.LogLevel = LogLevel.Developer;
|
||||
Server.LogLevel = LogLevel.Developer;
|
||||
NetworkLog.LogWarningServer(message);
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
yield return waitForSentMetric.WaitForMetricsReceived();
|
||||
|
||||
@@ -38,11 +41,15 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
[UnityTest]
|
||||
public IEnumerator TrackServerLogReceivedMetric()
|
||||
{
|
||||
var waitForReceivedMetric = new WaitForMetricValues<ServerLogEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ServerLogReceived);
|
||||
var waitForReceivedMetric = new WaitForEventMetricValues<ServerLogEvent>(ServerMetrics.Dispatcher, NetworkMetricTypes.ServerLogReceived);
|
||||
|
||||
var message = Guid.NewGuid().ToString();
|
||||
Client.LogLevel = LogLevel.Developer;
|
||||
Server.LogLevel = LogLevel.Developer;
|
||||
NetworkLog.LogWarningServer(message);
|
||||
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
yield return waitForReceivedMetric.WaitForMetricsReceived();
|
||||
|
||||
var receivedMetrics = waitForReceivedMetric.AssertMetricValuesHaveBeenFound();
|
||||
|
||||
@@ -6,7 +6,7 @@ using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Multiplayer.Tools.NetStats;
|
||||
using Unity.Netcode.RuntimeTests.Metrics.Utility;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
@@ -26,7 +26,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
try
|
||||
{
|
||||
writer.WriteValueSafe(messageName);
|
||||
|
||||
|
||||
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), Client.LocalClientId, writer);
|
||||
}
|
||||
finally
|
||||
@@ -54,7 +54,7 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
try
|
||||
{
|
||||
writer.WriteValueSafe(messageName);
|
||||
|
||||
|
||||
Server.CustomMessagingManager.SendNamedMessage(messageName.ToString(), Client.LocalClientId, writer);
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics.Utility
|
||||
{
|
||||
internal abstract class SingleClientMetricTestBase : BaseMultiInstanceTest
|
||||
{
|
||||
protected override int NbClients => 1;
|
||||
|
||||
protected virtual Action<GameObject> UpdatePlayerPrefab => _ => { };
|
||||
|
||||
internal NetworkManager Server { get; private set; }
|
||||
|
||||
internal NetworkMetrics ServerMetrics { get; private set; }
|
||||
|
||||
internal NetworkManager Client { get; private set; }
|
||||
|
||||
internal NetworkMetrics ClientMetrics { get; private set; }
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, UpdatePlayerPrefab);
|
||||
|
||||
Server = m_ServerNetworkManager;
|
||||
ServerMetrics = Server.NetworkMetrics as NetworkMetrics;
|
||||
Client = m_ClientNetworkManagers[0];
|
||||
ClientMetrics = Client.NetworkMetrics as NetworkMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DualClientMetricTestBase : BaseMultiInstanceTest
|
||||
{
|
||||
protected override int NbClients => 2;
|
||||
|
||||
protected virtual Action<GameObject> UpdatePlayerPrefab => _ => { };
|
||||
|
||||
internal NetworkManager Server { get; private set; }
|
||||
|
||||
internal NetworkMetrics ServerMetrics { get; private set; }
|
||||
|
||||
internal NetworkManager FirstClient { get; private set; }
|
||||
|
||||
internal NetworkMetrics FirstClientMetrics { get; private set; }
|
||||
|
||||
internal NetworkManager SecondClient { get; private set; }
|
||||
|
||||
internal NetworkMetrics SecondClientMetrics { get; private set; }
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, UpdatePlayerPrefab);
|
||||
|
||||
Server = m_ServerNetworkManager;
|
||||
ServerMetrics = Server.NetworkMetrics as NetworkMetrics;
|
||||
FirstClient = m_ClientNetworkManagers[0];
|
||||
FirstClientMetrics = FirstClient.NetworkMetrics as NetworkMetrics;
|
||||
SecondClient = m_ClientNetworkManagers[0];
|
||||
SecondClientMetrics = SecondClient.NetworkMetrics as NetworkMetrics;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics.Utility
|
||||
{
|
||||
public class NetworkVariableComponent : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<int> MyNetworkVariable { get; } = new NetworkVariable<int>();
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
MyNetworkVariable.Value = Random.Range(100, 999);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics.Utility
|
||||
{
|
||||
public class RpcTestComponent : NetworkBehaviour
|
||||
{
|
||||
public event Action OnServerRpcAction;
|
||||
public event Action OnClientRpcAction;
|
||||
|
||||
[ServerRpc]
|
||||
public void MyServerRpc()
|
||||
{
|
||||
OnServerRpcAction?.Invoke();
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void MyClientRpc()
|
||||
{
|
||||
OnClientRpcAction?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdfa28da9866545428083671c445a9ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,118 +0,0 @@
|
||||
#if MULTIPLAYER_TOOLS
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Multiplayer.Tools.NetStats;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Metrics.Utility
|
||||
{
|
||||
internal class WaitForMetricValues<TMetric> : IMetricObserver
|
||||
{
|
||||
readonly string m_MetricName;
|
||||
bool m_Found;
|
||||
bool m_HasError;
|
||||
string m_Error;
|
||||
uint m_NbFrames = 0;
|
||||
IReadOnlyCollection<TMetric> m_Values;
|
||||
|
||||
public delegate bool Filter(TMetric metric);
|
||||
|
||||
Filter m_FilterDelegate;
|
||||
|
||||
|
||||
public WaitForMetricValues(IMetricDispatcher dispatcher, DirectionalMetricInfo directionalMetricName)
|
||||
{
|
||||
m_MetricName = directionalMetricName.Id;
|
||||
|
||||
dispatcher.RegisterObserver(this);
|
||||
}
|
||||
|
||||
public WaitForMetricValues(IMetricDispatcher dispatcher, DirectionalMetricInfo directionalMetricName, Filter filter)
|
||||
: this(dispatcher, directionalMetricName)
|
||||
{
|
||||
m_FilterDelegate = filter;
|
||||
}
|
||||
|
||||
public IEnumerator WaitForMetricsReceived()
|
||||
{
|
||||
yield return WaitForFrames(60);
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<TMetric> AssertMetricValuesHaveBeenFound()
|
||||
{
|
||||
if (m_HasError)
|
||||
{
|
||||
Assert.Fail(m_Error);
|
||||
}
|
||||
|
||||
if (!m_Found)
|
||||
{
|
||||
Assert.Fail($"Found no matching values for metric of type '{typeof(TMetric).Name}', with name '{m_MetricName}' during '{m_NbFrames}' frames.");
|
||||
}
|
||||
|
||||
return m_Values;
|
||||
}
|
||||
|
||||
public void AssertMetricValuesHaveNotBeenFound()
|
||||
{
|
||||
if (m_HasError)
|
||||
{
|
||||
Assert.Fail(m_Error);
|
||||
}
|
||||
|
||||
if (!m_Found)
|
||||
{
|
||||
Assert.Pass();
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
public void Observe(MetricCollection collection)
|
||||
{
|
||||
if (m_Found || m_HasError)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var metric = collection.Metrics.SingleOrDefault(x => x.Name == m_MetricName);
|
||||
if (metric == default)
|
||||
{
|
||||
m_HasError = true;
|
||||
m_Error = $"Metric collection does not contain metric named '{m_MetricName}'.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var typedMetric = metric as IEventMetric<TMetric>;
|
||||
if (typedMetric == default)
|
||||
{
|
||||
m_HasError = true;
|
||||
m_Error = $"Metric collection contains a metric of type '{metric.GetType().Name}' for name '{m_MetricName}', but was expecting '{typeof(TMetric).Name}'.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (typedMetric.Values.Any())
|
||||
{
|
||||
// Apply filter if one was provided
|
||||
m_Values = m_FilterDelegate != null ? typedMetric.Values.Where(x => m_FilterDelegate(x)).ToList() : typedMetric.Values.ToList();
|
||||
m_Found = m_Values.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForFrames(uint maxNbFrames)
|
||||
{
|
||||
while (!m_Found && m_NbFrames < maxNbFrames)
|
||||
{
|
||||
m_NbFrames++;
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 176888f06e2c5e14db33783fd0299668
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,505 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helpers for running multi instance tests.
|
||||
/// </summary>
|
||||
public static class MultiInstanceHelpers
|
||||
{
|
||||
public const int DefaultMinFrames = 1;
|
||||
public const int DefaultMaxFrames = 64;
|
||||
private static List<NetworkManager> s_NetworkManagerInstances = new List<NetworkManager>();
|
||||
private static bool s_IsStarted;
|
||||
private static int s_ClientCount;
|
||||
private static int s_OriginalTargetFrameRate = -1;
|
||||
|
||||
public static List<NetworkManager> NetworkManagerInstances => s_NetworkManagerInstances;
|
||||
|
||||
/// <summary>
|
||||
/// Creates NetworkingManagers and configures them for use in a multi instance setting.
|
||||
/// </summary>
|
||||
/// <param name="clientCount">The amount of clients</param>
|
||||
/// <param name="server">The server NetworkManager</param>
|
||||
/// <param name="clients">The clients NetworkManagers</param>
|
||||
/// <param name="targetFrameRate">The targetFrameRate of the Unity engine to use while the multi instance helper is running. Will be reset on shutdown.</param>
|
||||
public static bool Create(int clientCount, out NetworkManager server, out NetworkManager[] clients, int targetFrameRate = 60)
|
||||
{
|
||||
s_NetworkManagerInstances = new List<NetworkManager>();
|
||||
CreateNewClients(clientCount, out clients);
|
||||
|
||||
// Create gameObject
|
||||
var go = new GameObject("NetworkManager - Server");
|
||||
|
||||
// Create networkManager component
|
||||
server = go.AddComponent<NetworkManager>();
|
||||
NetworkManagerInstances.Insert(0, server);
|
||||
|
||||
// Set the NetworkConfig
|
||||
server.NetworkConfig = new NetworkConfig()
|
||||
{
|
||||
// Set transport
|
||||
NetworkTransport = go.AddComponent<SIPTransport>()
|
||||
};
|
||||
|
||||
s_OriginalTargetFrameRate = Application.targetFrameRate;
|
||||
Application.targetFrameRate = targetFrameRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to add a client to the already existing list of clients
|
||||
/// </summary>
|
||||
/// <param name="clientCount">The amount of clients</param>
|
||||
/// <param name="clients"></param>
|
||||
/// <returns></returns>
|
||||
public static bool CreateNewClients(int clientCount, out NetworkManager[] clients)
|
||||
{
|
||||
clients = new NetworkManager[clientCount];
|
||||
var activeSceneName = SceneManager.GetActiveScene().name;
|
||||
for (int i = 0; i < clientCount; i++)
|
||||
{
|
||||
// Create gameObject
|
||||
var go = new GameObject("NetworkManager - Client - " + i);
|
||||
// Create networkManager component
|
||||
clients[i] = go.AddComponent<NetworkManager>();
|
||||
|
||||
// Set the NetworkConfig
|
||||
clients[i].NetworkConfig = new NetworkConfig()
|
||||
{
|
||||
// Set transport
|
||||
NetworkTransport = go.AddComponent<SIPTransport>()
|
||||
};
|
||||
}
|
||||
|
||||
NetworkManagerInstances.AddRange(clients);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops one single client and makes sure to cleanup any static variables in this helper
|
||||
/// </summary>
|
||||
/// <param name="clientToStop"></param>
|
||||
public static void StopOneClient(NetworkManager clientToStop)
|
||||
{
|
||||
clientToStop.Shutdown();
|
||||
Object.Destroy(clientToStop.gameObject);
|
||||
NetworkManagerInstances.Remove(clientToStop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should always be invoked when finished with a single unit test
|
||||
/// (i.e. during TearDown)
|
||||
/// </summary>
|
||||
public static void Destroy()
|
||||
{
|
||||
if (s_IsStarted == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_IsStarted = false;
|
||||
|
||||
// Shutdown the server which forces clients to disconnect
|
||||
foreach (var networkManager in NetworkManagerInstances)
|
||||
{
|
||||
networkManager.Shutdown();
|
||||
}
|
||||
|
||||
// Destroy the network manager instances
|
||||
foreach (var networkManager in NetworkManagerInstances)
|
||||
{
|
||||
Object.DestroyImmediate(networkManager.gameObject);
|
||||
}
|
||||
|
||||
NetworkManagerInstances.Clear();
|
||||
|
||||
// Destroy the temporary GameObject used to run co-routines
|
||||
if (s_CoroutineRunner != null)
|
||||
{
|
||||
s_CoroutineRunner.StopAllCoroutines();
|
||||
Object.DestroyImmediate(s_CoroutineRunner);
|
||||
}
|
||||
|
||||
Application.targetFrameRate = s_OriginalTargetFrameRate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts NetworkManager instances created by the Create method.
|
||||
/// </summary>
|
||||
/// <param name="host">Whether or not to create a Host instead of Server</param>
|
||||
/// <param name="server">The Server NetworkManager</param>
|
||||
/// <param name="clients">The Clients NetworkManager</param>
|
||||
/// <param name="startInitializationCallback">called immediately after server and client(s) are started</param>
|
||||
/// <returns></returns>
|
||||
public static bool Start(bool host, NetworkManager server, NetworkManager[] clients, Action<NetworkManager> startInitializationCallback = null)
|
||||
{
|
||||
if (s_IsStarted)
|
||||
{
|
||||
throw new InvalidOperationException("MultiInstanceHelper already started. Did you forget to Destroy?");
|
||||
}
|
||||
|
||||
s_IsStarted = true;
|
||||
s_ClientCount = clients.Length;
|
||||
|
||||
if (host)
|
||||
{
|
||||
server.StartHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
server.StartServer();
|
||||
}
|
||||
|
||||
// if set, then invoke this for the server
|
||||
startInitializationCallback?.Invoke(server);
|
||||
|
||||
for (int i = 0; i < clients.Length; i++)
|
||||
{
|
||||
clients[i].StartClient();
|
||||
|
||||
// if set, then invoke this for the client
|
||||
startInitializationCallback?.Invoke(clients[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Empty MonoBehaviour that is a holder of coroutine
|
||||
private class CoroutineRunner : MonoBehaviour
|
||||
{
|
||||
}
|
||||
|
||||
private static CoroutineRunner s_CoroutineRunner;
|
||||
|
||||
/// <summary>
|
||||
/// Runs a IEnumerator as a Coroutine on a dummy GameObject. Used to get exceptions coming from the coroutine
|
||||
/// </summary>
|
||||
/// <param name="enumerator">The IEnumerator to run</param>
|
||||
public static Coroutine Run(IEnumerator enumerator)
|
||||
{
|
||||
if (s_CoroutineRunner == null)
|
||||
{
|
||||
s_CoroutineRunner = new GameObject(nameof(CoroutineRunner)).AddComponent<CoroutineRunner>();
|
||||
}
|
||||
|
||||
return s_CoroutineRunner.StartCoroutine(enumerator);
|
||||
}
|
||||
|
||||
public class CoroutineResultWrapper<T>
|
||||
{
|
||||
public T Result;
|
||||
}
|
||||
|
||||
private static uint s_AutoIncrementGlobalObjectIdHashCounter = 111111;
|
||||
|
||||
/// <summary>
|
||||
/// Normally we would only allow player prefabs to be set to a prefab. Not runtime created objects.
|
||||
/// In order to prevent having a Resource folder full of a TON of prefabs that we have to maintain,
|
||||
/// MultiInstanceHelper has a helper function that lets you mark a runtime created object to be
|
||||
/// treated as a prefab by the Netcode. That's how we can get away with creating the player prefab
|
||||
/// at runtime without it being treated as a SceneObject or causing other conflicts with the Netcode.
|
||||
/// </summary>
|
||||
/// <param name="networkObject">The networkObject to be treated as Prefab</param>
|
||||
/// <param name="globalObjectIdHash">The GlobalObjectId to force</param>
|
||||
public static void MakeNetworkObjectTestPrefab(NetworkObject networkObject, uint globalObjectIdHash = default)
|
||||
{
|
||||
// Override `GlobalObjectIdHash` if `globalObjectIdHash` param is set
|
||||
if (globalObjectIdHash != default)
|
||||
{
|
||||
networkObject.GlobalObjectIdHash = globalObjectIdHash;
|
||||
}
|
||||
|
||||
// Fallback to auto-increment if `GlobalObjectIdHash` was never set
|
||||
if (networkObject.GlobalObjectIdHash == default)
|
||||
{
|
||||
networkObject.GlobalObjectIdHash = ++s_AutoIncrementGlobalObjectIdHashCounter;
|
||||
}
|
||||
|
||||
// Prevent object from being snapped up as a scene object
|
||||
networkObject.IsSceneObject = false;
|
||||
}
|
||||
|
||||
// We use GameObject instead of SceneObject to be able to keep hierarchy
|
||||
public static void MarkAsSceneObjectRoot(GameObject networkObjectRoot, NetworkManager server, NetworkManager[] clients)
|
||||
{
|
||||
networkObjectRoot.name += " - Server";
|
||||
|
||||
NetworkObject[] serverNetworkObjects = networkObjectRoot.GetComponentsInChildren<NetworkObject>();
|
||||
|
||||
for (int i = 0; i < serverNetworkObjects.Length; i++)
|
||||
{
|
||||
serverNetworkObjects[i].NetworkManagerOwner = server;
|
||||
}
|
||||
|
||||
for (int i = 0; i < clients.Length; i++)
|
||||
{
|
||||
GameObject root = Object.Instantiate(networkObjectRoot);
|
||||
root.name += " - Client - " + i;
|
||||
|
||||
NetworkObject[] clientNetworkObjects = root.GetComponentsInChildren<NetworkObject>();
|
||||
|
||||
for (int j = 0; j < clientNetworkObjects.Length; j++)
|
||||
{
|
||||
clientNetworkObjects[j].NetworkManagerOwner = clients[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits on the client side to be connected.
|
||||
/// </summary>
|
||||
/// <param name="client">The client</param>
|
||||
/// <param name="result">The result. If null, it will automatically assert</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator WaitForClientConnected(NetworkManager client, CoroutineResultWrapper<bool> result = null, int maxFrames = DefaultMaxFrames)
|
||||
{
|
||||
yield return WaitForClientsConnected(new NetworkManager[] { client }, result, maxFrames);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Similar to WaitForClientConnected, this waits for multiple clients to be connected.
|
||||
/// </summary>
|
||||
/// <param name="clients">The clients to be connected</param>
|
||||
/// <param name="result">The result. If null, it will automatically assert<</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerator WaitForClientsConnected(NetworkManager[] clients, CoroutineResultWrapper<bool> result = null, int maxFrames = DefaultMaxFrames)
|
||||
{
|
||||
// Make sure none are the host client
|
||||
foreach (var client in clients)
|
||||
{
|
||||
if (client.IsServer)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot wait for connected as server");
|
||||
}
|
||||
}
|
||||
|
||||
var startFrameNumber = Time.frameCount;
|
||||
var allConnected = true;
|
||||
while (Time.frameCount - startFrameNumber <= maxFrames)
|
||||
{
|
||||
allConnected = true;
|
||||
foreach (var client in clients)
|
||||
{
|
||||
if (!client.IsConnectedClient)
|
||||
{
|
||||
allConnected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allConnected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
var nextFrameNumber = Time.frameCount + 1;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
result.Result = allConnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < clients.Length; ++i)
|
||||
{
|
||||
var client = clients[i];
|
||||
// Logging i+1 because that's the local client ID they'll get (0 is server)
|
||||
// Can't use client.LocalClientId because that doesn't get assigned until IsConnectedClient == true,
|
||||
Assert.True(client.IsConnectedClient, $"Client {i + 1} never connected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits on the server side for 1 client to be connected
|
||||
/// </summary>
|
||||
/// <param name="server">The server</param>
|
||||
/// <param name="result">The result. If null, it will automatically assert</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator WaitForClientConnectedToServer(NetworkManager server, CoroutineResultWrapper<bool> result = null, int maxFrames = DefaultMaxFrames)
|
||||
{
|
||||
yield return WaitForClientsConnectedToServer(server, server.IsHost ? s_ClientCount + 1 : s_ClientCount, result, maxFrames);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits on the server side for 1 client to be connected
|
||||
/// </summary>
|
||||
/// <param name="server">The server</param>
|
||||
/// <param name="result">The result. If null, it will automatically assert</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator WaitForClientsConnectedToServer(NetworkManager server, int clientCount = 1, CoroutineResultWrapper<bool> result = null, int maxFrames = DefaultMaxFrames)
|
||||
{
|
||||
if (!server.IsServer)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot wait for connected as client");
|
||||
}
|
||||
|
||||
var startFrameNumber = Time.frameCount;
|
||||
|
||||
while (Time.frameCount - startFrameNumber <= maxFrames && server.ConnectedClients.Count != clientCount)
|
||||
{
|
||||
var nextFrameNumber = Time.frameCount + 1;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
}
|
||||
|
||||
var res = server.ConnectedClients.Count == clientCount;
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
result.Result = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(res, "A client never connected to server");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a NetworkObject instance as it's represented by a certain peer.
|
||||
/// </summary>
|
||||
/// <param name="networkObjectId">The networkObjectId to get</param>
|
||||
/// <param name="representation">The representation to get the object from</param>
|
||||
/// <param name="result">The result</param>
|
||||
/// <param name="failIfNull">Whether or not to fail if no object is found and result is null</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator GetNetworkObjectByRepresentation(ulong networkObjectId, NetworkManager representation, CoroutineResultWrapper<NetworkObject> result, bool failIfNull = true, int maxFrames = DefaultMaxFrames)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException("Result cannot be null");
|
||||
}
|
||||
|
||||
var startFrameNumber = Time.frameCount;
|
||||
|
||||
while (Time.frameCount - startFrameNumber <= maxFrames && representation.SpawnManager.SpawnedObjects.All(x => x.Value.NetworkObjectId != networkObjectId))
|
||||
{
|
||||
var nextFrameNumber = Time.frameCount + 1;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
}
|
||||
|
||||
result.Result = representation.SpawnManager.SpawnedObjects.First(x => x.Value.NetworkObjectId == networkObjectId).Value;
|
||||
|
||||
if (failIfNull && result.Result == null)
|
||||
{
|
||||
Assert.Fail("NetworkObject could not be found");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a NetworkObject instance as it's represented by a certain peer.
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate used to filter for your target NetworkObject</param>
|
||||
/// <param name="representation">The representation to get the object from</param>
|
||||
/// <param name="result">The result</param>
|
||||
/// <param name="failIfNull">Whether or not to fail if no object is found and result is null</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator GetNetworkObjectByRepresentation(Func<NetworkObject, bool> predicate, NetworkManager representation, CoroutineResultWrapper<NetworkObject> result, bool failIfNull = true, int maxFrames = DefaultMaxFrames)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException("Result cannot be null");
|
||||
}
|
||||
|
||||
if (predicate == null)
|
||||
{
|
||||
throw new ArgumentNullException("Predicate cannot be null");
|
||||
}
|
||||
|
||||
var startFrame = Time.frameCount;
|
||||
|
||||
while (Time.frameCount - startFrame <= maxFrames && !representation.SpawnManager.SpawnedObjects.Any(x => predicate(x.Value)))
|
||||
{
|
||||
var nextFrameNumber = Time.frameCount + 1;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
}
|
||||
|
||||
result.Result = representation.SpawnManager.SpawnedObjects.FirstOrDefault(x => predicate(x.Value)).Value;
|
||||
|
||||
if (failIfNull && result.Result == null)
|
||||
{
|
||||
Assert.Fail("NetworkObject could not be found");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs some code, then verifies the condition (combines 'Run' and 'WaitForCondition')
|
||||
/// </summary>
|
||||
/// <param name="workload">Action / code to run</param>
|
||||
/// <param name="predicate">The predicate to wait for</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator RunAndWaitForCondition(Action workload, Func<bool> predicate, int maxFrames = DefaultMaxFrames, int minFrames = DefaultMinFrames)
|
||||
{
|
||||
var waitResult = new CoroutineResultWrapper<bool>();
|
||||
workload();
|
||||
|
||||
yield return Run(WaitForCondition(
|
||||
predicate,
|
||||
waitResult,
|
||||
maxFrames: maxFrames,
|
||||
minFrames: minFrames));
|
||||
|
||||
if (!waitResult.Result)
|
||||
{
|
||||
Assert.Fail("Predicate condition failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a predicate condition to be met
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate to wait for</param>
|
||||
/// <param name="result">The result. If null, it will fail if the predicate is not met</param>
|
||||
/// <param name="minFrames">The min frames to wait for</param>
|
||||
/// <param name="maxFrames">The max frames to wait for</param>
|
||||
public static IEnumerator WaitForCondition(Func<bool> predicate, CoroutineResultWrapper<bool> result = null, int maxFrames = DefaultMaxFrames, int minFrames = DefaultMinFrames)
|
||||
{
|
||||
if (predicate == null)
|
||||
{
|
||||
throw new ArgumentNullException("Predicate cannot be null");
|
||||
}
|
||||
|
||||
var startFrameNumber = Time.frameCount;
|
||||
|
||||
if (minFrames > 0)
|
||||
{
|
||||
yield return new WaitUntil(() =>
|
||||
{
|
||||
return Time.frameCount >= minFrames;
|
||||
});
|
||||
}
|
||||
|
||||
while (Time.frameCount - startFrameNumber <= maxFrames &&
|
||||
!predicate())
|
||||
{
|
||||
// Changed to 2 frames to avoid the scenario where it would take 1+ frames to
|
||||
// see a value change (i.e. discovered in the NetworkTransformTests)
|
||||
var nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() =>
|
||||
{
|
||||
return Time.frameCount >= nextFrameNumber;
|
||||
});
|
||||
}
|
||||
|
||||
var res = predicate();
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
result.Result = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(res, "PREDICATE CONDITION");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1c62160e3e5b4489b2143fc21b56e55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,37 +1,38 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode;
|
||||
using Unity.Netcode.RuntimeTests;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace TestProject.RuntimeTests
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NestedNetworkManagerTests
|
||||
{
|
||||
[UnityTest]
|
||||
public IEnumerator CheckNestedNetworkManager()
|
||||
[Test]
|
||||
public void 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<SIPTransport>();
|
||||
var networkManager = networkManagerObject.AddComponent<NetworkManager>();
|
||||
networkManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport };
|
||||
// Trap for the nested NetworkManager exception
|
||||
LogAssert.Expect(LogType.Error, messageToCheck);
|
||||
|
||||
yield return new WaitForSeconds(0.02f);
|
||||
// Make our NetworkManager's GameObject nested
|
||||
networkManagerObject.transform.parent = parent.transform;
|
||||
|
||||
// Generate the error message we are expecting to see
|
||||
var messageToCheck = NetworkManager.GenerateNestedNetworkManagerMessage(networkManagerObject.transform);
|
||||
|
||||
// Trap for the nested NetworkManager exception
|
||||
#if UNITY_EDITOR
|
||||
LogAssert.Expect(LogType.Error, messageToCheck);
|
||||
#else
|
||||
LogAssert.Expect(LogType.Exception, $"Exception: {messageToCheck}");
|
||||
#endif
|
||||
|
||||
// Clean up
|
||||
Object.Destroy(parent);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e60372130aba464f9f9ae4a24bb9fe0
|
||||
guid: 3acde7838205d4b09ae3a035554c51c5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
237
Tests/Runtime/NetworkAnimator/NetworkAnimatorTests.cs
Normal file
237
Tests/Runtime/NetworkAnimator/NetworkAnimatorTests.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.Components;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
[TestFixture(HostOrServer.Host)]
|
||||
[TestFixture(HostOrServer.Server)]
|
||||
public class NetworkAnimatorTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
private GameObject m_PlayerOnServer;
|
||||
private GameObject m_PlayerOnClient;
|
||||
|
||||
private Animator m_PlayerOnServerAnimator;
|
||||
private Animator m_PlayerOnClientAnimator;
|
||||
|
||||
public NetworkAnimatorTests(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
// ideally, we would build up the AnimatorController entirely in code and not need an asset,
|
||||
// but after some attempts this doesn't seem readily doable. Instead, we load a controller
|
||||
var controller = Resources.Load("TestAnimatorController") as RuntimeAnimatorController;
|
||||
var animator = m_PlayerPrefab.AddComponent<Animator>();
|
||||
animator.runtimeAnimatorController = controller;
|
||||
|
||||
var networkAnimator = m_PlayerPrefab.AddComponent<NetworkAnimator>();
|
||||
networkAnimator.Animator = animator;
|
||||
}
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
m_PlayerOnServer = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].gameObject;
|
||||
m_PlayerOnServerAnimator = m_PlayerOnServerAnimator = m_PlayerOnServer.GetComponent<Animator>();
|
||||
|
||||
m_PlayerOnClient = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].gameObject;
|
||||
m_PlayerOnClientAnimator = m_PlayerOnClient.GetComponent<Animator>();
|
||||
|
||||
return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
// helper function to scan an animator and verify a given clip is present
|
||||
private bool HasClip(Animator animator, string clipName)
|
||||
{
|
||||
var clips = new List<AnimatorClipInfo>();
|
||||
animator.GetCurrentAnimatorClipInfo(0, clips);
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
if (clip.clip.name == clipName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator AnimationTriggerReset([Values(true, false)] bool asHash)
|
||||
{
|
||||
// We have "UnboundTrigger" purposely not bound to any animations so we can test resetting.
|
||||
// If we used a trigger that was bound to a transition, then the trigger would reset as soon as the
|
||||
// transition happens. This way it will stay stuck on
|
||||
string triggerString = "UnboundTrigger";
|
||||
int triggerHash = Animator.StringToHash(triggerString);
|
||||
|
||||
// Verify trigger is off
|
||||
Assert.True(m_PlayerOnServerAnimator.GetBool(triggerString) == false);
|
||||
Assert.True(m_PlayerOnClientAnimator.GetBool(triggerString) == false);
|
||||
|
||||
// trigger.
|
||||
if (asHash)
|
||||
{
|
||||
m_PlayerOnServer.GetComponent<NetworkAnimator>().SetTrigger(triggerHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlayerOnServer.GetComponent<NetworkAnimator>().SetTrigger(triggerString);
|
||||
}
|
||||
|
||||
// verify trigger is set for client and server
|
||||
yield return WaitForConditionOrTimeOut(() => asHash ? m_PlayerOnServerAnimator.GetBool(triggerHash) : m_PlayerOnServerAnimator.GetBool(triggerString));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out on server trigger set check");
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => asHash ? m_PlayerOnClientAnimator.GetBool(triggerHash) : m_PlayerOnClientAnimator.GetBool(triggerString));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out on client trigger set check");
|
||||
|
||||
// reset the trigger
|
||||
if (asHash)
|
||||
{
|
||||
m_PlayerOnServer.GetComponent<NetworkAnimator>().ResetTrigger(triggerHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlayerOnServer.GetComponent<NetworkAnimator>().ResetTrigger(triggerString);
|
||||
}
|
||||
|
||||
// verify trigger is reset for client and server
|
||||
yield return WaitForConditionOrTimeOut(() => asHash ? m_PlayerOnServerAnimator.GetBool(triggerHash) == false : m_PlayerOnServerAnimator.GetBool(triggerString) == false);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out on server reset check");
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => asHash ? m_PlayerOnClientAnimator.GetBool(triggerHash) == false : m_PlayerOnClientAnimator.GetBool(triggerString) == false);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out on client reset check");
|
||||
}
|
||||
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator AnimationStateSyncTest()
|
||||
{
|
||||
// check that we have started in the default state
|
||||
Assert.True(m_PlayerOnServerAnimator.GetCurrentAnimatorStateInfo(0).IsName("DefaultState"));
|
||||
Assert.True(m_PlayerOnClientAnimator.GetCurrentAnimatorStateInfo(0).IsName("DefaultState"));
|
||||
|
||||
// cause a change to the AlphaState state by setting AlphaParameter, which is
|
||||
// the variable bound to the transition from default to AlphaState (see the TestAnimatorController asset)
|
||||
m_PlayerOnServerAnimator.SetBool("AlphaParameter", true);
|
||||
|
||||
// ...and now we should be in the AlphaState having triggered the AlphaParameter
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerOnServerAnimator.GetCurrentAnimatorStateInfo(0).IsName("AlphaState"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Server failed to reach its animation state");
|
||||
|
||||
// ...and now the client should also have sync'd and arrived at the correct state
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerOnClientAnimator.GetCurrentAnimatorStateInfo(0).IsName("AlphaState"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Client failed to sync its animation state from the server");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator AnimationLayerStateSyncTest()
|
||||
{
|
||||
int layer = 1;
|
||||
// check that we have started in the default state
|
||||
Assert.True(m_PlayerOnServerAnimator.GetCurrentAnimatorStateInfo(layer).IsName("DefaultStateLayer2"));
|
||||
Assert.True(m_PlayerOnClientAnimator.GetCurrentAnimatorStateInfo(layer).IsName("DefaultStateLayer2"));
|
||||
|
||||
// cause a change to the AlphaState state by setting AlphaParameter, which is
|
||||
// the variable bound to the transition from default to AlphaState (see the TestAnimatorController asset)
|
||||
m_PlayerOnServerAnimator.SetBool("Layer2AlphaParameter", true);
|
||||
|
||||
// ...and now we should be in the AlphaState having triggered the AlphaParameter
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerOnServerAnimator.GetCurrentAnimatorStateInfo(layer).IsName("Layer2AlphaState"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Server failed to reach its animation state");
|
||||
|
||||
// ...and now the client should also have sync'd and arrived at the correct state
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerOnClientAnimator.GetCurrentAnimatorStateInfo(layer).IsName("Layer2AlphaState"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Client failed to sync its animation state from the server");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator AnimationLayerWeightTest()
|
||||
{
|
||||
int layer = 1;
|
||||
float targetWeight = 0.333f;
|
||||
|
||||
// check that we have started in the default state
|
||||
Assert.True(Mathf.Approximately(m_PlayerOnServerAnimator.GetLayerWeight(layer), 1f));
|
||||
Assert.True(Mathf.Approximately(m_PlayerOnClientAnimator.GetLayerWeight(layer), 1f));
|
||||
|
||||
m_PlayerOnServerAnimator.SetLayerWeight(layer, targetWeight);
|
||||
|
||||
// ...and now we should be in the AlphaState having triggered the AlphaParameter
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Mathf.Approximately(m_PlayerOnServerAnimator.GetLayerWeight(layer), targetWeight)
|
||||
);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Server failed to reach its animation state");
|
||||
|
||||
// ...and now the client should also have sync'd and arrived at the correct state
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Mathf.Approximately(m_PlayerOnClientAnimator.GetLayerWeight(layer), targetWeight)
|
||||
);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Server failed to reach its animation state");
|
||||
}
|
||||
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator AnimationStateSyncTriggerTest([Values(true, false)] bool asHash)
|
||||
{
|
||||
string triggerString = "TestTrigger";
|
||||
int triggerHash = Animator.StringToHash(triggerString);
|
||||
|
||||
// check that we have started in the default state
|
||||
Assert.True(m_PlayerOnServerAnimator.GetCurrentAnimatorStateInfo(0).IsName("DefaultState"));
|
||||
Assert.True(m_PlayerOnClientAnimator.GetCurrentAnimatorStateInfo(0).IsName("DefaultState"));
|
||||
|
||||
// cause a change to the AlphaState state by setting TestTrigger
|
||||
// note, we have a special test for triggers because activating triggers via the
|
||||
// NetworkAnimator is special; for other parameters you set them on the Animator and NetworkAnimator
|
||||
// listens. But because triggers are super short and transitory, we require users to call
|
||||
// NetworkAnimator.SetTrigger so we don't miss it
|
||||
if (asHash)
|
||||
{
|
||||
m_PlayerOnServer.GetComponent<NetworkAnimator>().SetTrigger(triggerHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlayerOnServer.GetComponent<NetworkAnimator>().SetTrigger(triggerString);
|
||||
}
|
||||
|
||||
// ...and now we should be in the AlphaState having triggered the AlphaParameter
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerOnServerAnimator.GetCurrentAnimatorStateInfo(0).IsName("TriggeredState"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Server failed to reach its animation state via trigger");
|
||||
|
||||
// ...and now the client should also have sync'd and arrived at the correct state
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerOnClientAnimator.GetCurrentAnimatorStateInfo(0).IsName("TriggeredState"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Client failed to sync its animation state from the server via trigger");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator AnimationStateSyncTestWithOverride()
|
||||
{
|
||||
// set up the animation override controller
|
||||
var overrideController = Resources.Load("TestAnimatorOverrideController") as AnimatorOverrideController;
|
||||
m_PlayerOnServer.GetComponent<Animator>().runtimeAnimatorController = overrideController;
|
||||
m_PlayerOnClient.GetComponent<Animator>().runtimeAnimatorController = overrideController;
|
||||
|
||||
// in our default state, we should see the OverrideDefaultAnimation clip
|
||||
Assert.True(HasClip(m_PlayerOnServerAnimator, "OverrideDefaultAnimation"));
|
||||
Assert.True(HasClip(m_PlayerOnClientAnimator, "OverrideDefaultAnimation"));
|
||||
|
||||
// cause a change to the AlphaState state by setting AlphaParameter, which is
|
||||
// the variable bound to the transition from default to AlphaState (see the TestAnimatorController asset)
|
||||
m_PlayerOnServerAnimator.SetBool("AlphaParameter", true);
|
||||
|
||||
// ...and now we should be in the AlphaState having set the AlphaParameter
|
||||
yield return WaitForConditionOrTimeOut(() => HasClip(m_PlayerOnServerAnimator, "OverrideAlphaAnimation"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Server failed to reach its overriden animation state");
|
||||
|
||||
// ...and now the client should also have sync'd and arrived at the correct state
|
||||
yield return WaitForConditionOrTimeOut(() => HasClip(m_PlayerOnServerAnimator, "OverrideAlphaAnimation"));
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Client failed to reach its overriden animation state");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c726f5bc421c3874d9c1a26bcac3f091
|
||||
guid: c2e5a740c1abd4315801e3f26ecf8adb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb1b6e801936c7f4a9af28dbed5ea2ff
|
||||
guid: c3a8707ef624947a7ae8843ca6c70c0a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
53
Tests/Runtime/NetworkAnimator/Resources/AlphaAnimation.anim
Normal file
53
Tests/Runtime/NetworkAnimator/Resources/AlphaAnimation.anim
Normal file
@@ -0,0 +1,53 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: AlphaAnimation
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings: []
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves: []
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db8faf64ca46248abb6624513ac1fb1b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: DefaultAnimation
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings: []
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves: []
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f6191147839943ab93e2171cc15c5e9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
53
Tests/Runtime/NetworkAnimator/Resources/Layer2Animation.anim
Normal file
53
Tests/Runtime/NetworkAnimator/Resources/Layer2Animation.anim
Normal file
@@ -0,0 +1,53 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Layer2Animation
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings: []
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves: []
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d31c84f6372c54d7eb8decb27010d005
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: OverrideAlphaAnimation
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings: []
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves: []
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05a2afc2ff8884d32afc64ed6765880a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: OverrideDefaultAnimation
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings: []
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves: []
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf503a5569d0b4df4910a26d09ce4530
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,449 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1102 &-8144973961595650150
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: New State
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 0}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1102 &-7257898091357968356
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: New State
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 0}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1101 &-7235917949335567458
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 2
|
||||
m_ConditionEvent: Layer2AlphaParameter
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 6016706997111698284}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 2
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1101 &-6097014330458455406
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 2
|
||||
m_ConditionEvent: AlphaParameter
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: -1198466922477486815}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1107 &-1914299053840757887
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Base Layer
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -1198466922477486815}
|
||||
m_Position: {x: 70, y: 290, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 320527679719022362}
|
||||
m_Position: {x: 110, y: 490, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 3942933370568001311}
|
||||
m_Position: {x: 380, y: 280, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions: []
|
||||
m_StateMachineTransitions: {}
|
||||
m_StateMachineBehaviours: []
|
||||
m_AnyStatePosition: {x: 50, y: 20, z: 0}
|
||||
m_EntryPosition: {x: 30, y: 180, z: 0}
|
||||
m_ExitPosition: {x: 800, y: 120, z: 0}
|
||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||
m_DefaultState: {fileID: -1198466922477486815}
|
||||
--- !u!1102 &-1198466922477486815
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: DefaultState
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: 232953446134799302}
|
||||
- {fileID: 8340347106517238820}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: 1f6191147839943ab93e2171cc15c5e9, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!91 &9100000
|
||||
AnimatorController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: TestAnimatorController
|
||||
serializedVersion: 5
|
||||
m_AnimatorParameters:
|
||||
- m_Name: AlphaParameter
|
||||
m_Type: 4
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
- m_Name: TestTrigger
|
||||
m_Type: 9
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
- m_Name: UnboundTrigger
|
||||
m_Type: 9
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
- m_Name: Layer2AlphaParameter
|
||||
m_Type: 4
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
m_AnimatorLayers:
|
||||
- serializedVersion: 5
|
||||
m_Name: Base Layer
|
||||
m_StateMachine: {fileID: -1914299053840757887}
|
||||
m_Mask: {fileID: 0}
|
||||
m_Motions: []
|
||||
m_Behaviours: []
|
||||
m_BlendingMode: 0
|
||||
m_SyncedLayerIndex: -1
|
||||
m_DefaultWeight: 0
|
||||
m_IKPass: 0
|
||||
m_SyncedLayerAffectsTiming: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
- serializedVersion: 5
|
||||
m_Name: Layer2
|
||||
m_StateMachine: {fileID: 1433017894673297828}
|
||||
m_Mask: {fileID: 0}
|
||||
m_Motions: []
|
||||
m_Behaviours: []
|
||||
m_BlendingMode: 0
|
||||
m_SyncedLayerIndex: -1
|
||||
m_DefaultWeight: 1
|
||||
m_IKPass: 0
|
||||
m_SyncedLayerAffectsTiming: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
--- !u!1101 &232953446134799302
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: AlphaParameter
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 320527679719022362}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1102 &320527679719022362
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: AlphaState
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: db8faf64ca46248abb6624513ac1fb1b, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1102 &927597079590233140
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Layer2AlphaState
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: -7235917949335567458}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: d31c84f6372c54d7eb8decb27010d005, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1107 &1433017894673297828
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Layer2
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 6016706997111698284}
|
||||
m_Position: {x: 160, y: 250, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 927597079590233140}
|
||||
m_Position: {x: 270, y: 370, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions: []
|
||||
m_StateMachineTransitions: {}
|
||||
m_StateMachineBehaviours: []
|
||||
m_AnyStatePosition: {x: 50, y: 20, z: 0}
|
||||
m_EntryPosition: {x: 50, y: 120, z: 0}
|
||||
m_ExitPosition: {x: 800, y: 120, z: 0}
|
||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||
m_DefaultState: {fileID: 6016706997111698284}
|
||||
--- !u!1102 &3942933370568001311
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: TriggeredState
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: db8faf64ca46248abb6624513ac1fb1b, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1101 &5326371122012901575
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 2
|
||||
m_ConditionEvent: AlphaParameter
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: -1198466922477486815}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1102 &6016706997111698284
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: DefaultStateLayer2
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: 6324505406226331058}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 0}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1101 &6324505406226331058
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: Layer2AlphaParameter
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 927597079590233140}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 2
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1101 &8340347106517238820
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: TestTrigger
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 3942933370568001311}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0b8ebecb362240989d16159bdfa067c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 9100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!221 &22100000
|
||||
AnimatorOverrideController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: TestAnimatorOverrideController
|
||||
m_Controller: {fileID: 9100000, guid: a0b8ebecb362240989d16159bdfa067c, type: 2}
|
||||
m_Clips:
|
||||
- m_OriginalClip: {fileID: 7400000, guid: 1f6191147839943ab93e2171cc15c5e9, type: 2}
|
||||
m_OverrideClip: {fileID: 7400000, guid: cf503a5569d0b4df4910a26d09ce4530, type: 2}
|
||||
- m_OriginalClip: {fileID: 7400000, guid: db8faf64ca46248abb6624513ac1fb1b, type: 2}
|
||||
m_OverrideClip: {fileID: 7400000, guid: 05a2afc2ff8884d32afc64ed6765880a, type: 2}
|
||||
61
Tests/Runtime/NetworkBehaviourGenericTests.cs
Normal file
61
Tests/Runtime/NetworkBehaviourGenericTests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is for testing general fixes or functionality of NetworkBehaviours
|
||||
/// </summary>
|
||||
public class NetworkBehaviourGenericTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 0;
|
||||
|
||||
private bool m_AllowServerToStart;
|
||||
|
||||
protected override bool CanStartServerAndClients()
|
||||
{
|
||||
return m_AllowServerToStart;
|
||||
}
|
||||
|
||||
public class SimpleNetworkBehaviour : NetworkBehaviour
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This test validates a fix to NetworkBehaviour.NetworkObject when
|
||||
/// the NetworkManager.LogLevel is set to Developer
|
||||
/// Note: This test does not require any clients, but should not impact this
|
||||
/// particular test if new tests are added to this class that do require clients
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator ValidateNoSpam()
|
||||
{
|
||||
m_AllowServerToStart = true;
|
||||
var objectToTest = new GameObject();
|
||||
var simpleNetworkBehaviour = objectToTest.AddComponent<SimpleNetworkBehaviour>();
|
||||
|
||||
// Now just start the Host
|
||||
yield return StartServerAndClients();
|
||||
|
||||
// set the log level to developer
|
||||
m_ServerNetworkManager.LogLevel = LogLevel.Developer;
|
||||
|
||||
// Verify the warning gets logged under normal conditions
|
||||
var isNull = simpleNetworkBehaviour.NetworkObject == null;
|
||||
LogAssert.Expect(LogType.Warning, $"[Netcode] Could not get {nameof(NetworkObject)} for the {nameof(NetworkBehaviour)}. Are you missing a {nameof(NetworkObject)} component?");
|
||||
|
||||
var networkObjectToTest = objectToTest.AddComponent<NetworkObject>();
|
||||
networkObjectToTest.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
networkObjectToTest.Spawn();
|
||||
|
||||
// Assure no log messages are logged when they should not be logged
|
||||
isNull = simpleNetworkBehaviour.NetworkObject != null;
|
||||
LogAssert.NoUnexpectedReceived();
|
||||
|
||||
networkObjectToTest.Despawn();
|
||||
Object.Destroy(networkObjectToTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 124489f89ef59d449ab4bed1f5ef2f59
|
||||
guid: f87989d8d290ed24a9048b6dbddae527
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,180 +1,344 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkBehaviourUpdaterTests : BaseMultiInstanceTest
|
||||
/// <summary>
|
||||
/// This is a refactor of the original test's NetworkBehaviour INetVarInfo derived NetworkBehaviours
|
||||
/// </summary>
|
||||
public class NetVarContainer : NetworkBehaviour
|
||||
{
|
||||
protected override int NbClients => throw new NotSupportedException("handled per test");
|
||||
|
||||
private static Type[] s_TypesToTest = new[] { null, typeof(ZeroNetVar), typeof(OneNetVar), typeof(TwoNetVar) };
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
/// <summary>
|
||||
/// Creates a prefab with two instances of this NetworkBehaviour
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static GameObject CreatePrefabGameObject(NetVarCombinationTypes netVarsToCheck)
|
||||
{
|
||||
yield break;
|
||||
var gameObject = new GameObject
|
||||
{
|
||||
// Always a good idea to name the Prefab for easy identification purposes
|
||||
name = "NetVarContainerObject"
|
||||
};
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
|
||||
// Create the two instances of the NetVarContainer components and add them to the
|
||||
// GameObject of this prefab
|
||||
var netVarContainer = gameObject.AddComponent<NetVarContainer>();
|
||||
netVarContainer.NumberOfNetVarsToCheck = netVarsToCheck.FirstType;
|
||||
netVarContainer.ValueToSetNetVarTo = NetworkBehaviourUpdaterTests.NetVarValueToSet;
|
||||
netVarContainer = gameObject.AddComponent<NetVarContainer>();
|
||||
netVarContainer.NumberOfNetVarsToCheck = netVarsToCheck.SecondType;
|
||||
netVarContainer.ValueToSetNetVarTo = NetworkBehaviourUpdaterTests.NetVarValueToSet;
|
||||
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
public enum NetVarsToCheck
|
||||
{
|
||||
One,
|
||||
Two
|
||||
}
|
||||
|
||||
public NetVarsToCheck NumberOfNetVarsToCheck;
|
||||
public int ValueToSetNetVarTo = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Only used on the client-side for this test, this
|
||||
/// is used to see if the network variables have changed.
|
||||
/// </summary>
|
||||
public bool HaveAllValuesChanged(int valueToCheck)
|
||||
{
|
||||
var allValuesChanged = false;
|
||||
switch (NumberOfNetVarsToCheck)
|
||||
{
|
||||
case NetVarsToCheck.Two:
|
||||
{
|
||||
allValuesChanged = m_FirstValue.Value == valueToCheck && m_SeconValue.Value == valueToCheck;
|
||||
break;
|
||||
}
|
||||
case NetVarsToCheck.One:
|
||||
{
|
||||
allValuesChanged = m_FirstValue.Value == valueToCheck;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allValuesChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This runs test combinations for the following
|
||||
/// test with 0, 1, 2 clients
|
||||
/// test with host and server mode
|
||||
/// test with 0, 1, 2 spawned objects
|
||||
/// test with 0, 1, 2 network behaviour per prefab
|
||||
/// test with 0, 1, 2 network variable per network behaviour
|
||||
/// for each, update netvar
|
||||
/// for each check value changed
|
||||
/// check that all network variables are no longer dirty after update
|
||||
/// Only used on the server side to check the isDirty flag for the
|
||||
/// NetworkVariables being used for each test iteration
|
||||
/// </summary>
|
||||
/// <param name="nbClients"></param>
|
||||
/// <param name="useHost"></param>
|
||||
/// <param name="nbSpawnedObjects"></param>
|
||||
/// <param name="firstNetworkBehaviour"></param>
|
||||
/// <param name="secondNetworkBehaviour"></param>
|
||||
/// <param name="thirdNetworkBehaviour"></param>
|
||||
/// <returns></returns>
|
||||
[UnityTest]
|
||||
public IEnumerator BehaviourUpdaterAllTests([Values(0, 1, 2)] int nbClients, [Values] bool useHost, [Values(0, 1, 2)] int nbSpawnedObjects,
|
||||
[ValueSource(nameof(s_TypesToTest))] Type firstNetworkBehaviour, [ValueSource(nameof(s_TypesToTest))] Type secondNetworkBehaviour)
|
||||
public bool AreNetVarsDirty()
|
||||
{
|
||||
// Create multiple NetworkManager instances
|
||||
if (!MultiInstanceHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients))
|
||||
var areDirty = false;
|
||||
switch (NumberOfNetVarsToCheck)
|
||||
{
|
||||
Debug.LogError("Failed to create instances");
|
||||
Assert.Fail("Failed to create instances");
|
||||
}
|
||||
m_ClientNetworkManagers = clients;
|
||||
m_ServerNetworkManager = server;
|
||||
Assert.That(m_ClientNetworkManagers.Length, Is.EqualTo(nbClients));
|
||||
Assert.That(m_ServerNetworkManager, Is.Not.Null);
|
||||
|
||||
// setup prefab to spawn
|
||||
void AddNetworkBehaviour(Type type, GameObject prefab)
|
||||
{
|
||||
if (type != null)
|
||||
{
|
||||
var info = prefab.AddComponent(type) as INetVarInfo;
|
||||
}
|
||||
}
|
||||
var prefabToSpawn = new GameObject();
|
||||
var networkObjectPrefab = prefabToSpawn.AddComponent<NetworkObject>();
|
||||
AddNetworkBehaviour(firstNetworkBehaviour, prefabToSpawn);
|
||||
AddNetworkBehaviour(secondNetworkBehaviour, prefabToSpawn);
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObjectPrefab);
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
clientNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
}
|
||||
|
||||
// Start the instances
|
||||
if (!MultiInstanceHelpers.Start(useHost, server, clients))
|
||||
{
|
||||
Debug.LogError("Failed to start instances");
|
||||
Assert.Fail("Failed to start instances");
|
||||
}
|
||||
// Wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
|
||||
|
||||
// Wait for connection on server side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clientCount: useHost ? nbClients + 1 : nbClients));
|
||||
|
||||
// gathering netvars to test on
|
||||
var serverNetVarsToUpdate = new List<NetworkVariable<int>>();
|
||||
for (int i = 0; i < nbSpawnedObjects; i++)
|
||||
{
|
||||
var spawnedObject = Object.Instantiate(prefabToSpawn);
|
||||
var networkSpawnedObject = spawnedObject.GetComponent<NetworkObject>();
|
||||
networkSpawnedObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
networkSpawnedObject.Spawn();
|
||||
int nbBehaviours = 0;
|
||||
foreach (var networkBehaviour in spawnedObject.GetComponents<NetworkBehaviour>())
|
||||
{
|
||||
serverNetVarsToUpdate.AddRange(((INetVarInfo)networkBehaviour).AllNetVars);
|
||||
nbBehaviours++;
|
||||
}
|
||||
Assert.That(nbBehaviours, Is.EqualTo((firstNetworkBehaviour == null ? 0 : 1) + (secondNetworkBehaviour == null ? 0 : 1)));
|
||||
}
|
||||
var serverNetVarCount = serverNetVarsToUpdate.Count;
|
||||
|
||||
yield return new WaitForSeconds(0); // wait a frame to make sure spawn is done
|
||||
// todo: with Snapshot spawns enabled and the current race condition, the following line is needed:
|
||||
// yield return new WaitForSeconds(0.2f); // wait a bit to fix the spawn/update race condition
|
||||
|
||||
foreach (var netVar in serverNetVarsToUpdate)
|
||||
{
|
||||
Assert.That(netVar.Value, Is.EqualTo(0)); // sanity check
|
||||
}
|
||||
|
||||
// test updating all netvars
|
||||
int updatedValue = 1;
|
||||
foreach (var netVar in serverNetVarsToUpdate)
|
||||
{
|
||||
netVar.Value = updatedValue;
|
||||
Assert.That(netVar.IsDirty, Is.True);
|
||||
}
|
||||
|
||||
m_ServerNetworkManager.BehaviourUpdater.NetworkBehaviourUpdate(m_ServerNetworkManager);
|
||||
|
||||
// make sure we're not dirty anymore and that clients will receive that new value
|
||||
foreach (var netVar in serverNetVarsToUpdate)
|
||||
{
|
||||
// if we don't have connected clients, netvars remain dirty
|
||||
Assert.That(netVar.IsDirty, nbClients > 0 || useHost ? Is.Not.True : Is.True);
|
||||
}
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
var nbVarsCheckedClientSide = 0;
|
||||
var countSpawnObjectResult = new MultiInstanceHelpers.CoroutineResultWrapper<bool>();
|
||||
yield return MultiInstanceHelpers.WaitForCondition(() => client.SpawnManager.SpawnedObjects.Count == nbSpawnedObjects, countSpawnObjectResult);
|
||||
Assert.That(countSpawnObjectResult.Result, Is.True);
|
||||
|
||||
foreach (var spawnedObject in client.SpawnManager.SpawnedObjects)
|
||||
{
|
||||
foreach (var behaviour in spawnedObject.Value.GetComponentsInChildren<NetworkBehaviour>())
|
||||
case NetVarsToCheck.Two:
|
||||
{
|
||||
foreach (var networkVariable in behaviour.NetworkVariableFields)
|
||||
{
|
||||
var varInt = networkVariable as NetworkVariable<int>;
|
||||
var varUpdateResult = new MultiInstanceHelpers.CoroutineResultWrapper<bool>();
|
||||
yield return MultiInstanceHelpers.WaitForCondition(() => varInt.Value == updatedValue, varUpdateResult);
|
||||
Assert.That(varUpdateResult.Result, Is.True);
|
||||
|
||||
nbVarsCheckedClientSide++;
|
||||
Assert.That(varInt.Value, Is.EqualTo(updatedValue));
|
||||
}
|
||||
areDirty = m_FirstValue.IsDirty() && m_SeconValue.IsDirty();
|
||||
break;
|
||||
}
|
||||
case NetVarsToCheck.One:
|
||||
{
|
||||
areDirty = m_FirstValue.IsDirty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return areDirty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The original version of this test only ever had up to 2 NetworkVariables per
|
||||
/// NetworkBehaviour. As opposed to using a List of NetworkVariables, we just
|
||||
/// create the maximum number that could be used and then only use what we need
|
||||
/// for each test iteration.
|
||||
/// </summary>
|
||||
private NetworkVariable<int> m_FirstValue = new NetworkVariable<int>();
|
||||
private NetworkVariable<int> m_SeconValue = new NetworkVariable<int>();
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
// Clients will register each NetworkObject when it is spawned
|
||||
if (!IsServer)
|
||||
{
|
||||
NetworkBehaviourUpdaterTests.ClientSideNotifyObjectSpawned(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server side only, sets the NetworkVariables being used to the ValueToSetNetVarTo
|
||||
/// that is pre-configured when the Network Prefab is created.
|
||||
/// </summary>
|
||||
public void SetNetworkVariableValues()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
switch (NumberOfNetVarsToCheck)
|
||||
{
|
||||
case NetVarsToCheck.Two:
|
||||
{
|
||||
m_FirstValue.Value = ValueToSetNetVarTo;
|
||||
m_SeconValue.Value = ValueToSetNetVarTo;
|
||||
Assert.True(AreNetVarsDirty(), "Not all NetworkVariables were marked dirty on server after spawned!");
|
||||
break;
|
||||
}
|
||||
case NetVarsToCheck.One:
|
||||
{
|
||||
m_FirstValue.Value = ValueToSetNetVarTo;
|
||||
Assert.True(AreNetVarsDirty(), "Not all NetworkVariables were marked dirty on server after spawned!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.That(nbVarsCheckedClientSide, Is.EqualTo(m_ClientNetworkManagers.Length > 0 ? serverNetVarCount : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface INetVarInfo
|
||||
/// <summary>
|
||||
/// Used to define how many NetworkVariables to use per NetVarContainer instance.
|
||||
/// There are always two
|
||||
/// </summary>
|
||||
public struct NetVarCombinationTypes
|
||||
{
|
||||
public List<NetworkVariable<int>> AllNetVars { get; }
|
||||
public NetVarContainer.NetVarsToCheck FirstType;
|
||||
public NetVarContainer.NetVarsToCheck SecondType;
|
||||
}
|
||||
|
||||
public class ZeroNetVar : NetworkBehaviour, INetVarInfo
|
||||
public class NetworkBehaviourUpdaterTests : NetcodeIntegrationTest
|
||||
{
|
||||
public List<NetworkVariable<int>> AllNetVars => new List<NetworkVariable<int>>(); // Needed to be independant from NetworkBehaviour's list of fields. This way, if that changes, we can still do this validation in this test
|
||||
}
|
||||
// Go ahead and create maximum number of clients (not all tests will use them)
|
||||
protected override int NumberOfClients => 2;
|
||||
public const int NetVarValueToSet = 1;
|
||||
private static List<GameObject> s_ClientSpawnedNetworkObjects = new List<GameObject>();
|
||||
private List<NetworkManager> m_ActiveClientsForCurrentTest;
|
||||
|
||||
public class OneNetVar : NetworkBehaviour, INetVarInfo
|
||||
{
|
||||
private NetworkVariable<int> m_SomeValue = new NetworkVariable<int>();
|
||||
public List<NetworkVariable<int>> AllNetVars => new List<NetworkVariable<int>>() { m_SomeValue };
|
||||
}
|
||||
/// <summary>
|
||||
/// Clients will call this when NetworkObjects are spawned on their end
|
||||
/// </summary>
|
||||
/// <param name="objectSpaned">the GameObject of the NetworkObject spawned</param>
|
||||
public static void ClientSideNotifyObjectSpawned(GameObject objectSpaned)
|
||||
{
|
||||
if (!s_ClientSpawnedNetworkObjects.Contains(objectSpaned))
|
||||
{
|
||||
s_ClientSpawnedNetworkObjects.Add(objectSpaned);
|
||||
}
|
||||
}
|
||||
|
||||
public class TwoNetVar : NetworkBehaviour, INetVarInfo
|
||||
{
|
||||
private NetworkVariable<int> m_SomeValue = new NetworkVariable<int>();
|
||||
private NetworkVariable<int> m_SomeOtherValue = new NetworkVariable<int>();
|
||||
public List<NetworkVariable<int>> AllNetVars => new List<NetworkVariable<int>>() { m_SomeValue, m_SomeOtherValue };
|
||||
protected override bool CanStartServerAndClients()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the server and client(s) required for this particular test iteration
|
||||
/// </summary>
|
||||
private IEnumerator StartClientsAndServer(bool useHost, int numberOfClients, GameObject prefabObject)
|
||||
{
|
||||
// Sanity check to make sure we are not trying to create more clients than we have available to use
|
||||
Assert.True(numberOfClients <= m_ClientNetworkManagers.Length);
|
||||
m_ActiveClientsForCurrentTest = new List<NetworkManager>();
|
||||
|
||||
// Create a list of the clients to be used in this test from the available clients
|
||||
for (int i = 0; i < numberOfClients; i++)
|
||||
{
|
||||
m_ActiveClientsForCurrentTest.Add(m_ClientNetworkManagers[i]);
|
||||
}
|
||||
|
||||
// Add the prefab to be used for this particular test iteration
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabObject });
|
||||
m_ServerNetworkManager.NetworkConfig.TickRate = 30;
|
||||
foreach (var clientManager in m_ActiveClientsForCurrentTest)
|
||||
{
|
||||
m_ServerNetworkManager.NetworkConfig.TickRate = 30;
|
||||
clientManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabObject });
|
||||
}
|
||||
|
||||
// Now spin everything up normally
|
||||
var clientsAsArry = m_ActiveClientsForCurrentTest.ToArray();
|
||||
Assert.True(NetcodeIntegrationTestHelpers.Start(useHost, m_ServerNetworkManager, clientsAsArry), "Failed to start server and client instances");
|
||||
|
||||
// Only if we have clients (not host)
|
||||
if (numberOfClients > 0)
|
||||
{
|
||||
RegisterSceneManagerHandler();
|
||||
}
|
||||
|
||||
// Wait for connection on client and server side
|
||||
yield return WaitForClientsConnectedOrTimeOut(clientsAsArry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This list replaces the original NetworkVariable types to be checked.
|
||||
/// Both NetworkVariables are of type int and the original version of this test was testing
|
||||
/// the NetworkBehaviour Update when there were 1 or more (i.e two) on the same NetworkBehaviour.
|
||||
/// After reviewing, we really only needed to test a much smaller combination of types and so
|
||||
/// this pre-generated array represents the reduced set of combinations to test.
|
||||
/// Note:
|
||||
/// The original test was also testing for no NetworkVariables of type int, which there ended up
|
||||
/// being no reason to do that and only added to the length of the execution time for this test.
|
||||
/// </summary>
|
||||
public static NetVarCombinationTypes[] NetVarCombinationTypeValues = new[]{
|
||||
new NetVarCombinationTypes() { FirstType = NetVarContainer.NetVarsToCheck.One, SecondType = NetVarContainer.NetVarsToCheck.One },
|
||||
new NetVarCombinationTypes() { FirstType = NetVarContainer.NetVarsToCheck.One, SecondType = NetVarContainer.NetVarsToCheck.Two },
|
||||
new NetVarCombinationTypes() { FirstType = NetVarContainer.NetVarsToCheck.Two, SecondType = NetVarContainer.NetVarsToCheck.Two }};
|
||||
|
||||
/// <summary>
|
||||
/// The updated BehaviourUpdaterAllTests was re-designed to replicate the same functionality being tested in the
|
||||
/// original version of this test with additional time out handling and a re-organization in the order of operations.
|
||||
/// Things like making sure all clients have spawned the NetworkObjects in question prior to testing for the
|
||||
/// NetworkVariable value changes helped to eliminate the timing issues that were happening when this test was run
|
||||
/// in a stand alone test runner build (i.e. all consoles run the stand alone version as opposed to the in-editor
|
||||
/// version like the desktop tests use).
|
||||
/// This update also updated how the server and clients were being constructed to help reduce the execution time.
|
||||
/// </summary>
|
||||
/// <param name="useHost"> whether to run the server as a host or not</param>
|
||||
/// <param name="varCombinationTypes">the NetworkVariable combination types</param>
|
||||
/// <param name="nbClients"> number of clients to use for the test</param>
|
||||
/// <param name="numToSpawn"> number of NetworkObjects to be spawned</param>
|
||||
[UnityTest]
|
||||
public IEnumerator BehaviourUpdaterAllTests([Values] bool useHost,
|
||||
[ValueSource(nameof(NetVarCombinationTypeValues))] NetVarCombinationTypes varCombinationTypes,
|
||||
[Values(0, 1, 2)] int nbClients, [Values(1, 2)] int numToSpawn)
|
||||
{
|
||||
s_ClientSpawnedNetworkObjects.Clear();
|
||||
|
||||
// The edge case scenario where we can exit early is when we are running
|
||||
// just the server (i.e. non-host) and there are zero clients. Under this
|
||||
// edge case scenario of the various combinations we do not need to run
|
||||
// this test as the IsDirty flag is never cleared when no clients exist at all.
|
||||
if (nbClients == 0 && !useHost)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Create our prefab based on the NetVarCombinationTypes
|
||||
var prefabToSpawn = NetVarContainer.CreatePrefabGameObject(varCombinationTypes);
|
||||
|
||||
yield return StartClientsAndServer(useHost, nbClients, prefabToSpawn);
|
||||
|
||||
// Tracks the server-side spawned prefab instances
|
||||
var spawnedPrefabs = new List<GameObject>();
|
||||
var tickInterval = 1.0f / m_ServerNetworkManager.NetworkConfig.TickRate;
|
||||
|
||||
// Used to determine if the client-side checks of this test should be
|
||||
// executed or not as well is used to make sure all clients have spawned
|
||||
// the appropriate number of NetworkObjects with the NetVarContainer behaviour
|
||||
var numberOfObjectsToSpawnOnClients = numToSpawn * nbClients;
|
||||
|
||||
// spawn the objects
|
||||
for (int i = 0; i < numToSpawn; i++)
|
||||
{
|
||||
var spawnedObject = Object.Instantiate(prefabToSpawn);
|
||||
spawnedPrefabs.Add(spawnedObject);
|
||||
var networkSpawnedObject = spawnedObject.GetComponent<NetworkObject>();
|
||||
networkSpawnedObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
networkSpawnedObject.Spawn();
|
||||
}
|
||||
|
||||
// When there are no clients (excluding when server is in host mode), we can skip all of this
|
||||
// wait until all objects are spawned on the clients
|
||||
if (numberOfObjectsToSpawnOnClients > 0)
|
||||
{
|
||||
// Waits for all clients to spawn the NetworkObjects
|
||||
yield return WaitForConditionOrTimeOut(() => numberOfObjectsToSpawnOnClients == s_ClientSpawnedNetworkObjects.Count);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for clients to report spawning objects! " +
|
||||
$"Total reported client-side spawned objects {s_ClientSpawnedNetworkObjects.Count}");
|
||||
}
|
||||
|
||||
// Once all clients have spawned the NetworkObjects, set the network variables for
|
||||
// those NetworkObjects on the server-side.
|
||||
foreach (var spawnedPrefab in spawnedPrefabs)
|
||||
{
|
||||
var netVarContiners = spawnedPrefab.GetComponents<NetVarContainer>();
|
||||
foreach (var netVarContiner in netVarContiners)
|
||||
{
|
||||
netVarContiner.SetNetworkVariableValues();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the NetworkBehaviours to make sure all network variables are no longer marked as dirty
|
||||
m_ServerNetworkManager.BehaviourUpdater.NetworkBehaviourUpdate(m_ServerNetworkManager);
|
||||
|
||||
// Verify that all network variables are no longer dirty on server side only if we have clients (including host)
|
||||
foreach (var serverSpawnedObject in spawnedPrefabs)
|
||||
{
|
||||
var netVarContainers = serverSpawnedObject.GetComponents<NetVarContainer>();
|
||||
foreach (var netVarContainer in netVarContainers)
|
||||
{
|
||||
Assert.False(netVarContainer.AreNetVarsDirty(), "Some NetworkVariables were still marked dirty after NetworkBehaviourUpdate!");
|
||||
}
|
||||
}
|
||||
|
||||
// When there are no clients (excluding when server is in host mode), we can skip all of this
|
||||
if (numberOfObjectsToSpawnOnClients > 0)
|
||||
{
|
||||
// Get a list of all NetVarContainer components on the client-side spawned NetworkObjects
|
||||
var clientSideNetVarContainers = new List<NetVarContainer>();
|
||||
foreach (var clientSpawnedObjects in s_ClientSpawnedNetworkObjects)
|
||||
{
|
||||
var netVarContainers = clientSpawnedObjects.GetComponents<NetVarContainer>();
|
||||
foreach (var netvarContiner in netVarContainers)
|
||||
{
|
||||
clientSideNetVarContainers.Add(netvarContiner);
|
||||
}
|
||||
}
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
clientSideNetVarContainers.Where(d =>
|
||||
d.HaveAllValuesChanged(NetVarValueToSet)).Count() == clientSideNetVarContainers.Count);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client side NetVarContainers to report all NetworkVariables have been updated!");
|
||||
}
|
||||
|
||||
Object.DestroyImmediate(prefabToSpawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkManagerCustomMessageManagerTests
|
||||
{
|
||||
@@ -13,6 +13,9 @@ namespace Unity.Netcode.EditorTests
|
||||
var transport = gameObject.AddComponent<DummyTransport>();
|
||||
|
||||
networkManager.NetworkConfig = new NetworkConfig();
|
||||
|
||||
|
||||
|
||||
// Set dummy transport that does nothing
|
||||
networkManager.NetworkConfig.NetworkTransport = transport;
|
||||
|
||||
@@ -24,6 +27,8 @@ namespace Unity.Netcode.EditorTests
|
||||
Debug.Assert(preManager == null);
|
||||
Debug.Assert(networkManager.CustomMessagingManager != null);
|
||||
|
||||
|
||||
networkManager.Shutdown();
|
||||
Object.DestroyImmediate(gameObject);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkManagerSceneManagerTests
|
||||
{
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
@@ -12,18 +13,9 @@ namespace Unity.Netcode.RuntimeTests
|
||||
/// - Server destroy spawned => Object gets destroyed and despawned/destroyed on all clients. Server does not run <see cref="NetworkPrefaInstanceHandler.HandleNetworkPrefabDestroy"/>. Client runs it.
|
||||
/// - Client destroy spawned => throw exception.
|
||||
/// </summary>
|
||||
public class NetworkObjectDestroyTests : BaseMultiInstanceTest
|
||||
public class NetworkObjectDestroyTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 1;
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, playerPrefab =>
|
||||
{
|
||||
// playerPrefab.AddComponent<TestDestroy>();
|
||||
});
|
||||
}
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Tests that a server can destroy a NetworkObject and that it gets despawned correctly.
|
||||
@@ -33,12 +25,12 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator TestNetworkObjectServerDestroy()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult));
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ServerNetworkManager, serverClientPlayerResult);
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ClientNetworkManagers[0], clientClientPlayerResult);
|
||||
|
||||
Assert.IsNotNull(serverClientPlayerResult.Result.gameObject);
|
||||
Assert.IsNotNull(clientClientPlayerResult.Result.gameObject);
|
||||
@@ -46,12 +38,9 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// destroy the server player
|
||||
Object.Destroy(serverClientPlayerResult.Result.gameObject);
|
||||
|
||||
yield return null;
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfType<DestroyObjectMessage>(m_ClientNetworkManagers[0]);
|
||||
|
||||
Assert.IsTrue(serverClientPlayerResult.Result == null); // Assert.IsNull doesn't work here
|
||||
|
||||
yield return null; // wait one frame more until we receive on client
|
||||
|
||||
Assert.IsTrue(clientClientPlayerResult.Result == null);
|
||||
|
||||
// create an unspawned networkobject and destroy it
|
||||
@@ -71,12 +60,12 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator TestNetworkObjectClientDestroy()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult));
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ServerNetworkManager, serverClientPlayerResult);
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ClientNetworkManagers[0], clientClientPlayerResult);
|
||||
|
||||
// destroy the client player, this is not allowed
|
||||
LogAssert.Expect(LogType.Exception, "NotServerException: Destroy a spawned NetworkObject on a non-host client is not valid. Call Destroy or Despawn on the server/host instead.");
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
@@ -13,13 +14,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator DontDestroyWithOwnerTest()
|
||||
{
|
||||
// create server and client instances
|
||||
MultiInstanceHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
|
||||
NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
|
||||
|
||||
// create prefab
|
||||
var gameObject = new GameObject("ClientOwnedObject");
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
networkObject.DontDestroyWithOwner = true;
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
|
||||
server.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab()
|
||||
{
|
||||
@@ -35,13 +36,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
// start server and connect clients
|
||||
MultiInstanceHelpers.Start(false, server, clients);
|
||||
NetcodeIntegrationTestHelpers.Start(false, server, clients);
|
||||
|
||||
// wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients);
|
||||
|
||||
// wait for connection on server side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(server));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(server);
|
||||
|
||||
// network objects
|
||||
var networkObjects = new List<NetworkObject>();
|
||||
@@ -56,13 +57,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
// wait for object spawn on client
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => clients[0].SpawnManager.SpawnedObjects.Count == 32));
|
||||
yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => clients[0].SpawnManager.SpawnedObjects.Count == 32);
|
||||
|
||||
// disconnect the client that owns all the clients
|
||||
MultiInstanceHelpers.StopOneClient(clients[0]);
|
||||
NetcodeIntegrationTestHelpers.StopOneClient(clients[0]);
|
||||
|
||||
// wait for disconnect
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => server.ConnectedClients.Count == 0));
|
||||
yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => server.ConnectedClients.Count == 0);
|
||||
|
||||
for (int i = 0; i < networkObjects.Count; i++)
|
||||
{
|
||||
@@ -71,7 +72,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
// cleanup
|
||||
MultiInstanceHelpers.Destroy();
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkObjectNetworkClientOwnedObjectsTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 1;
|
||||
private NetworkPrefab m_NetworkPrefab;
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
// create prefab
|
||||
var gameObject = new GameObject("ClientOwnedObject");
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
|
||||
m_NetworkPrefab = (new NetworkPrefab()
|
||||
{
|
||||
Prefab = gameObject
|
||||
});
|
||||
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(m_NetworkPrefab);
|
||||
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
client.NetworkConfig.NetworkPrefabs.Add(m_NetworkPrefab);
|
||||
}
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ChangeOwnershipOwnedObjectsAddTest()
|
||||
{
|
||||
NetworkObject serverObject = Object.Instantiate(m_NetworkPrefab.Prefab).GetComponent<NetworkObject>();
|
||||
serverObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
serverObject.Spawn();
|
||||
|
||||
// Provide enough time for the client to receive and process the spawned message.
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
// The object is owned by server
|
||||
Assert.False(m_ServerNetworkManager.ConnectedClients[m_ClientNetworkManagers[0].LocalClientId].OwnedObjects.Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
|
||||
|
||||
// Change the ownership
|
||||
serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
// Provide enough time for the client to receive and process the change in ownership message.
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
// Ensure it's now added to the list
|
||||
Assert.True(m_ServerNetworkManager.ConnectedClients[m_ClientNetworkManagers[0].LocalClientId].OwnedObjects.Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 067d53283c8fa4c31b638b830473c5b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
@@ -37,14 +38,14 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnitySetUp]
|
||||
public IEnumerator Setup()
|
||||
{
|
||||
Assert.IsTrue(MultiInstanceHelpers.Create(1, out m_ServerHost, out m_Clients));
|
||||
Assert.IsTrue(NetcodeIntegrationTestHelpers.Create(1, out m_ServerHost, out m_Clients));
|
||||
|
||||
m_ObjectToSpawn = new GameObject();
|
||||
m_NetworkObject = m_ObjectToSpawn.AddComponent<NetworkObject>();
|
||||
m_ObjectToSpawn.AddComponent<OnNetworkDespawnTestComponent>();
|
||||
|
||||
// Make it a prefab
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(m_NetworkObject);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(m_NetworkObject);
|
||||
|
||||
var networkPrefab = new NetworkPrefab();
|
||||
networkPrefab.Prefab = m_ObjectToSpawn;
|
||||
@@ -67,7 +68,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Object.Destroy(m_ObjectToSpawn);
|
||||
m_ObjectToSpawn = null;
|
||||
}
|
||||
MultiInstanceHelpers.Destroy();
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
yield return null;
|
||||
}
|
||||
|
||||
@@ -85,22 +86,22 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator TestNetworkObjectDespawnOnShutdown([Values(InstanceType.Server, InstanceType.Host, InstanceType.Client)] InstanceType despawnCheck)
|
||||
{
|
||||
var useHost = despawnCheck == InstanceType.Server ? false : true;
|
||||
var useHost = despawnCheck != InstanceType.Server;
|
||||
var networkManager = despawnCheck == InstanceType.Host || despawnCheck == InstanceType.Server ? m_ServerHost : m_Clients[0];
|
||||
|
||||
// Start the instances
|
||||
if (!MultiInstanceHelpers.Start(useHost, m_ServerHost, m_Clients))
|
||||
if (!NetcodeIntegrationTestHelpers.Start(useHost, m_ServerHost, m_Clients))
|
||||
{
|
||||
Debug.LogError("Failed to start instances");
|
||||
Assert.Fail("Failed to start instances");
|
||||
}
|
||||
|
||||
// [Client-Side] Wait for a connection to the server
|
||||
yield return MultiInstanceHelpers.WaitForClientsConnected(m_Clients, null, 512);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(m_Clients, null, 512);
|
||||
|
||||
// [Host-Server-Side] Check to make sure all clients are connected
|
||||
var clientCount = useHost ? m_Clients.Length + 1 : m_Clients.Length;
|
||||
yield return MultiInstanceHelpers.WaitForClientsConnectedToServer(m_ServerHost, clientCount, null, 512);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnectedToServer(m_ServerHost, clientCount, null, 512);
|
||||
|
||||
// Spawn the test object
|
||||
var spawnedObject = Object.Instantiate(m_NetworkObject);
|
||||
@@ -109,8 +110,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
spawnedNetworkObject.Spawn(true);
|
||||
|
||||
// Get the spawned object relative to which NetworkManager instance we are testing.
|
||||
var relativeSpawnedObject = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.GetComponent<OnNetworkDespawnTestComponent>() != null), networkManager, relativeSpawnedObject));
|
||||
var relativeSpawnedObject = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.GetComponent<OnNetworkDespawnTestComponent>() != null), networkManager, relativeSpawnedObject);
|
||||
var onNetworkDespawnTestComponent = relativeSpawnedObject.Result.GetComponent<OnNetworkDespawnTestComponent>();
|
||||
|
||||
// Confirm it is not set before shutting down the NetworkManager
|
||||
|
||||
@@ -3,22 +3,21 @@ using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkObjectOnSpawnTests : BaseMultiInstanceTest
|
||||
public class NetworkObjectOnSpawnTests : NetcodeIntegrationTest
|
||||
{
|
||||
private GameObject m_TestNetworkObjectPrefab;
|
||||
private GameObject m_TestNetworkObjectInstance;
|
||||
|
||||
protected override int NbClients => 2;
|
||||
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
/// <summary>
|
||||
/// Tests that instantiating a <see cref="NetworkObject"/> and destroying without spawning it
|
||||
/// does not run <see cref="NetworkBehaviour.OnNetworkSpawn"/> or <see cref="NetworkBehaviour.OnNetworkSpawn"/>.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityTest]
|
||||
public IEnumerator InstantiateDestroySpawnNotCalled()
|
||||
{
|
||||
@@ -29,6 +28,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// instantiate
|
||||
m_TestNetworkObjectInstance = Object.Instantiate(m_TestNetworkObjectPrefab);
|
||||
yield return null;
|
||||
Object.Destroy(m_TestNetworkObjectInstance);
|
||||
|
||||
}
|
||||
|
||||
private class FailWhenSpawned : NetworkBehaviour
|
||||
@@ -44,20 +45,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
}
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, playerPrefab =>
|
||||
{
|
||||
// add test component
|
||||
playerPrefab.AddComponent<TrackOnSpawnFunctions>();
|
||||
});
|
||||
m_PlayerPrefab.AddComponent<TrackOnSpawnFunctions>();
|
||||
}
|
||||
|
||||
[UnityTearDown]
|
||||
public override IEnumerator Teardown()
|
||||
protected override IEnumerator OnTearDown()
|
||||
{
|
||||
|
||||
if (m_TestNetworkObjectPrefab != null)
|
||||
{
|
||||
Object.Destroy(m_TestNetworkObjectPrefab);
|
||||
@@ -67,10 +61,11 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
Object.Destroy(m_TestNetworkObjectInstance);
|
||||
}
|
||||
yield return base.Teardown();
|
||||
|
||||
yield return base.OnTearDown();
|
||||
}
|
||||
|
||||
private List<TrackOnSpawnFunctions> m_ClientTrackOnSpawnInstances = new List<TrackOnSpawnFunctions>();
|
||||
|
||||
/// <summary>
|
||||
/// Test that callbacks are run for playerobject spawn, despawn, regular spawn, destroy on server.
|
||||
/// </summary>
|
||||
@@ -79,19 +74,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator TestOnNetworkSpawnCallbacks()
|
||||
{
|
||||
// [Host-Side] Get the Host owned instance
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult));
|
||||
var serverInstance = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ServerNetworkManager.LocalClientId].GetComponent<TrackOnSpawnFunctions>();
|
||||
|
||||
var serverInstance = serverClientPlayerResult.Result.GetComponent<TrackOnSpawnFunctions>();
|
||||
|
||||
var clientInstances = new List<TrackOnSpawnFunctions>();
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), client, clientClientPlayerResult));
|
||||
var clientRpcTests = clientClientPlayerResult.Result.GetComponent<TrackOnSpawnFunctions>();
|
||||
var clientRpcTests = m_PlayerNetworkObjects[client.LocalClientId][m_ServerNetworkManager.LocalClientId].gameObject.GetComponent<TrackOnSpawnFunctions>();
|
||||
Assert.IsNotNull(clientRpcTests);
|
||||
clientInstances.Add(clientRpcTests);
|
||||
m_ClientTrackOnSpawnInstances.Add(clientRpcTests);
|
||||
}
|
||||
|
||||
// -------------- step 1 check player spawn despawn
|
||||
@@ -99,69 +88,84 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// check spawned on server
|
||||
Assert.AreEqual(1, serverInstance.OnNetworkSpawnCalledCount);
|
||||
|
||||
// safety check despawned
|
||||
// safety check server despawned
|
||||
Assert.AreEqual(0, serverInstance.OnNetworkDespawnCalledCount);
|
||||
|
||||
// check spawned on client
|
||||
foreach (var clientInstance in clientInstances)
|
||||
// Conditional check for clients spawning or despawning
|
||||
var checkSpawnCondition = false;
|
||||
var expectedSpawnCount = 1;
|
||||
var expectedDespawnCount = 0;
|
||||
bool HasConditionBeenMet()
|
||||
{
|
||||
Assert.AreEqual(1, clientInstance.OnNetworkSpawnCalledCount);
|
||||
|
||||
// safety check despawned
|
||||
Assert.AreEqual(0, clientInstance.OnNetworkDespawnCalledCount);
|
||||
var clientsCompleted = 0;
|
||||
// check spawned on client
|
||||
foreach (var clientInstance in m_ClientTrackOnSpawnInstances)
|
||||
{
|
||||
if (checkSpawnCondition)
|
||||
{
|
||||
if (clientInstance.OnNetworkSpawnCalledCount == expectedSpawnCount)
|
||||
{
|
||||
clientsCompleted++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clientInstance.OnNetworkDespawnCalledCount == expectedDespawnCount)
|
||||
{
|
||||
clientsCompleted++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return clientsCompleted >= NumberOfClients;
|
||||
}
|
||||
|
||||
// despawn on server. However, since we'll be using this object later in the test, don't delete it (false)
|
||||
// safety check that all clients have not been despawned yet
|
||||
Assert.True(HasConditionBeenMet(), "Failed condition that all clients not despawned yet!");
|
||||
|
||||
// now verify that all clients have been spawned
|
||||
checkSpawnCondition = true;
|
||||
yield return WaitForConditionOrTimeOut(HasConditionBeenMet);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side spawns!");
|
||||
|
||||
// despawn on server. However, since we'll be using this object later in the test, don't delete it
|
||||
serverInstance.GetComponent<NetworkObject>().Despawn(false);
|
||||
|
||||
// check despawned on server
|
||||
Assert.AreEqual(1, serverInstance.OnNetworkDespawnCalledCount);
|
||||
// we now expect the clients to each have despawned once
|
||||
expectedDespawnCount = 1;
|
||||
|
||||
// wait long enough for player object to be despawned
|
||||
int nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
yield return s_DefaultWaitForTick;
|
||||
// verify that all client-side instances are despawned
|
||||
checkSpawnCondition = false;
|
||||
yield return WaitForConditionOrTimeOut(HasConditionBeenMet);
|
||||
|
||||
// check despawned on clients
|
||||
foreach (var clientInstance in clientInstances)
|
||||
{
|
||||
Assert.AreEqual(1, clientInstance.OnNetworkDespawnCalledCount);
|
||||
}
|
||||
|
||||
//----------- step 2 check spawn again and destroy
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side despawns!");
|
||||
|
||||
//----------- step 2 check spawn and destroy again
|
||||
serverInstance.GetComponent<NetworkObject>().Spawn();
|
||||
|
||||
// wait long enough for player object to be spawned
|
||||
nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
|
||||
// wait a tick
|
||||
yield return s_DefaultWaitForTick;
|
||||
// check spawned again on server this is 2 because we are reusing the object which was already spawned once.
|
||||
Assert.AreEqual(2, serverInstance.OnNetworkSpawnCalledCount);
|
||||
|
||||
// check spawned on client
|
||||
foreach (var clientInstance in clientInstances)
|
||||
{
|
||||
Assert.AreEqual(1, clientInstance.OnNetworkSpawnCalledCount);
|
||||
}
|
||||
checkSpawnCondition = true;
|
||||
yield return WaitForConditionOrTimeOut(HasConditionBeenMet);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side spawns! (2nd pass)");
|
||||
|
||||
// destroy the server object
|
||||
Object.Destroy(serverInstance.gameObject);
|
||||
|
||||
// wait one frame for destroy to kick in
|
||||
yield return null;
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
// check whether despawned was called again on server instance
|
||||
Assert.AreEqual(2, serverInstance.OnNetworkDespawnCalledCount);
|
||||
|
||||
// wait long enough for player object to be despawned on client
|
||||
nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
checkSpawnCondition = false;
|
||||
yield return WaitForConditionOrTimeOut(HasConditionBeenMet);
|
||||
|
||||
// check despawned on clients
|
||||
foreach (var clientInstance in clientInstances)
|
||||
{
|
||||
Assert.AreEqual(1, clientInstance.OnNetworkDespawnCalledCount);
|
||||
}
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side despawns! (2nd pass)");
|
||||
}
|
||||
|
||||
private class TrackOnSpawnFunctions : NetworkBehaviour
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -52,7 +53,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Assert.That(k_ClientInstanceCount, Is.GreaterThan(0));
|
||||
|
||||
// create NetworkManager instances
|
||||
Assert.That(MultiInstanceHelpers.Create(k_ClientInstanceCount, out m_ServerNetworkManager, out m_ClientNetworkManagers));
|
||||
Assert.That(NetcodeIntegrationTestHelpers.Create(k_ClientInstanceCount, out m_ServerNetworkManager, out m_ClientNetworkManagers));
|
||||
Assert.That(m_ServerNetworkManager, Is.Not.Null);
|
||||
Assert.That(m_ClientNetworkManagers, Is.Not.Null);
|
||||
Assert.That(m_ClientNetworkManagers.Length, Is.EqualTo(k_ClientInstanceCount));
|
||||
@@ -61,7 +62,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
m_DummyPrefab = new GameObject("DummyPrefabPrototype");
|
||||
m_DummyPrefab.AddComponent<NetworkObject>();
|
||||
m_DummyPrefab.AddComponent<NetworkObjectOwnershipComponent>();
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(m_DummyPrefab.GetComponent<NetworkObject>());
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(m_DummyPrefab.GetComponent<NetworkObject>());
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab { Prefab = m_DummyPrefab });
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
@@ -69,19 +70,19 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
// start server and client NetworkManager instances
|
||||
Assert.That(MultiInstanceHelpers.Start(m_IsHost, m_ServerNetworkManager, m_ClientNetworkManagers));
|
||||
Assert.That(NetcodeIntegrationTestHelpers.Start(m_IsHost, m_ServerNetworkManager, m_ClientNetworkManagers));
|
||||
|
||||
// wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(m_ClientNetworkManagers));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(m_ClientNetworkManagers);
|
||||
|
||||
// wait for connection on server side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(m_ServerNetworkManager));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(m_ServerNetworkManager);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
MultiInstanceHelpers.Destroy();
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
|
||||
if (m_DummyGameObject != null)
|
||||
{
|
||||
@@ -106,8 +107,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var dummyNetworkObjectId = dummyNetworkObject.NetworkObjectId;
|
||||
Assert.That(dummyNetworkObjectId, Is.GreaterThan(0));
|
||||
|
||||
int nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfType<CreateObjectMessage>(m_ClientNetworkManagers[0]);
|
||||
|
||||
Assert.That(m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(dummyNetworkObjectId));
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
@@ -136,17 +136,14 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Assert.That(m_ServerNetworkManager.ConnectedClients.ContainsKey(m_ClientNetworkManagers[0].LocalClientId));
|
||||
serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfType<ChangeOwnershipMessage>(m_ClientNetworkManagers[0]);
|
||||
|
||||
|
||||
Assert.That(clientComponent.OnGainedOwnershipFired);
|
||||
Assert.That(clientComponent.CachedOwnerIdOnGainedOwnership, Is.EqualTo(m_ClientNetworkManagers[0].LocalClientId));
|
||||
serverObject.ChangeOwnership(m_ServerNetworkManager.ServerClientId);
|
||||
|
||||
nextFrameNumber = Time.frameCount + 2;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfType<ChangeOwnershipMessage>(m_ClientNetworkManagers[0]);
|
||||
|
||||
Assert.That(serverObject.OwnerClientId, Is.EqualTo(m_ServerNetworkManager.LocalClientId));
|
||||
Assert.That(clientComponent.OnLostOwnershipFired);
|
||||
|
||||
@@ -3,6 +3,7 @@ using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkObjectSpawnManyObjectsTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 1;
|
||||
// "many" in this case means enough to exceed a ushort_max message size written in the header
|
||||
// 1500 is not a magic number except that it's big enough to trigger a failure
|
||||
private const int k_SpawnedObjects = 1500;
|
||||
|
||||
private NetworkPrefab m_PrefabToSpawn;
|
||||
|
||||
// Using this component assures we will know precisely how many prefabs were spawned on the client
|
||||
public class SpawnObjecTrackingComponent : NetworkBehaviour
|
||||
{
|
||||
public static int SpawnedObjects;
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (!IsServer)
|
||||
{
|
||||
SpawnedObjects++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
SpawnObjecTrackingComponent.SpawnedObjects = 0;
|
||||
// create prefab
|
||||
var gameObject = new GameObject("TestObject");
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
gameObject.AddComponent<SpawnObjecTrackingComponent>();
|
||||
|
||||
m_PrefabToSpawn = new NetworkPrefab() { Prefab = gameObject };
|
||||
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(m_PrefabToSpawn);
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
client.NetworkConfig.NetworkPrefabs.Add(m_PrefabToSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
// When this test fails it does so without an exception and will wait the default ~6 minutes
|
||||
[Timeout(10000)]
|
||||
public IEnumerator WhenManyObjectsAreSpawnedAtOnce_AllAreReceived()
|
||||
{
|
||||
for (int x = 0; x < k_SpawnedObjects; x++)
|
||||
{
|
||||
NetworkObject serverObject = Object.Instantiate(m_PrefabToSpawn.Prefab).GetComponent<NetworkObject>();
|
||||
serverObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
serverObject.Spawn();
|
||||
}
|
||||
// ensure all objects are replicated before spawning more
|
||||
yield return WaitForConditionOrTimeOut(() => SpawnObjecTrackingComponent.SpawnedObjects < k_SpawnedObjects);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for the client to spawn {k_SpawnedObjects} objects!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e0439aa2d2a72e4aa42b051d26af366
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -22,7 +23,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
Guid baseObjectID = NetworkManagerHelper.AddGameNetworkObject(k_TestPrefabObjectName + m_ObjectId.ToString());
|
||||
NetworkObject validPrefab = NetworkManagerHelper.InstantiatedNetworkObjects[baseObjectID];
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(validPrefab);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(validPrefab);
|
||||
m_ObjectId++;
|
||||
return validPrefab.gameObject;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -29,9 +30,9 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
}
|
||||
|
||||
public class NetworkShowHideTests : BaseMultiInstanceTest
|
||||
public class NetworkShowHideTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 2;
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
private ulong m_ClientId0;
|
||||
private GameObject m_PrefabToSpawn;
|
||||
@@ -43,15 +44,14 @@ namespace Unity.Netcode.RuntimeTests
|
||||
private NetworkObject m_Object2OnClient0;
|
||||
private NetworkObject m_Object3OnClient0;
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(useHost: true, nbClients: NbClients,
|
||||
updatePlayerPrefab: playerPrefab =>
|
||||
{
|
||||
var networkTransform = playerPrefab.AddComponent<NetworkShowHideTest>();
|
||||
m_PrefabToSpawn = PreparePrefab(typeof(ShowHideObject));
|
||||
});
|
||||
var networkTransform = m_PlayerPrefab.AddComponent<NetworkShowHideTest>();
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_PrefabToSpawn = PreparePrefab(typeof(ShowHideObject));
|
||||
}
|
||||
|
||||
public GameObject PreparePrefab(Type type)
|
||||
@@ -59,7 +59,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var prefabToSpawn = new GameObject();
|
||||
prefabToSpawn.AddComponent(type);
|
||||
var networkObjectPrefab = prefabToSpawn.AddComponent<NetworkObject>();
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObjectPrefab);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObjectPrefab);
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
@@ -138,25 +138,22 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
private IEnumerator RefreshNetworkObjects()
|
||||
{
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(
|
||||
MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.NetworkObjectId == m_NetSpawnedObject1.NetworkObjectId,
|
||||
m_ClientNetworkManagers[0],
|
||||
serverClientPlayerResult));
|
||||
serverClientPlayerResult);
|
||||
m_Object1OnClient0 = serverClientPlayerResult.Result;
|
||||
yield return MultiInstanceHelpers.Run(
|
||||
MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.NetworkObjectId == m_NetSpawnedObject2.NetworkObjectId,
|
||||
m_ClientNetworkManagers[0],
|
||||
serverClientPlayerResult));
|
||||
serverClientPlayerResult);
|
||||
m_Object2OnClient0 = serverClientPlayerResult.Result;
|
||||
serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(
|
||||
MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.NetworkObjectId == m_NetSpawnedObject3.NetworkObjectId,
|
||||
m_ClientNetworkManagers[0],
|
||||
serverClientPlayerResult));
|
||||
serverClientPlayerResult);
|
||||
m_Object3OnClient0 = serverClientPlayerResult.Result;
|
||||
|
||||
// make sure the objects are set with the right network manager
|
||||
|
||||
@@ -2,16 +2,17 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkSpawnManagerTests : BaseMultiInstanceTest
|
||||
public class NetworkSpawnManagerTests : NetcodeIntegrationTest
|
||||
{
|
||||
private ulong serverSideClientId => m_ServerNetworkManager.ServerClientId;
|
||||
private ulong clientSideClientId => m_ClientNetworkManagers[0].LocalClientId;
|
||||
private ulong otherClientSideClientId => m_ClientNetworkManagers[1].LocalClientId;
|
||||
|
||||
protected override int NbClients => 2;
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
[Test]
|
||||
public void TestServerCanAccessItsOwnPlayer()
|
||||
@@ -96,7 +97,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// test when client connects, player object is now available
|
||||
|
||||
// connect new client
|
||||
if (!MultiInstanceHelpers.CreateNewClients(1, out NetworkManager[] clients))
|
||||
if (!NetcodeIntegrationTestHelpers.CreateNewClients(1, out NetworkManager[] clients))
|
||||
{
|
||||
Debug.LogError("Failed to create instances");
|
||||
Assert.Fail("Failed to create instances");
|
||||
@@ -104,8 +105,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var newClientNetworkManager = clients[0];
|
||||
newClientNetworkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
newClientNetworkManager.StartClient();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnected(newClientNetworkManager));
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerNetworkManager.ConnectedClients.ContainsKey(newClientNetworkManager.LocalClientId)));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientConnected(newClientNetworkManager);
|
||||
yield return WaitForConditionOrTimeOut(() => m_ServerNetworkManager.ConnectedClients.ContainsKey(newClientNetworkManager.LocalClientId));
|
||||
var newClientLocalClientId = newClientNetworkManager.LocalClientId;
|
||||
|
||||
// test new client can get that itself locally
|
||||
@@ -119,8 +120,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
// test when client disconnects, player object no longer available.
|
||||
var nbConnectedClients = m_ServerNetworkManager.ConnectedClients.Count;
|
||||
MultiInstanceHelpers.StopOneClient(newClientNetworkManager);
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => m_ServerNetworkManager.ConnectedClients.Count == nbConnectedClients - 1));
|
||||
NetcodeIntegrationTestHelpers.StopOneClient(newClientNetworkManager);
|
||||
yield return WaitForConditionOrTimeOut(() => m_ServerNetworkManager.ConnectedClients.Count == nbConnectedClients - 1);
|
||||
|
||||
serverSideNewClientPlayer = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(newClientLocalClientId);
|
||||
Assert.Null(serverSideNewClientPlayer);
|
||||
|
||||
@@ -8,90 +8,92 @@ using NUnit.Framework;
|
||||
// using Unity.Netcode.Samples;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkTransformTestComponent : NetworkTransform
|
||||
{
|
||||
public bool ReadyToReceivePositionUpdate = false;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
base.OnNetworkSpawn();
|
||||
|
||||
ReadyToReceivePositionUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// [TestFixture(true, true)]
|
||||
[TestFixture(true, false)]
|
||||
// [TestFixture(false, true)]
|
||||
[TestFixture(false, false)]
|
||||
public class NetworkTransformTests : BaseMultiInstanceTest
|
||||
public class NetworkTransformTests : NetcodeIntegrationTest
|
||||
{
|
||||
private NetworkObject m_ClientSideClientPlayer;
|
||||
private NetworkObject m_ServerSideClientPlayer;
|
||||
|
||||
private readonly bool m_TestWithClientNetworkTransform;
|
||||
|
||||
private readonly bool m_TestWithHost;
|
||||
|
||||
public NetworkTransformTests(bool testWithHost, bool testWithClientNetworkTransform)
|
||||
{
|
||||
m_TestWithHost = testWithHost; // from test fixture
|
||||
m_UseHost = testWithHost; // from test fixture
|
||||
m_TestWithClientNetworkTransform = testWithClientNetworkTransform;
|
||||
}
|
||||
|
||||
protected override int NbClients => 1;
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(useHost: m_TestWithHost, nbClients: NbClients, updatePlayerPrefab: playerPrefab =>
|
||||
if (m_TestWithClientNetworkTransform)
|
||||
{
|
||||
if (m_TestWithClientNetworkTransform)
|
||||
{
|
||||
// playerPrefab.AddComponent<ClientNetworkTransform>();
|
||||
}
|
||||
else
|
||||
{
|
||||
playerPrefab.AddComponent<NetworkTransform>();
|
||||
}
|
||||
});
|
||||
// m_PlayerPrefab.AddComponent<ClientNetworkTransform>();
|
||||
}
|
||||
else
|
||||
{
|
||||
var networkTransform = m_PlayerPrefab.AddComponent<NetworkTransformTestComponent>();
|
||||
networkTransform.Interpolate = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
#if NGO_TRANSFORM_DEBUG
|
||||
// Log assert for writing without authority is a developer log...
|
||||
// TODO: This is why monolithic test base classes and test helpers are an anti-pattern - this is part of an individual test case setup but is separated from the code verifying it!
|
||||
m_ServerNetworkManager.LogLevel = LogLevel.Developer;
|
||||
m_ClientNetworkManagers[0].LogLevel = LogLevel.Developer;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ServerNetworkManager, serverClientPlayerResult));
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
// Get the client player representation on both the server and the client side
|
||||
m_ServerSideClientPlayer = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId];
|
||||
m_ClientSideClientPlayer = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId];
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
// Get the NetworkTransformTestComponent to make sure the client side is ready before starting test
|
||||
var otherSideNetworkTransformComponent = m_ClientSideClientPlayer.GetComponent<NetworkTransformTestComponent>();
|
||||
|
||||
m_ServerSideClientPlayer = serverClientPlayerResult.Result;
|
||||
m_ClientSideClientPlayer = clientClientPlayerResult.Result;
|
||||
// Wait for the client-side to notify it is finished initializing and spawning.
|
||||
yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransformComponent.ReadyToReceivePositionUpdate == true);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client-side to notify it is ready!");
|
||||
|
||||
yield return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
// TODO: rewrite after perms & authority changes
|
||||
[UnityTest]
|
||||
public IEnumerator TestAuthoritativeTransformChangeOneAtATime([Values] bool testLocalTransform)
|
||||
{
|
||||
var waitResult = new MultiInstanceHelpers.CoroutineResultWrapper<bool>();
|
||||
// Get the client player's NetworkTransform for both instances
|
||||
var authoritativeNetworkTransform = m_ServerSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
var otherSideNetworkTransform = m_ClientSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
|
||||
NetworkTransform authoritativeNetworkTransform;
|
||||
NetworkTransform otherSideNetworkTransform;
|
||||
// if (m_TestWithClientNetworkTransform)
|
||||
// {
|
||||
// // client auth net transform can write from client, not from server
|
||||
// otherSideNetworkTransform = m_ServerSideClientPlayer.GetComponent<ClientNetworkTransform>();
|
||||
// authoritativeNetworkTransform = m_ClientSideClientPlayer.GetComponent<ClientNetworkTransform>();
|
||||
// }
|
||||
// else
|
||||
{
|
||||
// server auth net transform can't write from client, not from client
|
||||
authoritativeNetworkTransform = m_ServerSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
otherSideNetworkTransform = m_ClientSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
}
|
||||
Assert.That(!otherSideNetworkTransform.CanCommitToTransform);
|
||||
Assert.That(authoritativeNetworkTransform.CanCommitToTransform);
|
||||
|
||||
authoritativeNetworkTransform.Interpolate = false;
|
||||
otherSideNetworkTransform.Interpolate = false;
|
||||
|
||||
if (authoritativeNetworkTransform.CanCommitToTransform)
|
||||
{
|
||||
authoritativeNetworkTransform.InLocalSpace = testLocalTransform;
|
||||
@@ -106,23 +108,25 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
// test position
|
||||
var authPlayerTransform = authoritativeNetworkTransform.transform;
|
||||
authPlayerTransform.position = new Vector3(10, 20, 30);
|
||||
|
||||
Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "server side pos should be zero at first"); // sanity check
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.position.x > approximation, waitResult, maxFrames: 120));
|
||||
if (!waitResult.Result)
|
||||
{
|
||||
throw new Exception("timeout while waiting for position change");
|
||||
}
|
||||
|
||||
authPlayerTransform.position = new Vector3(10, 20, 30);
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransform.transform.position.x > approximation);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"timeout while waiting for position change! Otherside value {otherSideNetworkTransform.transform.position.x} vs. Approximation {approximation}");
|
||||
|
||||
Assert.True(new Vector3(10, 20, 30) == otherSideNetworkTransform.transform.position, $"wrong position on ghost, {otherSideNetworkTransform.transform.position}"); // Vector3 already does float approximation with ==
|
||||
|
||||
// test rotation
|
||||
authPlayerTransform.rotation = Quaternion.Euler(45, 40, 35); // using euler angles instead of quaternions directly to really see issues users might encounter
|
||||
Assert.AreEqual(Quaternion.identity, otherSideNetworkTransform.transform.rotation, "wrong initial value for rotation"); // sanity check
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.rotation.eulerAngles.x > approximation, waitResult, maxFrames: 120));
|
||||
if (!waitResult.Result)
|
||||
{
|
||||
throw new Exception("timeout while waiting for rotation change");
|
||||
}
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransform.transform.rotation.eulerAngles.x > approximation);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "timeout while waiting for rotation change");
|
||||
|
||||
// approximation needed here since eulerAngles isn't super precise.
|
||||
Assert.LessOrEqual(Math.Abs(45 - otherSideNetworkTransform.transform.rotation.eulerAngles.x), approximation, $"wrong rotation on ghost on x, got {otherSideNetworkTransform.transform.rotation.eulerAngles.x}");
|
||||
Assert.LessOrEqual(Math.Abs(40 - otherSideNetworkTransform.transform.rotation.eulerAngles.y), approximation, $"wrong rotation on ghost on y, got {otherSideNetworkTransform.transform.rotation.eulerAngles.y}");
|
||||
@@ -133,11 +137,11 @@ namespace Unity.Netcode.RuntimeTests
|
||||
UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.y, "wrong initial value for scale"); // sanity check
|
||||
UnityEngine.Assertions.Assert.AreApproximatelyEqual(1f, otherSideNetworkTransform.transform.lossyScale.z, "wrong initial value for scale"); // sanity check
|
||||
authPlayerTransform.localScale = new Vector3(2, 3, 4);
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => otherSideNetworkTransform.transform.lossyScale.x > 1f + approximation, waitResult, maxFrames: 120));
|
||||
if (!waitResult.Result)
|
||||
{
|
||||
throw new Exception("timeout while waiting for scale change");
|
||||
}
|
||||
|
||||
yield return WaitForConditionOrTimeOut(() => otherSideNetworkTransform.transform.lossyScale.x > 1f + approximation);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "timeout while waiting for scale change");
|
||||
|
||||
UnityEngine.Assertions.Assert.AreApproximatelyEqual(2f, otherSideNetworkTransform.transform.lossyScale.x, "wrong scale on ghost");
|
||||
UnityEngine.Assertions.Assert.AreApproximatelyEqual(3f, otherSideNetworkTransform.transform.lossyScale.y, "wrong scale on ghost");
|
||||
UnityEngine.Assertions.Assert.AreApproximatelyEqual(4f, otherSideNetworkTransform.transform.lossyScale.z, "wrong scale on ghost");
|
||||
@@ -147,33 +151,17 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
// [Ignore("skipping for now, still need to figure weird multiinstance issue with hosts")]
|
||||
public IEnumerator TestCantChangeTransformFromOtherSideAuthority([Values] bool testClientAuthority)
|
||||
{
|
||||
// test server can't change client authoritative transform
|
||||
NetworkTransform authoritativeNetworkTransform;
|
||||
NetworkTransform otherSideNetworkTransform;
|
||||
|
||||
// if (m_TestWithClientNetworkTransform)
|
||||
// {
|
||||
// // client auth net transform can write from client, not from server
|
||||
// otherSideNetworkTransform = m_ServerSideClientPlayer.GetComponent<ClientNetworkTransform>();
|
||||
// authoritativeNetworkTransform = m_ClientSideClientPlayer.GetComponent<ClientNetworkTransform>();
|
||||
// }
|
||||
// else
|
||||
{
|
||||
// server auth net transform can't write from client, not from client
|
||||
authoritativeNetworkTransform = m_ServerSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
otherSideNetworkTransform = m_ClientSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
}
|
||||
|
||||
authoritativeNetworkTransform.Interpolate = false;
|
||||
otherSideNetworkTransform.Interpolate = false;
|
||||
// Get the client player's NetworkTransform for both instances
|
||||
var authoritativeNetworkTransform = m_ServerSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
var otherSideNetworkTransform = m_ClientSideClientPlayer.GetComponent<NetworkTransform>();
|
||||
|
||||
Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "other side pos should be zero at first"); // sanity check
|
||||
|
||||
otherSideNetworkTransform.transform.position = new Vector3(4, 5, 6);
|
||||
|
||||
yield return null; // one frame
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
Assert.AreEqual(Vector3.zero, otherSideNetworkTransform.transform.position, "got authority error, but other side still moved!");
|
||||
#if NGO_TRANSFORM_DEBUG
|
||||
@@ -190,12 +178,10 @@ namespace Unity.Netcode.RuntimeTests
|
||||
* test teleport without interpolation
|
||||
* test dynamic spawning
|
||||
*/
|
||||
|
||||
[UnityTearDown]
|
||||
public override IEnumerator Teardown()
|
||||
protected override IEnumerator OnTearDown()
|
||||
{
|
||||
yield return base.Teardown();
|
||||
UnityEngine.Object.DestroyImmediate(m_PlayerPrefab);
|
||||
yield return base.OnTearDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkVarBufferCopyTest : BaseMultiInstanceTest
|
||||
public class NetworkVarBufferCopyTest : NetcodeIntegrationTest
|
||||
{
|
||||
public class DummyNetVar : NetworkVariableBase
|
||||
{
|
||||
@@ -13,7 +15,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public bool FieldWritten;
|
||||
public bool DeltaRead;
|
||||
public bool FieldRead;
|
||||
public bool Dirty = true;
|
||||
public bool Dirty = false;
|
||||
|
||||
public override void ResetDirty()
|
||||
{
|
||||
@@ -80,56 +82,88 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
public class DummyNetBehaviour : NetworkBehaviour
|
||||
{
|
||||
public DummyNetVar NetVar;
|
||||
}
|
||||
protected override int NbClients => 1;
|
||||
public DummyNetVar NetVar = new DummyNetVar();
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(useHost: true, nbClients: NbClients,
|
||||
updatePlayerPrefab: playerPrefab =>
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (!IsServer)
|
||||
{
|
||||
var dummyNetBehaviour = playerPrefab.AddComponent<DummyNetBehaviour>();
|
||||
});
|
||||
ClientDummyNetBehaviourSpawned(this);
|
||||
}
|
||||
base.OnNetworkSpawn();
|
||||
}
|
||||
}
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
private static List<DummyNetBehaviour> s_ClientDummyNetBehavioursSpawned = new List<DummyNetBehaviour>();
|
||||
public static void ClientDummyNetBehaviourSpawned(DummyNetBehaviour dummyNetBehaviour)
|
||||
{
|
||||
s_ClientDummyNetBehavioursSpawned.Add(dummyNetBehaviour);
|
||||
}
|
||||
|
||||
protected override IEnumerator OnSetup()
|
||||
{
|
||||
s_ClientDummyNetBehavioursSpawned.Clear();
|
||||
return base.OnSetup();
|
||||
}
|
||||
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<DummyNetBehaviour>();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestEntireBufferIsCopiedOnNetworkVariableDelta()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId,
|
||||
m_ServerNetworkManager, serverClientPlayerResult));
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId,
|
||||
m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
m_ServerNetworkManager, serverClientPlayerResult);
|
||||
|
||||
var serverSideClientPlayer = serverClientPlayerResult.Result;
|
||||
var serverComponent = serverSideClientPlayer.GetComponent<DummyNetBehaviour>();
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId,
|
||||
m_ClientNetworkManagers[0], clientClientPlayerResult);
|
||||
|
||||
var clientSideClientPlayer = clientClientPlayerResult.Result;
|
||||
var clientComponent = clientSideClientPlayer.GetComponent<DummyNetBehaviour>();
|
||||
|
||||
var serverComponent = (serverSideClientPlayer).GetComponent<DummyNetBehaviour>();
|
||||
var clientComponent = (clientSideClientPlayer).GetComponent<DummyNetBehaviour>();
|
||||
// Wait for the DummyNetBehaviours on the client side to notify they have been initialized and spawned
|
||||
yield return WaitForConditionOrTimeOut(() => s_ClientDummyNetBehavioursSpawned.Count >= 1);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client side DummyNetBehaviour to register it was spawned!");
|
||||
|
||||
var waitResult = new MultiInstanceHelpers.CoroutineResultWrapper<bool>();
|
||||
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(
|
||||
() => clientComponent.NetVar.DeltaRead == true,
|
||||
waitResult,
|
||||
maxFrames: 120));
|
||||
|
||||
if (!waitResult.Result)
|
||||
{
|
||||
Assert.Fail("Failed to send a delta within 120 frames");
|
||||
}
|
||||
// Check that FieldWritten is written when dirty
|
||||
serverComponent.NetVar.Dirty = true;
|
||||
yield return s_DefaultWaitForTick;
|
||||
Assert.True(serverComponent.NetVar.FieldWritten);
|
||||
|
||||
// Check that DeltaWritten is written when dirty
|
||||
serverComponent.NetVar.Dirty = true;
|
||||
yield return s_DefaultWaitForTick;
|
||||
Assert.True(serverComponent.NetVar.DeltaWritten);
|
||||
Assert.True(clientComponent.NetVar.FieldRead);
|
||||
Assert.True(clientComponent.NetVar.DeltaRead);
|
||||
|
||||
// Check that both FieldRead and DeltaRead were invoked on the client side
|
||||
yield return WaitForConditionOrTimeOut(() => clientComponent.NetVar.FieldRead == true && clientComponent.NetVar.DeltaRead == true);
|
||||
|
||||
var timedOutMessage = "Timed out waiting for client reads: ";
|
||||
if (s_GlobalTimeoutHelper.TimedOut)
|
||||
{
|
||||
if (!clientComponent.NetVar.FieldRead)
|
||||
{
|
||||
timedOutMessage += "[FieldRead]";
|
||||
}
|
||||
|
||||
if (!clientComponent.NetVar.DeltaRead)
|
||||
{
|
||||
timedOutMessage += "[DeltaRead]";
|
||||
}
|
||||
}
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, timedOutMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public struct TestStruct : INetworkSerializable
|
||||
public struct TestStruct : INetworkSerializable, IEquatable<TestStruct>
|
||||
{
|
||||
public uint SomeInt;
|
||||
public bool SomeBool;
|
||||
@@ -27,12 +29,31 @@ namespace Unity.Netcode.RuntimeTests
|
||||
serializer.SerializeValue(ref SomeInt);
|
||||
serializer.SerializeValue(ref SomeBool);
|
||||
}
|
||||
|
||||
public bool Equals(TestStruct other)
|
||||
{
|
||||
return SomeInt == other.SomeInt && SomeBool == other.SomeBool;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is TestStruct other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return ((int)SomeInt * 397) ^ SomeBool.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkVariableTest : NetworkBehaviour
|
||||
{
|
||||
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 NetworkVariable<FixedString32Bytes> FixedString32 = new NetworkVariable<FixedString32Bytes>();
|
||||
|
||||
@@ -47,14 +68,26 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
public readonly NetworkVariable<TestStruct> TheStruct = new NetworkVariable<TestStruct>();
|
||||
public readonly NetworkList<TestStruct> TheListOfStructs = new NetworkList<TestStruct>();
|
||||
|
||||
public bool ListDelegateTriggered;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (!IsServer)
|
||||
{
|
||||
NetworkVariableTests.ClientNetworkVariableTestSpawned(this);
|
||||
}
|
||||
base.OnNetworkSpawn();
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkVariableTests : BaseMultiInstanceTest
|
||||
[TestFixture(true)]
|
||||
[TestFixture(false)]
|
||||
public class NetworkVariableTests : NetcodeIntegrationTest
|
||||
{
|
||||
private const string k_FixedStringTestValue = "abcdefghijklmnopqrstuvwxyz";
|
||||
protected override int NbClients => 2;
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
private const uint k_TestUInt = 0x12345678;
|
||||
|
||||
@@ -64,36 +97,72 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
private const int k_TestKey1 = 0x0f0f;
|
||||
|
||||
private static List<NetworkVariableTest> s_ClientNetworkVariableTestInstances = new List<NetworkVariableTest>();
|
||||
public static void ClientNetworkVariableTestSpawned(NetworkVariableTest networkVariableTest)
|
||||
{
|
||||
s_ClientNetworkVariableTestInstances.Add(networkVariableTest);
|
||||
}
|
||||
|
||||
// Player1 component on the server
|
||||
private NetworkVariableTest m_Player1OnServer;
|
||||
|
||||
// Player1 component on client1
|
||||
private NetworkVariableTest m_Player1OnClient1;
|
||||
|
||||
private bool m_TestWithHost;
|
||||
private NetworkListTestPredicate m_NetworkListPredicateHandler;
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
private bool m_EnsureLengthSafety;
|
||||
|
||||
public NetworkVariableTests(bool ensureLengthSafety)
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(useHost: m_TestWithHost, nbClients: NbClients,
|
||||
updatePlayerPrefab: playerPrefab =>
|
||||
{
|
||||
playerPrefab.AddComponent<NetworkVariableTest>();
|
||||
});
|
||||
m_EnsureLengthSafety = ensureLengthSafety;
|
||||
}
|
||||
|
||||
protected override bool CanStartServerAndClients()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is an adjustment to how the server and clients are started in order
|
||||
/// to avoid timing issues when running in a stand alone test runner build.
|
||||
/// </summary>
|
||||
private IEnumerator InitializeServerAndClients(bool useHost)
|
||||
{
|
||||
s_ClientNetworkVariableTestInstances.Clear();
|
||||
m_PlayerPrefab.AddComponent<NetworkVariableTest>();
|
||||
|
||||
m_ServerNetworkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_EnsureLengthSafety;
|
||||
m_ServerNetworkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
client.NetworkConfig.EnsureNetworkVariableLengthSafety = m_EnsureLengthSafety;
|
||||
client.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
}
|
||||
|
||||
Assert.True(NetcodeIntegrationTestHelpers.Start(useHost, m_ServerNetworkManager, m_ClientNetworkManagers), "Failed to start server and client instances");
|
||||
|
||||
RegisterSceneManagerHandler();
|
||||
|
||||
// Wait for connection on client and server side
|
||||
yield return WaitForClientsConnectedOrTimeOut();
|
||||
|
||||
// These are the *SERVER VERSIONS* of the *CLIENT PLAYER 1 & 2*
|
||||
var result = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
var result = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId,
|
||||
m_ServerNetworkManager, result));
|
||||
m_ServerNetworkManager, result);
|
||||
|
||||
// Assign server-side client's player
|
||||
m_Player1OnServer = result.Result.GetComponent<NetworkVariableTest>();
|
||||
|
||||
// This is client1's view of itself
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation(
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId,
|
||||
m_ClientNetworkManagers[0], result));
|
||||
m_ClientNetworkManagers[0], result);
|
||||
|
||||
// Assign client-side local player
|
||||
m_Player1OnClient1 = result.Result.GetComponent<NetworkVariableTest>();
|
||||
|
||||
m_Player1OnServer.TheList.Clear();
|
||||
@@ -106,6 +175,14 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
throw new Exception("at least one client network container not empty at start");
|
||||
}
|
||||
|
||||
var instanceCount = useHost ? NumberOfClients * 3 : NumberOfClients * 2;
|
||||
// Wait for the client-side to notify it is finished initializing and spawning.
|
||||
yield return WaitForConditionOrTimeOut(() => s_ClientNetworkVariableTestInstances.Count == instanceCount);
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for all client NetworkVariableTest instances to register they have spawned!");
|
||||
|
||||
yield return s_DefaultWaitForTick;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,13 +191,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator AllNetworkVariableTypes([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
|
||||
// Create, instantiate, and host
|
||||
// This would normally go in Setup, but since every other test but this one
|
||||
// uses MultiInstanceHelper, and it does its own NetworkManager setup / teardown,
|
||||
// uses NetworkManagerHelper, and it does its own NetworkManager setup / teardown,
|
||||
// for now we put this within this one test until we migrate it to MIH
|
||||
Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out _));
|
||||
Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out NetworkManager server, useHost ? NetworkManagerHelper.NetworkManagerOperatingMode.Host : NetworkManagerHelper.NetworkManagerOperatingMode.Server));
|
||||
|
||||
Assert.IsTrue(server.IsHost == useHost, $"{nameof(useHost)} does not match the server.IsHost value!");
|
||||
|
||||
Guid gameObjectId = NetworkManagerHelper.AddGameNetworkObject("NetworkVariableTestComponent");
|
||||
|
||||
@@ -131,14 +208,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// Start Testing
|
||||
networkVariableTestComponent.EnableTesting = true;
|
||||
|
||||
var testsAreComplete = networkVariableTestComponent.IsTestComplete();
|
||||
|
||||
// Wait for the NetworkVariable tests to complete
|
||||
while (!testsAreComplete)
|
||||
{
|
||||
yield return new WaitForSeconds(0.003f);
|
||||
testsAreComplete = networkVariableTestComponent.IsTestComplete();
|
||||
}
|
||||
yield return WaitForConditionOrTimeOut(() => true == networkVariableTestComponent.IsTestComplete());
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for the test to complete!");
|
||||
|
||||
// Stop Testing
|
||||
networkVariableTestComponent.EnableTesting = false;
|
||||
@@ -148,18 +219,16 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// Disable this once we are done.
|
||||
networkVariableTestComponent.gameObject.SetActive(false);
|
||||
|
||||
Assert.IsTrue(testsAreComplete);
|
||||
|
||||
// This would normally go in Teardown, but since every other test but this one
|
||||
// uses MultiInstanceHelper, and it does its own NetworkManager setup / teardown,
|
||||
// uses NetworkManagerHelper, and it does its own NetworkManager setup / teardown,
|
||||
// for now we put this within this one test until we migrate it to MIH
|
||||
NetworkManagerHelper.ShutdownNetworkManager();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClientWritePermissionTest([Values(true, false)] bool useHost)
|
||||
[UnityTest]
|
||||
public IEnumerator ClientWritePermissionTest([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
|
||||
// client must not be allowed to write to a server auth variable
|
||||
Assert.Throws<InvalidOperationException>(() => m_Player1OnClient1.TheScalar.Value = k_TestVal1);
|
||||
@@ -168,222 +237,186 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator FixedString32Test([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.FixedString32.Value = k_FixedStringTestValue;
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
m_Player1OnServer.FixedString32.Value = k_FixedStringTestValue;
|
||||
|
||||
// we are writing to the private and public variables on player 1's object...
|
||||
},
|
||||
() =>
|
||||
{
|
||||
|
||||
// ...and we should see the writes to the private var only on the server & the owner,
|
||||
// but the public variable everywhere
|
||||
return
|
||||
m_Player1OnClient1.FixedString32.Value == k_FixedStringTestValue;
|
||||
}
|
||||
);
|
||||
// Now wait for the client side version to be updated to k_FixedStringTestValue
|
||||
yield return WaitForConditionOrTimeOut(() => m_Player1OnClient1.FixedString32.Value == k_FixedStringTestValue);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client-side NetworkVariable to update!");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListAdd([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(k_TestVal1);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal2);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return m_Player1OnServer.TheList.Count == 2 &&
|
||||
m_Player1OnClient1.TheList.Count == 2 &&
|
||||
m_Player1OnServer.ListDelegateTriggered &&
|
||||
m_Player1OnClient1.ListDelegateTriggered &&
|
||||
m_Player1OnServer.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnClient1.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnServer.TheList[1] == k_TestVal2 &&
|
||||
m_Player1OnClient1.TheList[1] == k_TestVal2;
|
||||
}
|
||||
);
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
m_NetworkListPredicateHandler = new NetworkListTestPredicate(m_Player1OnServer, m_Player1OnClient1, NetworkListTestPredicate.NetworkListTestStates.Add, 10);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WhenListContainsManyLargeValues_OverflowExceptionIsNotThrown([Values(true, false)] bool useHost)
|
||||
{
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
m_NetworkListPredicateHandler = new NetworkListTestPredicate(m_Player1OnServer, m_Player1OnClient1, NetworkListTestPredicate.NetworkListTestStates.ContainsLarge, 20);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListContains([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.Contains(k_TestVal1) &&
|
||||
m_Player1OnClient1.TheList.Contains(k_TestVal1);
|
||||
}
|
||||
);
|
||||
// Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated
|
||||
yield return NetworkListAdd(useHost);
|
||||
|
||||
// Now test the NetworkList.Contains method
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.Contains);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListRemoveValue([Values(true, false)] bool useHost)
|
||||
public IEnumerator NetworkListRemove([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(k_TestVal1);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal2);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal3);
|
||||
m_Player1OnServer.TheList.Remove(k_TestVal2);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return m_Player1OnServer.TheList.Count == 2 &&
|
||||
m_Player1OnClient1.TheList.Count == 2 &&
|
||||
m_Player1OnServer.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnClient1.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnServer.TheList[1] == k_TestVal3 &&
|
||||
m_Player1OnClient1.TheList[1] == k_TestVal3;
|
||||
}
|
||||
);
|
||||
// Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated
|
||||
yield return NetworkListAdd(useHost);
|
||||
|
||||
// Remove two entries by index
|
||||
m_Player1OnServer.TheList.Remove(3);
|
||||
m_Player1OnServer.TheList.Remove(5);
|
||||
|
||||
// Really just verifies the data at this point
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListInsert([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(k_TestVal1);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal2);
|
||||
m_Player1OnServer.TheList.Insert(1, k_TestVal3);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return m_Player1OnServer.TheList.Count == 3 &&
|
||||
m_Player1OnClient1.TheList.Count == 3 &&
|
||||
m_Player1OnServer.ListDelegateTriggered &&
|
||||
m_Player1OnClient1.ListDelegateTriggered &&
|
||||
m_Player1OnServer.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnClient1.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnServer.TheList[1] == k_TestVal3 &&
|
||||
m_Player1OnClient1.TheList[1] == k_TestVal3 &&
|
||||
m_Player1OnServer.TheList[2] == k_TestVal2 &&
|
||||
m_Player1OnClient1.TheList[2] == k_TestVal2;
|
||||
}
|
||||
);
|
||||
// Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated
|
||||
yield return NetworkListAdd(useHost);
|
||||
|
||||
// Now randomly insert a random value entry
|
||||
m_Player1OnServer.TheList.Insert(Random.Range(0, 9), Random.Range(1, 99));
|
||||
|
||||
// Verify the element count and values on the client matches the server
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListIndexOf([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(k_TestVal1);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal2);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal3);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return m_Player1OnServer.TheList.IndexOf(k_TestVal1) == 0 &&
|
||||
m_Player1OnClient1.TheList.IndexOf(k_TestVal1) == 0 &&
|
||||
m_Player1OnServer.TheList.IndexOf(k_TestVal2) == 1 &&
|
||||
m_Player1OnClient1.TheList.IndexOf(k_TestVal2) == 1 &&
|
||||
m_Player1OnServer.TheList.IndexOf(k_TestVal3) == 2 &&
|
||||
m_Player1OnClient1.TheList.IndexOf(k_TestVal3) == 2;
|
||||
}
|
||||
);
|
||||
}
|
||||
// Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated
|
||||
yield return NetworkListAdd(useHost);
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListArrayOperator([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(k_TestVal3);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal3);
|
||||
m_Player1OnServer.TheList[0] = k_TestVal1;
|
||||
m_Player1OnServer.TheList[1] = k_TestVal2;
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return m_Player1OnServer.TheList.Count == 2 &&
|
||||
m_Player1OnClient1.TheList.Count == 2 &&
|
||||
m_Player1OnServer.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnClient1.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnServer.TheList[1] == k_TestVal2 &&
|
||||
m_Player1OnClient1.TheList[1] == k_TestVal2;
|
||||
}
|
||||
);
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.IndexOf);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
|
||||
[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;
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
// Add 1 element value and verify it is the same on the client
|
||||
m_NetworkListPredicateHandler = new NetworkListTestPredicate(m_Player1OnServer, m_Player1OnClient1, NetworkListTestPredicate.NetworkListTestStates.Add, 1);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
|
||||
// Setup our original and
|
||||
var previousValue = m_Player1OnServer.TheList[0];
|
||||
var updatedValue = previousValue + 10;
|
||||
|
||||
// Callback that verifies the changed event occurred and that the original and new values are correct
|
||||
void TestValueUpdatedCallback(NetworkListEvent<int> changedEvent)
|
||||
{
|
||||
testSucceeded = changedEvent.PreviousValue == k_TestVal1 &&
|
||||
changedEvent.Value == k_TestVal3;
|
||||
testSucceeded = changedEvent.PreviousValue == previousValue &&
|
||||
changedEvent.Value == updatedValue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// Subscribe to the OnListChanged event on the client side and
|
||||
m_Player1OnClient1.TheList.OnListChanged += TestValueUpdatedCallback;
|
||||
m_Player1OnServer.TheList[0] = updatedValue;
|
||||
|
||||
// Wait until we know the client side matches the server side before checking if the callback was a success
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
|
||||
Assert.That(testSucceeded);
|
||||
m_Player1OnClient1.TheList.OnListChanged -= TestValueUpdatedCallback;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NetworkListIEnumerator([Values(true, false)] bool useHost)
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListRemoveAt([Values(true, false)] bool useHost)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
// Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated
|
||||
yield return NetworkListAdd(useHost);
|
||||
|
||||
// Randomly remove a few entries
|
||||
m_Player1OnServer.TheList.RemoveAt(Random.Range(0, m_Player1OnServer.TheList.Count - 1));
|
||||
m_Player1OnServer.TheList.RemoveAt(Random.Range(0, m_Player1OnServer.TheList.Count - 1));
|
||||
m_Player1OnServer.TheList.RemoveAt(Random.Range(0, m_Player1OnServer.TheList.Count - 1));
|
||||
|
||||
// Verify the element count and values on the client matches the server
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListClear([Values(true, false)] bool useHost)
|
||||
{
|
||||
// Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated
|
||||
yield return NetworkListAdd(useHost);
|
||||
m_Player1OnServer.TheList.Clear();
|
||||
// Verify the element count and values on the client matches the server
|
||||
m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData);
|
||||
yield return WaitForConditionOrTimeOut(m_NetworkListPredicateHandler);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestNetworkVariableStruct([Values(true, false)] bool useHost)
|
||||
{
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
|
||||
bool VerifyStructure()
|
||||
{
|
||||
return m_Player1OnClient1.TheStruct.Value.SomeBool == m_Player1OnServer.TheStruct.Value.SomeBool &&
|
||||
m_Player1OnClient1.TheStruct.Value.SomeInt == m_Player1OnServer.TheStruct.Value.SomeInt;
|
||||
}
|
||||
|
||||
m_Player1OnServer.TheStruct.Value = new TestStruct() { SomeInt = k_TestUInt, SomeBool = false };
|
||||
m_Player1OnServer.TheStruct.SetDirty(true);
|
||||
|
||||
// Wait for the client-side to notify it is finished initializing and spawning.
|
||||
yield return WaitForConditionOrTimeOut(VerifyStructure);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestINetworkSerializableCallsNetworkSerialize([Values(true, false)] bool useHost)
|
||||
{
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
TestStruct.NetworkSerializeCalledOnWrite = false;
|
||||
TestStruct.NetworkSerializeCalledOnRead = false;
|
||||
m_Player1OnServer.TheStruct.Value = new TestStruct() { SomeInt = k_TestUInt, SomeBool = false };
|
||||
|
||||
static bool VerifyCallback() => TestStruct.NetworkSerializeCalledOnWrite && TestStruct.NetworkSerializeCalledOnRead;
|
||||
|
||||
// Wait for the client-side to notify it is finished initializing and spawning.
|
||||
yield return WaitForConditionOrTimeOut(VerifyCallback);
|
||||
}
|
||||
|
||||
#region COULD_BE_REMOVED
|
||||
[UnityTest]
|
||||
[Ignore("This is used several times already in the NetworkListPredicate")]
|
||||
// TODO: If we end up using the new suggested pattern, then delete this
|
||||
public IEnumerator NetworkListArrayOperator([Values(true, false)] bool useHost)
|
||||
{
|
||||
yield return NetworkListAdd(useHost);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
[Ignore("This is used several times already in the NetworkListPredicate")]
|
||||
// TODO: If we end up using the new suggested pattern, then delete this
|
||||
public IEnumerator NetworkListIEnumerator([Values(true, false)] bool useHost)
|
||||
{
|
||||
yield return InitializeServerAndClients(useHost);
|
||||
var correctVals = new int[3];
|
||||
correctVals[0] = k_TestVal1;
|
||||
correctVals[1] = k_TestVal2;
|
||||
@@ -404,99 +437,184 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListRemoveAt([Values(true, false)] bool useHost)
|
||||
|
||||
protected override IEnumerator OnTearDown()
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
m_NetworkListPredicateHandler = null;
|
||||
yield return base.OnTearDown();
|
||||
}
|
||||
}
|
||||
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(k_TestVal1);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal2);
|
||||
m_Player1OnServer.TheList.Add(k_TestVal3);
|
||||
m_Player1OnServer.TheList.RemoveAt(1);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return m_Player1OnServer.TheList.Count == 2 &&
|
||||
m_Player1OnClient1.TheList.Count == 2 &&
|
||||
m_Player1OnServer.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnClient1.TheList[0] == k_TestVal1 &&
|
||||
m_Player1OnServer.TheList[1] == k_TestVal3 &&
|
||||
m_Player1OnClient1.TheList[1] == k_TestVal3;
|
||||
}
|
||||
);
|
||||
/// <summary>
|
||||
/// Handles the more generic conditional logic for NetworkList tests
|
||||
/// which can be used with the <see cref="NetcodeIntegrationTest.WaitForConditionOrTimeOut"/>
|
||||
/// that accepts anything derived from the <see cref="ConditionalPredicateBase"/> class
|
||||
/// as a parameter.
|
||||
/// </summary>
|
||||
public class NetworkListTestPredicate : ConditionalPredicateBase
|
||||
{
|
||||
private const int k_MaxRandomValue = 1000;
|
||||
|
||||
private Dictionary<NetworkListTestStates, Func<bool>> m_StateFunctions;
|
||||
|
||||
// Player1 component on the Server
|
||||
private NetworkVariableTest m_Player1OnServer;
|
||||
|
||||
// Player1 component on client1
|
||||
private NetworkVariableTest m_Player1OnClient1;
|
||||
|
||||
private string m_TestStageFailedMessage;
|
||||
|
||||
public enum NetworkListTestStates
|
||||
{
|
||||
Add,
|
||||
ContainsLarge,
|
||||
Contains,
|
||||
VerifyData,
|
||||
IndexOf,
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkListClear([Values(true, false)] bool useHost)
|
||||
private NetworkListTestStates m_NetworkListTestState;
|
||||
|
||||
public void SetNetworkListTestState(NetworkListTestStates networkListTestState)
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
|
||||
// first put some stuff in; re-use the add test
|
||||
yield return NetworkListAdd(useHost);
|
||||
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() => m_Player1OnServer.TheList.Clear(),
|
||||
() =>
|
||||
{
|
||||
return
|
||||
m_Player1OnServer.ListDelegateTriggered &&
|
||||
m_Player1OnClient1.ListDelegateTriggered &&
|
||||
m_Player1OnServer.TheList.Count == 0 &&
|
||||
m_Player1OnClient1.TheList.Count == 0;
|
||||
}
|
||||
);
|
||||
m_NetworkListTestState = networkListTestState;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestNetworkVariableStruct([Values(true, false)] bool useHost)
|
||||
/// <summary>
|
||||
/// Determines if the condition has been reached for the current NetworkListTestState
|
||||
/// </summary>
|
||||
protected override bool OnHasConditionBeenReached()
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
m_Player1OnServer.TheStruct.Value =
|
||||
new TestStruct() { SomeInt = k_TestUInt, SomeBool = false };
|
||||
m_Player1OnServer.TheStruct.SetDirty(true);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return
|
||||
m_Player1OnClient1.TheStruct.Value.SomeBool == false &&
|
||||
m_Player1OnClient1.TheStruct.Value.SomeInt == k_TestUInt;
|
||||
}
|
||||
);
|
||||
var isStateRegistered = m_StateFunctions.ContainsKey(m_NetworkListTestState);
|
||||
Assert.IsTrue(isStateRegistered);
|
||||
return m_StateFunctions[m_NetworkListTestState].Invoke();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestINetworkSerializableCallsNetworkSerialize([Values(true, false)] bool useHost)
|
||||
/// <summary>
|
||||
/// Provides all information about the players for both sides for simplicity and informative sake.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string ConditionFailedInfo()
|
||||
{
|
||||
m_TestWithHost = useHost;
|
||||
yield return MultiInstanceHelpers.RunAndWaitForCondition(
|
||||
() =>
|
||||
{
|
||||
TestStruct.NetworkSerializeCalledOnWrite = false;
|
||||
TestStruct.NetworkSerializeCalledOnRead = false;
|
||||
m_Player1OnServer.TheStruct.Value =
|
||||
new TestStruct() { SomeInt = k_TestUInt, SomeBool = false };
|
||||
m_Player1OnServer.TheStruct.SetDirty(true);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
return
|
||||
TestStruct.NetworkSerializeCalledOnWrite &&
|
||||
TestStruct.NetworkSerializeCalledOnRead;
|
||||
}
|
||||
);
|
||||
return $"{m_NetworkListTestState} condition test failed:\n Server List Count: { m_Player1OnServer.TheList.Count} vs Client List Count: { m_Player1OnClient1.TheList.Count}\n" +
|
||||
$"Server List Count: { m_Player1OnServer.TheLargeList.Count} vs Client List Count: { m_Player1OnClient1.TheLargeList.Count}\n" +
|
||||
$"Server Delegate Triggered: {m_Player1OnServer.ListDelegateTriggered} | Client Delegate Triggered: {m_Player1OnClient1.ListDelegateTriggered}\n";
|
||||
}
|
||||
|
||||
[UnityTearDown]
|
||||
public override IEnumerator Teardown()
|
||||
/// <summary>
|
||||
/// When finished, check if a time out occurred and if so assert and provide meaningful information to troubleshoot why
|
||||
/// </summary>
|
||||
protected override void OnFinished()
|
||||
{
|
||||
yield return base.Teardown();
|
||||
Assert.IsFalse(TimedOut, $"{nameof(NetworkListTestPredicate)} timed out waiting for the {m_NetworkListTestState} condition to be reached! \n" + ConditionFailedInfo());
|
||||
}
|
||||
|
||||
// Uses the ArrayOperator and validates that on both sides the count and values are the same
|
||||
private bool OnVerifyData()
|
||||
{
|
||||
// Wait until both sides have the same number of elements
|
||||
if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the client values against the server values to make sure they match
|
||||
for (int i = 0; i < m_Player1OnServer.TheList.Count; i++)
|
||||
{
|
||||
if (m_Player1OnServer.TheList[i] != m_Player1OnClient1.TheList[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the data count, values, and that the ListDelegate on both sides was triggered
|
||||
/// </summary>
|
||||
private bool OnAdd()
|
||||
{
|
||||
bool wasTriggerred = m_Player1OnServer.ListDelegateTriggered && m_Player1OnClient1.ListDelegateTriggered;
|
||||
return wasTriggerred && OnVerifyData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current version of this test only verified the count of the large list, so that is what this does
|
||||
/// </summary>
|
||||
private bool OnContainsLarge()
|
||||
{
|
||||
return m_Player1OnServer.TheLargeList.Count == m_Player1OnClient1.TheLargeList.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests NetworkList.Contains which also verifies all values are the same on both sides
|
||||
/// </summary>
|
||||
private bool OnContains()
|
||||
{
|
||||
// Wait until both sides have the same number of elements
|
||||
if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse through all server values and use the NetworkList.Contains method to check if the value is in the list on the client side
|
||||
foreach (var serverValue in m_Player1OnServer.TheList)
|
||||
{
|
||||
if (!m_Player1OnClient1.TheList.Contains(serverValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests NetworkList.IndexOf and verifies that all values are aligned on both sides
|
||||
/// </summary>
|
||||
private bool OnIndexOf()
|
||||
{
|
||||
foreach (var serverSideValue in m_Player1OnServer.TheList)
|
||||
{
|
||||
var indexToTest = m_Player1OnServer.TheList.IndexOf(serverSideValue);
|
||||
if (indexToTest != m_Player1OnServer.TheList.IndexOf(serverSideValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public NetworkListTestPredicate(NetworkVariableTest player1OnServer, NetworkVariableTest player1OnClient1, NetworkListTestStates networkListTestState, int elementCount)
|
||||
{
|
||||
m_NetworkListTestState = networkListTestState;
|
||||
m_Player1OnServer = player1OnServer;
|
||||
m_Player1OnClient1 = player1OnClient1;
|
||||
m_StateFunctions = new Dictionary<NetworkListTestStates, Func<bool>>
|
||||
{
|
||||
{ NetworkListTestStates.Add, OnAdd },
|
||||
{ NetworkListTestStates.ContainsLarge, OnContainsLarge },
|
||||
{ NetworkListTestStates.Contains, OnContains },
|
||||
{ NetworkListTestStates.VerifyData, OnVerifyData },
|
||||
{ NetworkListTestStates.IndexOf, OnIndexOf }
|
||||
};
|
||||
|
||||
if (networkListTestState == NetworkListTestStates.ContainsLarge)
|
||||
{
|
||||
for (var i = 0; i < elementCount; ++i)
|
||||
{
|
||||
m_Player1OnServer.TheLargeList.Add(new FixedString128Bytes());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < elementCount; i++)
|
||||
{
|
||||
m_Player1OnServer.TheList.Add(Random.Range(0, k_MaxRandomValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
Tests/Runtime/NetworkVisibilityTests.cs
Normal file
55
Tests/Runtime/NetworkVisibilityTests.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
[TestFixture(SceneManagementState.SceneManagementEnabled)]
|
||||
[TestFixture(SceneManagementState.SceneManagementDisabled)]
|
||||
public class NetworkVisibilityTests : NetcodeIntegrationTest
|
||||
{
|
||||
public enum SceneManagementState
|
||||
{
|
||||
SceneManagementEnabled,
|
||||
SceneManagementDisabled
|
||||
}
|
||||
protected override int NumberOfClients => 1;
|
||||
private GameObject m_TestNetworkPrefab;
|
||||
private bool m_SceneManagementEnabled;
|
||||
|
||||
public NetworkVisibilityTests(SceneManagementState sceneManagementState)
|
||||
{
|
||||
m_SceneManagementEnabled = sceneManagementState == SceneManagementState.SceneManagementEnabled;
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_TestNetworkPrefab = CreateNetworkObjectPrefab("Object");
|
||||
m_TestNetworkPrefab.AddComponent<NetworkVisibilityComponent>();
|
||||
m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = m_SceneManagementEnabled;
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
clientNetworkManager.NetworkConfig.EnableSceneManagement = m_SceneManagementEnabled;
|
||||
}
|
||||
base.OnServerAndClientsCreated();
|
||||
}
|
||||
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
SpawnObject(m_TestNetworkPrefab, m_ServerNetworkManager);
|
||||
|
||||
yield return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator HiddenObjectsTest()
|
||||
{
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType<NetworkVisibilityComponent>().Where((c) => c.IsSpawned).Count() == 2);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for the visible object count to equal 2!");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Runtime/NetworkVisibilityTests.cs.meta
Normal file
11
Tests/Runtime/NetworkVisibilityTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45ff8252bf32540509fde11c19e0f3c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,8 +3,9 @@ using NUnit.Framework;
|
||||
using Unity.Netcode.Components;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Physics
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkRigidbody2DDynamicTest : NetworkRigidbody2DTestBase
|
||||
{
|
||||
@@ -16,23 +17,19 @@ namespace Unity.Netcode.RuntimeTests.Physics
|
||||
public override bool Kinematic => true;
|
||||
}
|
||||
|
||||
public abstract class NetworkRigidbody2DTestBase : BaseMultiInstanceTest
|
||||
public abstract class NetworkRigidbody2DTestBase : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 1;
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
public abstract bool Kinematic { get; }
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, playerPrefab =>
|
||||
{
|
||||
playerPrefab.AddComponent<NetworkTransform>();
|
||||
playerPrefab.AddComponent<Rigidbody2D>();
|
||||
playerPrefab.AddComponent<NetworkRigidbody2D>();
|
||||
playerPrefab.GetComponent<Rigidbody2D>().interpolation = RigidbodyInterpolation2D.Interpolate;
|
||||
playerPrefab.GetComponent<Rigidbody2D>().isKinematic = Kinematic;
|
||||
});
|
||||
m_PlayerPrefab.AddComponent<NetworkTransform>();
|
||||
m_PlayerPrefab.AddComponent<Rigidbody2D>();
|
||||
m_PlayerPrefab.AddComponent<NetworkRigidbody2D>();
|
||||
m_PlayerPrefab.GetComponent<Rigidbody2D>().interpolation = RigidbodyInterpolation2D.Interpolate;
|
||||
m_PlayerPrefab.GetComponent<Rigidbody2D>().isKinematic = Kinematic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,19 +40,19 @@ namespace Unity.Netcode.RuntimeTests.Physics
|
||||
public IEnumerator TestRigidbodyKinematicEnableDisable()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult));
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult);
|
||||
var serverPlayer = serverClientPlayerResult.Result.gameObject;
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult);
|
||||
var clientPlayer = clientClientPlayerResult.Result.gameObject;
|
||||
|
||||
Assert.IsNotNull(serverPlayer);
|
||||
Assert.IsNotNull(clientPlayer);
|
||||
|
||||
yield return NetworkRigidbodyTestBase.WaitForFrames(5);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5);
|
||||
|
||||
// server rigidbody has authority and should have a kinematic mode of false
|
||||
Assert.True(serverPlayer.GetComponent<Rigidbody2D>().isKinematic == Kinematic);
|
||||
@@ -68,15 +65,14 @@ namespace Unity.Netcode.RuntimeTests.Physics
|
||||
// despawn the server player, (but keep it around on the server)
|
||||
serverPlayer.GetComponent<NetworkObject>().Despawn(false);
|
||||
|
||||
yield return NetworkRigidbodyTestBase.WaitForFrames(5);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5);
|
||||
|
||||
// This should equal Kinematic
|
||||
Assert.IsTrue(serverPlayer.GetComponent<Rigidbody2D>().isKinematic == Kinematic);
|
||||
|
||||
yield return NetworkRigidbodyTestBase.WaitForFrames(5);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 5);
|
||||
|
||||
Assert.IsTrue(clientPlayer == null); // safety check that object is actually despawned.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ using NUnit.Framework;
|
||||
using Unity.Netcode.Components;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Physics
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkRigidbodyDynamicTest : NetworkRigidbodyTestBase
|
||||
{
|
||||
@@ -16,23 +17,19 @@ namespace Unity.Netcode.RuntimeTests.Physics
|
||||
public override bool Kinematic => true;
|
||||
}
|
||||
|
||||
public abstract class NetworkRigidbodyTestBase : BaseMultiInstanceTest
|
||||
public abstract class NetworkRigidbodyTestBase : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NbClients => 1;
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
public abstract bool Kinematic { get; }
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, playerPrefab =>
|
||||
{
|
||||
playerPrefab.AddComponent<NetworkTransform>();
|
||||
playerPrefab.AddComponent<Rigidbody>();
|
||||
playerPrefab.AddComponent<NetworkRigidbody>();
|
||||
playerPrefab.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
|
||||
playerPrefab.GetComponent<Rigidbody>().isKinematic = Kinematic;
|
||||
});
|
||||
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>
|
||||
@@ -43,44 +40,38 @@ namespace Unity.Netcode.RuntimeTests.Physics
|
||||
public IEnumerator TestRigidbodyKinematicEnableDisable()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult));
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult);
|
||||
var serverPlayer = serverClientPlayerResult.Result.gameObject;
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult);
|
||||
var clientPlayer = clientClientPlayerResult.Result.gameObject;
|
||||
|
||||
Assert.IsNotNull(serverPlayer);
|
||||
Assert.IsNotNull(clientPlayer);
|
||||
Assert.IsNotNull(serverPlayer, "serverPlayer is not null");
|
||||
Assert.IsNotNull(clientPlayer, "clientPlayer is not null");
|
||||
|
||||
yield return WaitForFrames(5);
|
||||
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);
|
||||
Assert.AreEqual(RigidbodyInterpolation.Interpolate, serverPlayer.GetComponent<Rigidbody>().interpolation);
|
||||
Assert.True(serverPlayer.GetComponent<Rigidbody>().isKinematic == Kinematic, "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
|
||||
Assert.True(clientPlayer.GetComponent<Rigidbody>().isKinematic);
|
||||
Assert.AreEqual(RigidbodyInterpolation.None, clientPlayer.GetComponent<Rigidbody>().interpolation);
|
||||
Assert.True(clientPlayer.GetComponent<Rigidbody>().isKinematic, "clientPlayer kinematic");
|
||||
Assert.AreEqual(RigidbodyInterpolation.None, clientPlayer.GetComponent<Rigidbody>().interpolation, "client equal interpolate");
|
||||
|
||||
// despawn the server player (but keep it around on the server)
|
||||
serverPlayer.GetComponent<NetworkObject>().Despawn(false);
|
||||
|
||||
yield return WaitForFrames(5);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);
|
||||
|
||||
Assert.IsTrue(serverPlayer.GetComponent<Rigidbody>().isKinematic == Kinematic);
|
||||
Assert.IsTrue(serverPlayer.GetComponent<Rigidbody>().isKinematic == Kinematic, "serverPlayer second kinematic");
|
||||
|
||||
yield return WaitForFrames(5);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);
|
||||
|
||||
Assert.IsTrue(clientPlayer == null); // safety check that object is actually despawned.
|
||||
}
|
||||
|
||||
public static IEnumerator WaitForFrames(int count)
|
||||
{
|
||||
int nextFrameNumber = Time.frameCount + count;
|
||||
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
|
||||
Assert.IsTrue(clientPlayer == null, "clientPlayer being null"); // safety check that object is actually despawned.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
|
||||
153
Tests/Runtime/RpcManyClientsTests.cs
Normal file
153
Tests/Runtime/RpcManyClientsTests.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class RpcManyClientsObject : NetworkBehaviour
|
||||
{
|
||||
public int Count = 0;
|
||||
public List<ulong> ReceivedFrom = new List<ulong>();
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void ResponseServerRpc(ServerRpcParams rpcParams = default)
|
||||
{
|
||||
ReceivedFrom.Add(rpcParams.Receive.SenderClientId);
|
||||
Count++;
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void NoParamsClientRpc()
|
||||
{
|
||||
ResponseServerRpc();
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void OneParamClientRpc(int value)
|
||||
{
|
||||
ResponseServerRpc();
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void TwoParamsClientRpc(int value1, int value2)
|
||||
{
|
||||
ResponseServerRpc();
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void WithParamsClientRpc(ClientRpcParams param)
|
||||
{
|
||||
ResponseServerRpc();
|
||||
}
|
||||
}
|
||||
|
||||
public class RpcManyClientsTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 10;
|
||||
|
||||
private GameObject m_PrefabToSpawn;
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_PrefabToSpawn = PreparePrefab(typeof(RpcManyClientsObject));
|
||||
}
|
||||
|
||||
public GameObject PreparePrefab(Type type)
|
||||
{
|
||||
var prefabToSpawn = new GameObject();
|
||||
prefabToSpawn.AddComponent(type);
|
||||
var networkObjectPrefab = prefabToSpawn.AddComponent<NetworkObject>();
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObjectPrefab);
|
||||
m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
clientNetworkManager.NetworkConfig.NetworkPrefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn });
|
||||
}
|
||||
return prefabToSpawn;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator RpcManyClientsTest()
|
||||
{
|
||||
var spawnedObject = UnityEngine.Object.Instantiate(m_PrefabToSpawn);
|
||||
var netSpawnedObject = spawnedObject.GetComponent<NetworkObject>();
|
||||
netSpawnedObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
|
||||
netSpawnedObject.Spawn();
|
||||
|
||||
var messageHookList = new List<MessageHookEntry>();
|
||||
var serverMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager);
|
||||
serverMessageHookEntry.AssignMessageType<ServerRpcMessage>();
|
||||
messageHookList.Add(serverMessageHookEntry);
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
var clientMessageHookEntry = new MessageHookEntry(client);
|
||||
clientMessageHookEntry.AssignMessageType<ServerRpcMessage>();
|
||||
messageHookList.Add(clientMessageHookEntry);
|
||||
}
|
||||
var rpcMessageHooks = new MessageHooksConditional(messageHookList);
|
||||
|
||||
var rpcManyClientsObject = netSpawnedObject.GetComponent<RpcManyClientsObject>();
|
||||
|
||||
rpcManyClientsObject.Count = 0;
|
||||
rpcManyClientsObject.NoParamsClientRpc(); // RPC with no params
|
||||
|
||||
// Check that all ServerRpcMessages were sent
|
||||
yield return WaitForConditionOrTimeOut(rpcMessageHooks);
|
||||
|
||||
// Now provide a small window of time to let the server receive and process all messages
|
||||
yield return WaitForConditionOrTimeOut(() => TotalClients == rpcManyClientsObject.Count);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out wait for {nameof(rpcManyClientsObject.NoParamsClientRpc)}! Only {rpcManyClientsObject.Count} of {TotalClients} was received!");
|
||||
|
||||
rpcManyClientsObject.Count = 0;
|
||||
rpcManyClientsObject.OneParamClientRpc(0); // RPC with one param
|
||||
rpcMessageHooks.Reset();
|
||||
yield return WaitForConditionOrTimeOut(rpcMessageHooks);
|
||||
|
||||
// Now provide a small window of time to let the server receive and process all messages
|
||||
yield return WaitForConditionOrTimeOut(() => TotalClients == rpcManyClientsObject.Count);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out wait for {nameof(rpcManyClientsObject.OneParamClientRpc)}! Only {rpcManyClientsObject.Count} of {TotalClients} was received!");
|
||||
|
||||
var param = new ClientRpcParams();
|
||||
|
||||
rpcManyClientsObject.Count = 0;
|
||||
rpcManyClientsObject.TwoParamsClientRpc(0, 0); // RPC with two params
|
||||
|
||||
rpcMessageHooks.Reset();
|
||||
yield return WaitForConditionOrTimeOut(rpcMessageHooks);
|
||||
// Now provide a small window of time to let the server receive and process all messages
|
||||
yield return WaitForConditionOrTimeOut(() => TotalClients == rpcManyClientsObject.Count);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out wait for {nameof(rpcManyClientsObject.TwoParamsClientRpc)}! Only {rpcManyClientsObject.Count} of {TotalClients} was received!");
|
||||
|
||||
rpcManyClientsObject.ReceivedFrom.Clear();
|
||||
rpcManyClientsObject.Count = 0;
|
||||
var target = new List<ulong> { m_ClientNetworkManagers[1].LocalClientId, m_ClientNetworkManagers[2].LocalClientId };
|
||||
param.Send.TargetClientIds = target;
|
||||
rpcManyClientsObject.WithParamsClientRpc(param);
|
||||
|
||||
messageHookList.Clear();
|
||||
var targetedClientMessageHookEntry = new MessageHookEntry(m_ClientNetworkManagers[1]);
|
||||
targetedClientMessageHookEntry.AssignMessageType<ServerRpcMessage>();
|
||||
messageHookList.Add(targetedClientMessageHookEntry);
|
||||
targetedClientMessageHookEntry = new MessageHookEntry(m_ClientNetworkManagers[2]);
|
||||
targetedClientMessageHookEntry.AssignMessageType<ServerRpcMessage>();
|
||||
messageHookList.Add(targetedClientMessageHookEntry);
|
||||
rpcMessageHooks = new MessageHooksConditional(messageHookList);
|
||||
|
||||
yield return WaitForConditionOrTimeOut(rpcMessageHooks);
|
||||
|
||||
// Now provide a small window of time to let the server receive and process all messages
|
||||
yield return WaitForConditionOrTimeOut(() => 2 == rpcManyClientsObject.Count);
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out wait for {nameof(rpcManyClientsObject.TwoParamsClientRpc)}! Only {rpcManyClientsObject.Count} of 2 was received!");
|
||||
|
||||
// either of the 2 selected clients can reply to the server first, due to network timing
|
||||
var possibility1 = new List<ulong> { m_ClientNetworkManagers[1].LocalClientId, m_ClientNetworkManagers[2].LocalClientId };
|
||||
var possibility2 = new List<ulong> { m_ClientNetworkManagers[2].LocalClientId, m_ClientNetworkManagers[1].LocalClientId };
|
||||
Debug.Assert(Enumerable.SequenceEqual(rpcManyClientsObject.ReceivedFrom, possibility1) || Enumerable.SequenceEqual(rpcManyClientsObject.ReceivedFrom, possibility2));
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Runtime/RpcManyClientsTests.cs.meta
Normal file
11
Tests/Runtime/RpcManyClientsTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fc23d25ed71f46ecadbff65a20522c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class RpcTests : BaseMultiInstanceTest
|
||||
public class RpcTests : NetcodeIntegrationTest
|
||||
{
|
||||
public class RpcTestNB : NetworkBehaviour
|
||||
{
|
||||
@@ -26,54 +28,47 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
}
|
||||
|
||||
protected override int NbClients => 1;
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
[UnitySetUp]
|
||||
public override IEnumerator Setup()
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
yield return StartSomeClientsAndServerWithPlayers(true, NbClients, playerPrefab =>
|
||||
{
|
||||
playerPrefab.AddComponent<RpcTestNB>();
|
||||
});
|
||||
m_PlayerPrefab.AddComponent<RpcTestNB>();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestRpcs()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
var clientId = m_ClientNetworkManagers[0].LocalClientId;
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clientId), m_ServerNetworkManager, serverClientPlayerResult));
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component
|
||||
var serverClientRpcTestNB = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent<RpcTestNB>();
|
||||
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER*
|
||||
var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper<NetworkObject>();
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clientId), m_ClientNetworkManagers[0], clientClientPlayerResult));
|
||||
// This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component
|
||||
var localClienRpcTestNB = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent<RpcTestNB>();
|
||||
|
||||
// Setup state
|
||||
bool hasReceivedServerRpc = false;
|
||||
bool hasReceivedClientRpcRemotely = false;
|
||||
bool hasReceivedClientRpcLocally = false;
|
||||
|
||||
clientClientPlayerResult.Result.GetComponent<RpcTestNB>().OnClient_Rpc += () =>
|
||||
localClienRpcTestNB.OnClient_Rpc += () =>
|
||||
{
|
||||
Debug.Log("ClientRpc received on client object");
|
||||
hasReceivedClientRpcRemotely = true;
|
||||
};
|
||||
|
||||
clientClientPlayerResult.Result.GetComponent<RpcTestNB>().OnServer_Rpc += (clientId, param) =>
|
||||
localClienRpcTestNB.OnServer_Rpc += (clientId, param) =>
|
||||
{
|
||||
// The RPC invoked locally. (Weaver failure?)
|
||||
Assert.Fail("ServerRpc invoked locally. Weaver failure?");
|
||||
};
|
||||
|
||||
serverClientPlayerResult.Result.GetComponent<RpcTestNB>().OnServer_Rpc += (clientId, param) =>
|
||||
serverClientRpcTestNB.OnServer_Rpc += (clientId, param) =>
|
||||
{
|
||||
Debug.Log("ServerRpc received on server object");
|
||||
Assert.True(param.Receive.SenderClientId == clientId);
|
||||
hasReceivedServerRpc = true;
|
||||
};
|
||||
|
||||
serverClientPlayerResult.Result.GetComponent<RpcTestNB>().OnClient_Rpc += () =>
|
||||
serverClientRpcTestNB.OnClient_Rpc += () =>
|
||||
{
|
||||
// The RPC invoked locally. (Weaver failure?)
|
||||
Debug.Log("ClientRpc received on server object");
|
||||
@@ -81,13 +76,28 @@ namespace Unity.Netcode.RuntimeTests
|
||||
};
|
||||
|
||||
// Send ServerRpc
|
||||
clientClientPlayerResult.Result.GetComponent<RpcTestNB>().MyServerRpc(clientId);
|
||||
localClienRpcTestNB.MyServerRpc(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
// Send ClientRpc
|
||||
serverClientPlayerResult.Result.GetComponent<RpcTestNB>().MyClientRpc();
|
||||
serverClientRpcTestNB.MyClientRpc();
|
||||
|
||||
// Wait for RPCs to be received
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForCondition(() => hasReceivedServerRpc && hasReceivedClientRpcLocally && hasReceivedClientRpcRemotely));
|
||||
// Validate each NetworkManager relative MessagingSystem received each respective RPC
|
||||
var messageHookList = new List<MessageHookEntry>();
|
||||
var serverMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager);
|
||||
serverMessageHookEntry.AssignMessageType<ServerRpcMessage>();
|
||||
messageHookList.Add(serverMessageHookEntry);
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
var clientMessageHookEntry = new MessageHookEntry(client);
|
||||
clientMessageHookEntry.AssignMessageType<ClientRpcMessage>();
|
||||
messageHookList.Add(clientMessageHookEntry);
|
||||
}
|
||||
var rpcMessageHooks = new MessageHooksConditional(messageHookList);
|
||||
yield return WaitForConditionOrTimeOut(rpcMessageHooks);
|
||||
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);
|
||||
|
||||
Assert.True(hasReceivedServerRpc, "ServerRpc was not received");
|
||||
Assert.True(hasReceivedClientRpcLocally, "ClientRpc was not locally received on the server");
|
||||
|
||||
@@ -3,8 +3,9 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Serialization
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests to test:
|
||||
|
||||
@@ -4,9 +4,10 @@ using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests.Serialization
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests to test:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class StartStopTests
|
||||
{
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -10,7 +11,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator WhenShuttingDownAndRestarting_SDKRestartsSuccessfullyAndStaysRunning()
|
||||
{ // create server and client instances
|
||||
MultiInstanceHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
|
||||
NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -19,7 +20,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var gameObject = new GameObject("PlayerObject");
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
networkObject.DontDestroyWithOwner = true;
|
||||
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
|
||||
|
||||
server.NetworkConfig.PlayerPrefab = gameObject;
|
||||
|
||||
@@ -29,13 +30,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
|
||||
// start server and connect clients
|
||||
MultiInstanceHelpers.Start(false, server, clients);
|
||||
NetcodeIntegrationTestHelpers.Start(false, server, clients);
|
||||
|
||||
// wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients);
|
||||
|
||||
// wait for connection on server side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(server));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(server);
|
||||
|
||||
// shutdown the server
|
||||
server.Shutdown();
|
||||
@@ -66,7 +67,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
finally
|
||||
{
|
||||
// cleanup
|
||||
MultiInstanceHelpers.Destroy();
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -41,13 +42,35 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
var tickSystem = NetworkManager.Singleton.NetworkTickSystem;
|
||||
var delta = tickSystem.LocalTime.FixedDeltaTime;
|
||||
var previous_localTickCalculated = 0;
|
||||
var previous_serverTickCalculated = 0;
|
||||
|
||||
while (tickSystem.LocalTime.Time < 3f)
|
||||
{
|
||||
yield return null;
|
||||
Assert.AreEqual(Mathf.FloorToInt((tickSystem.LocalTime.TimeAsFloat / delta)), NetworkManager.Singleton.LocalTime.Tick);
|
||||
Assert.AreEqual(Mathf.FloorToInt((tickSystem.ServerTime.TimeAsFloat / delta)), NetworkManager.Singleton.ServerTime.Tick);
|
||||
Assert.True(Mathf.Approximately((float)NetworkManager.Singleton.LocalTime.Time, (float)NetworkManager.Singleton.ServerTime.Time));
|
||||
|
||||
var tickCalculated = tickSystem.LocalTime.Time / delta;
|
||||
previous_localTickCalculated = (int)tickCalculated;
|
||||
|
||||
// This check is needed due to double division imprecision of large numbers
|
||||
if ((tickCalculated - previous_localTickCalculated) >= 0.999999999999)
|
||||
{
|
||||
previous_localTickCalculated++;
|
||||
}
|
||||
|
||||
|
||||
tickCalculated = NetworkManager.Singleton.ServerTime.Time / delta;
|
||||
previous_serverTickCalculated = (int)tickCalculated;
|
||||
|
||||
// This check is needed due to double division imprecision of large numbers
|
||||
if ((tickCalculated - previous_serverTickCalculated) >= 0.999999999999)
|
||||
{
|
||||
previous_serverTickCalculated++;
|
||||
}
|
||||
|
||||
Assert.AreEqual(previous_localTickCalculated, NetworkManager.Singleton.LocalTime.Tick, $"Calculated local tick {previous_localTickCalculated} does not match local tick {NetworkManager.Singleton.LocalTime.Tick}!");
|
||||
Assert.AreEqual(previous_serverTickCalculated, NetworkManager.Singleton.ServerTime.Tick, $"Calculated server tick {previous_serverTickCalculated} does not match server tick {NetworkManager.Singleton.ServerTime.Tick}!");
|
||||
Assert.True(Mathf.Approximately((float)NetworkManager.Singleton.LocalTime.Time, (float)NetworkManager.Singleton.ServerTime.Time), $"Local time {(float)NetworkManager.Singleton.LocalTime.Time} is not approximately server time {(float)NetworkManager.Singleton.ServerTime.Time}!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
@@ -18,14 +19,14 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator TestClientTimeInitializationOnConnect([Values(0, 1f)] float serverStartDelay, [Values(0, 1f)] float clientStartDelay, [Values(true, false)] bool isHost)
|
||||
{
|
||||
// Create multiple NetworkManager instances
|
||||
if (!MultiInstanceHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients, 30))
|
||||
if (!NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients, 30))
|
||||
{
|
||||
Debug.LogError("Failed to create instances");
|
||||
Assert.Fail("Failed to create instances");
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(serverStartDelay);
|
||||
MultiInstanceHelpers.Start(false, server, new NetworkManager[] { }, BaseMultiInstanceTest.SceneManagerValidationAndTestRunnerInitialization); // passing no clients on purpose to start them manually later
|
||||
NetcodeIntegrationTestHelpers.Start(false, server, new NetworkManager[] { }); // passing no clients on purpose to start them manually later
|
||||
|
||||
// 0 ticks should have passed
|
||||
var serverTick = server.NetworkTickSystem.ServerTime.Tick;
|
||||
@@ -34,9 +35,11 @@ namespace Unity.Netcode.RuntimeTests
|
||||
// server time should be 0
|
||||
Assert.AreEqual(0, server.NetworkTickSystem.ServerTime.Time);
|
||||
|
||||
// wait 2 frames to ensure network tick is run
|
||||
yield return null;
|
||||
yield return null;
|
||||
// wait until at least more than 2 server ticks have passed
|
||||
// Note: Waiting for more than 2 ticks on the server is due
|
||||
// to the time system applying buffering to the received time
|
||||
// in NetworkTimeSystem.Sync
|
||||
yield return new WaitUntil(() => server.NetworkTickSystem.ServerTime.Tick > 2);
|
||||
|
||||
var serverTimePassed = server.NetworkTickSystem.ServerTime.Time;
|
||||
var expectedServerTickCount = Mathf.FloorToInt((float)(serverTimePassed * 30));
|
||||
@@ -56,16 +59,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var clientStartRealTime = Time.time;
|
||||
|
||||
m_Client.StartClient();
|
||||
BaseMultiInstanceTest.SceneManagerValidationAndTestRunnerInitialization(clients[0]);
|
||||
NetcodeIntegrationTestHelpers.RegisterHandlers(clients[0]);
|
||||
|
||||
m_Client.NetworkTickSystem.Tick += NetworkTickSystemOnTick;
|
||||
m_ClientTickCounter = 0;
|
||||
|
||||
|
||||
// don't check for anything here and assume non-async connection.
|
||||
|
||||
// Wait for connection on client side
|
||||
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients);
|
||||
|
||||
var clientStartRealTimeDuration = Time.time - clientStartRealTime;
|
||||
var clientStartRealTickDuration = Mathf.FloorToInt(clientStartRealTimeDuration * 30);
|
||||
@@ -75,7 +75,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
Assert.True(m_ClientTickCounter <= clientStartRealTickDuration);
|
||||
|
||||
MultiInstanceHelpers.Destroy();
|
||||
yield return null;
|
||||
}
|
||||
|
||||
@@ -95,7 +94,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTearDown]
|
||||
public virtual IEnumerator Teardown()
|
||||
{
|
||||
MultiInstanceHelpers.Destroy();
|
||||
NetcodeIntegrationTestHelpers.Destroy();
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user