com.unity.netcode.gameobjects@2.0.0-pre.4
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). ## [2.0.0-pre.4] - 2024-08-21 ### Added - Added `NetworkVariable.CheckDirtyState` that is to be used in tandem with collections in order to detect whether the collection or an item within the collection has changed. (#3004) ### Fixed - Fixed issue where nested `NetworkTransform` components were not getting updated. (#3016) - Fixed issue by adding null checks in `NetworkVariableBase.CanClientRead` and `NetworkVariableBase.CanClientWrite` methods to ensure safe access to `NetworkBehaviour`. (#3012) - Fixed issue where `FixedStringSerializer<T>` was using `NetworkVariableSerialization<byte>.AreEqual` to determine if two bytes were equal causes an exception to be thrown due to no byte serializer having been defined. (#3009) - Fixed Issue where a state with dual triggers, inbound and outbound, could cause a false layer to layer state transition message to be sent to non-authority `NetworkAnimator` instances and cause a warning message to be logged. (#3008) - Fixed issue using collections within `NetworkVariable` where the collection would not detect changes to items or nested items. (#3004) - Fixed issue where `List`, `Dictionary`, and `HashSet` collections would not uniquely duplicate nested collections. (#3004) - Fixed issue where `NotAuthorityTarget` would include the service observer in the list of targets to send the RPC to as opposed to excluding the service observer as it should. (#3000) - Fixed issue where `ProxyRpcTargetGroup` could attempt to send a message if there were no targets to send to. (#3000) ### Changed - Changed `NetworkAnimator` to automatically switch to owner authoritative mode when using a distributed authority network topology. (#3021) - Changed permissions exception thrown in `NetworkList` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3004) - Changed permissions exception thrown in `NetworkVariable.Value` to exiting early with a logged error that is now a unified permissions message within `NetworkVariableBase`. (#3004)
This commit is contained in:
182
Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs
Normal file
182
Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
[TestFixture(HostOrServer.DAHost)]
|
||||
[TestFixture(HostOrServer.Host)]
|
||||
internal class NetworkVarBufferCopyTest : NetcodeIntegrationTest
|
||||
{
|
||||
internal class DummyNetVar : NetworkVariableBase
|
||||
{
|
||||
private const int k_DummyValue = 0x13579BDF;
|
||||
public bool DeltaWritten;
|
||||
public bool FieldWritten;
|
||||
public bool DeltaRead;
|
||||
public bool FieldRead;
|
||||
|
||||
public override void WriteDelta(FastBufferWriter writer)
|
||||
{
|
||||
writer.TryBeginWrite(FastBufferWriter.GetWriteSize(k_DummyValue) + 1);
|
||||
using (var bitWriter = writer.EnterBitwiseContext())
|
||||
{
|
||||
bitWriter.WriteBits(1, 1);
|
||||
}
|
||||
writer.WriteValue(k_DummyValue);
|
||||
|
||||
DeltaWritten = true;
|
||||
}
|
||||
|
||||
public override void WriteField(FastBufferWriter writer)
|
||||
{
|
||||
writer.TryBeginWrite(FastBufferWriter.GetWriteSize(k_DummyValue) + 1);
|
||||
using (var bitWriter = writer.EnterBitwiseContext())
|
||||
{
|
||||
bitWriter.WriteBits(1, 1);
|
||||
}
|
||||
writer.WriteValue(k_DummyValue);
|
||||
|
||||
FieldWritten = true;
|
||||
}
|
||||
|
||||
public override void ReadField(FastBufferReader reader)
|
||||
{
|
||||
reader.TryBeginRead(FastBufferWriter.GetWriteSize(k_DummyValue) + 1);
|
||||
using (var bitReader = reader.EnterBitwiseContext())
|
||||
{
|
||||
bitReader.ReadBits(out byte b, 1);
|
||||
}
|
||||
|
||||
reader.ReadValue(out int i);
|
||||
Assert.AreEqual(k_DummyValue, i);
|
||||
|
||||
FieldRead = true;
|
||||
}
|
||||
|
||||
public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
|
||||
{
|
||||
reader.TryBeginRead(FastBufferWriter.GetWriteSize(k_DummyValue) + 1);
|
||||
using (var bitReader = reader.EnterBitwiseContext())
|
||||
{
|
||||
bitReader.ReadBits(out byte b, 1);
|
||||
}
|
||||
|
||||
reader.ReadValue(out int i);
|
||||
Assert.AreEqual(k_DummyValue, i);
|
||||
|
||||
DeltaRead = true;
|
||||
}
|
||||
|
||||
public DummyNetVar(
|
||||
NetworkVariableReadPermission readPerm = DefaultReadPerm,
|
||||
NetworkVariableWritePermission writePerm = DefaultWritePerm) : base(readPerm, writePerm) { }
|
||||
}
|
||||
|
||||
internal class DummyNetBehaviour : NetworkBehaviour
|
||||
{
|
||||
public static bool DistributedAuthority;
|
||||
public DummyNetVar NetVar;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (DistributedAuthority)
|
||||
{
|
||||
NetVar = new DummyNetVar(writePerm: NetworkVariableWritePermission.Owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
NetVar = new DummyNetVar();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if ((NetworkManager.DistributedAuthorityMode && !IsOwner) || (!NetworkManager.DistributedAuthorityMode && !IsServer))
|
||||
{
|
||||
ClientDummyNetBehaviourSpawned(this);
|
||||
}
|
||||
base.OnNetworkSpawn();
|
||||
}
|
||||
}
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
public NetworkVarBufferCopyTest(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||
|
||||
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()
|
||||
{
|
||||
DummyNetBehaviour.DistributedAuthority = m_DistributedAuthority;
|
||||
m_PlayerPrefab.AddComponent<DummyNetBehaviour>();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestEntireBufferIsCopiedOnNetworkVariableDelta()
|
||||
{
|
||||
// This is the *SERVER VERSION* of the *CLIENT PLAYER*
|
||||
var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper<NetworkObject>();
|
||||
yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(
|
||||
x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId,
|
||||
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>();
|
||||
|
||||
// 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!");
|
||||
|
||||
// Check that FieldWritten is written when dirty
|
||||
var authorityComponent = m_DistributedAuthority ? clientComponent : serverComponent;
|
||||
var nonAuthorityComponent = m_DistributedAuthority ? serverComponent : clientComponent;
|
||||
authorityComponent.NetVar.SetDirty(true);
|
||||
yield return s_DefaultWaitForTick;
|
||||
Assert.True(authorityComponent.NetVar.FieldWritten);
|
||||
// Check that DeltaWritten is written when dirty
|
||||
authorityComponent.NetVar.SetDirty(true);
|
||||
yield return s_DefaultWaitForTick;
|
||||
Assert.True(authorityComponent.NetVar.DeltaWritten);
|
||||
|
||||
|
||||
// Check that both FieldRead and DeltaRead were invoked on the client side
|
||||
yield return WaitForConditionOrTimeOut(() => nonAuthorityComponent.NetVar.FieldRead == true && nonAuthorityComponent.NetVar.DeltaRead == true);
|
||||
|
||||
var timedOutMessage = "Timed out waiting for client reads: ";
|
||||
if (s_GlobalTimeoutHelper.TimedOut)
|
||||
{
|
||||
if (!nonAuthorityComponent.NetVar.FieldRead)
|
||||
{
|
||||
timedOutMessage += "[FieldRead]";
|
||||
}
|
||||
|
||||
if (!nonAuthorityComponent.NetVar.DeltaRead)
|
||||
{
|
||||
timedOutMessage += "[DeltaRead]";
|
||||
}
|
||||
}
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, timedOutMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7d44caa76a64b02978f5aca0e7b576a
|
||||
timeCreated: 1627926008
|
||||
@@ -0,0 +1,420 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
internal class NetworkVariableAnticipationComponent : NetworkBehaviour
|
||||
{
|
||||
public AnticipatedNetworkVariable<int> SnapOnAnticipationFailVariable = new AnticipatedNetworkVariable<int>(0, StaleDataHandling.Ignore);
|
||||
public AnticipatedNetworkVariable<float> SmoothOnAnticipationFailVariable = new AnticipatedNetworkVariable<float>(0, StaleDataHandling.Reanticipate);
|
||||
public AnticipatedNetworkVariable<float> ReanticipateOnAnticipationFailVariable = new AnticipatedNetworkVariable<float>(0, StaleDataHandling.Reanticipate);
|
||||
|
||||
public override void OnReanticipate(double lastRoundTripTime)
|
||||
{
|
||||
if (SmoothOnAnticipationFailVariable.ShouldReanticipate)
|
||||
{
|
||||
if (Mathf.Abs(SmoothOnAnticipationFailVariable.AuthoritativeValue - SmoothOnAnticipationFailVariable.PreviousAnticipatedValue) > Mathf.Epsilon)
|
||||
{
|
||||
SmoothOnAnticipationFailVariable.Smooth(SmoothOnAnticipationFailVariable.PreviousAnticipatedValue, SmoothOnAnticipationFailVariable.AuthoritativeValue, 1, Mathf.Lerp);
|
||||
}
|
||||
}
|
||||
|
||||
if (ReanticipateOnAnticipationFailVariable.ShouldReanticipate)
|
||||
{
|
||||
// Would love to test some stuff about anticipation based on time, but that is difficult to test accurately.
|
||||
// This reanticipating variable will just always anticipate a value 5 higher than the server value.
|
||||
ReanticipateOnAnticipationFailVariable.Anticipate(ReanticipateOnAnticipationFailVariable.AuthoritativeValue + 5);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SnapRpcResponseReceived = false;
|
||||
|
||||
[Rpc(SendTo.Server)]
|
||||
public void SetSnapValueRpc(int i, RpcParams rpcParams = default)
|
||||
{
|
||||
SnapOnAnticipationFailVariable.AuthoritativeValue = i;
|
||||
SetSnapValueResponseRpc(RpcTarget.Single(rpcParams.Receive.SenderClientId, RpcTargetUse.Temp));
|
||||
}
|
||||
|
||||
[Rpc(SendTo.SpecifiedInParams)]
|
||||
public void SetSnapValueResponseRpc(RpcParams rpcParams)
|
||||
{
|
||||
SnapRpcResponseReceived = true;
|
||||
}
|
||||
|
||||
[Rpc(SendTo.Server)]
|
||||
public void SetSmoothValueRpc(float f)
|
||||
{
|
||||
SmoothOnAnticipationFailVariable.AuthoritativeValue = f;
|
||||
}
|
||||
|
||||
[Rpc(SendTo.Server)]
|
||||
public void SetReanticipateValueRpc(float f)
|
||||
{
|
||||
ReanticipateOnAnticipationFailVariable.AuthoritativeValue = f;
|
||||
}
|
||||
}
|
||||
|
||||
internal class NetworkVariableAnticipationTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
protected override bool m_EnableTimeTravel => true;
|
||||
protected override bool m_SetupIsACoroutine => false;
|
||||
protected override bool m_TearDownIsACoroutine => false;
|
||||
|
||||
protected override void OnPlayerPrefabGameObjectCreated()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<NetworkVariableAnticipationComponent>();
|
||||
}
|
||||
|
||||
public NetworkVariableAnticipationComponent GetTestComponent()
|
||||
{
|
||||
return m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent<NetworkVariableAnticipationComponent>();
|
||||
}
|
||||
|
||||
public NetworkVariableAnticipationComponent GetServerComponent()
|
||||
{
|
||||
foreach (var obj in Object.FindObjectsByType<NetworkVariableAnticipationComponent>(FindObjectsSortMode.None))
|
||||
{
|
||||
if (obj.NetworkManager == m_ServerNetworkManager && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public NetworkVariableAnticipationComponent GetOtherClientComponent()
|
||||
{
|
||||
foreach (var obj in Object.FindObjectsByType<NetworkVariableAnticipationComponent>(FindObjectsSortMode.None))
|
||||
{
|
||||
if (obj.NetworkManager == m_ClientNetworkManagers[1] && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnticipating_ValueChangesImmediately()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
testComponent.SmoothOnAnticipationFailVariable.Anticipate(15);
|
||||
testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20);
|
||||
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(15, testComponent.SmoothOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, testComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnticipating_AuthoritativeValueDoesNotChange()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
testComponent.SmoothOnAnticipationFailVariable.Anticipate(15);
|
||||
testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20);
|
||||
|
||||
Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnticipating_ServerDoesNotChange()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
testComponent.SmoothOnAnticipationFailVariable.Anticipate(15);
|
||||
testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20);
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
|
||||
Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
|
||||
TimeTravel(2, 120);
|
||||
|
||||
Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAnticipating_OtherClientDoesNotChange()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
testComponent.SmoothOnAnticipationFailVariable.Anticipate(15);
|
||||
testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20);
|
||||
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
|
||||
Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
|
||||
TimeTravel(2, 120);
|
||||
|
||||
Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenServerChangesSnapValue_ValuesAreUpdated()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
testComponent.SetSnapValueRpc(10);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<RpcMessage>(
|
||||
new List<NetworkManager> { m_ServerNetworkManager }
|
||||
);
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
Assert.AreEqual(10, serverComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(10, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<NetworkVariableDeltaMessage>(m_ClientNetworkManagers.ToList());
|
||||
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
Assert.AreEqual(10, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(10, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenServerChangesSmoothValue_ValuesAreLerped()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.SmoothOnAnticipationFailVariable.Anticipate(15);
|
||||
|
||||
Assert.AreEqual(15, testComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(0, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
// Set to a different value to simulate a anticipation failure - will lerp between the anticipated value
|
||||
// and the actual one
|
||||
testComponent.SetSmoothValueRpc(20);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<RpcMessage>(
|
||||
new List<NetworkManager> { m_ServerNetworkManager }
|
||||
);
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
Assert.AreEqual(20, serverComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, serverComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<NetworkVariableDeltaMessage>(m_ClientNetworkManagers.ToList());
|
||||
|
||||
Assert.AreEqual(15 + 1f / 60f * 5, testComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
Assert.AreEqual(0 + 1f / 60f * 20, otherClientComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
for (var i = 1; i < 60; ++i)
|
||||
{
|
||||
TimeTravel(1f / 60f, 1);
|
||||
|
||||
Assert.AreEqual(15 + 1f / 60f * 5 * (i + 1), testComponent.SmoothOnAnticipationFailVariable.Value, 0.00001);
|
||||
Assert.AreEqual(20, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
Assert.AreEqual(0 + 1f / 60f * 20 * (i + 1), otherClientComponent.SmoothOnAnticipationFailVariable.Value, 0.00001);
|
||||
Assert.AreEqual(20, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
}
|
||||
TimeTravel(1f / 60f, 1);
|
||||
Assert.AreEqual(20, testComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, otherClientComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenServerChangesReanticipateValue_ValuesAreReanticipated()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
|
||||
testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(15);
|
||||
|
||||
Assert.AreEqual(15, testComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(0, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
// Set to a different value to simulate a anticipation failure - will lerp between the anticipated value
|
||||
// and the actual one
|
||||
testComponent.SetReanticipateValueRpc(20);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<RpcMessage>(
|
||||
new List<NetworkManager> { m_ServerNetworkManager }
|
||||
);
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<NetworkVariableDeltaMessage>(m_ClientNetworkManagers.ToList());
|
||||
|
||||
Assert.AreEqual(25, testComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
|
||||
Assert.AreEqual(25, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon);
|
||||
Assert.AreEqual(20, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNonStaleDataArrivesToIgnoreVariable_ItIsNotIgnored([Values(10u, 30u, 60u)] uint tickRate, [Values(0u, 1u, 2u)] uint skipFrames)
|
||||
{
|
||||
m_ServerNetworkManager.NetworkConfig.TickRate = tickRate;
|
||||
m_ServerNetworkManager.NetworkTickSystem.TickRate = tickRate;
|
||||
|
||||
for (var i = 0; i < skipFrames; ++i)
|
||||
{
|
||||
TimeTravel(1 / 60f, 1);
|
||||
}
|
||||
var testComponent = GetTestComponent();
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
testComponent.SetSnapValueRpc(20);
|
||||
WaitForMessageReceivedWithTimeTravel<RpcMessage>(new List<NetworkManager> { m_ServerNetworkManager });
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
|
||||
Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<NetworkVariableDeltaMessage>(m_ClientNetworkManagers.ToList());
|
||||
|
||||
// Both values get updated
|
||||
Assert.AreEqual(20, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
// Other client got the server value and had made no anticipation, so it applies it to the anticipated value as well.
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenStaleDataArrivesToIgnoreVariable_ItIsIgnored([Values(10u, 30u, 60u)] uint tickRate, [Values(0u, 1u, 2u)] uint skipFrames)
|
||||
{
|
||||
m_ServerNetworkManager.NetworkConfig.TickRate = tickRate;
|
||||
m_ServerNetworkManager.NetworkTickSystem.TickRate = tickRate;
|
||||
|
||||
for (var i = 0; i < skipFrames; ++i)
|
||||
{
|
||||
TimeTravel(1 / 60f, 1);
|
||||
}
|
||||
var testComponent = GetTestComponent();
|
||||
testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
|
||||
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
testComponent.SetSnapValueRpc(30);
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue = 20;
|
||||
|
||||
Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<NetworkVariableDeltaMessage>(m_ClientNetworkManagers.ToList());
|
||||
|
||||
if (testComponent.SnapRpcResponseReceived)
|
||||
{
|
||||
// In this case the tick rate is slow enough that the RPC was received and processed, so we check that.
|
||||
Assert.AreEqual(30, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(30, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(30, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(30, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In this case, we got an update before the RPC was processed, so we should have ignored it.
|
||||
// Anticipated client received this data for a tick earlier than its anticipation, and should have prioritized the anticipated value
|
||||
Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value);
|
||||
// However, the authoritative value still gets updated
|
||||
Assert.AreEqual(20, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
// Other client got the server value and had made no anticipation, so it applies it to the anticipated value as well.
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenStaleDataArrivesToReanticipatedVariable_ItIsAppliedAndReanticipated()
|
||||
{
|
||||
var testComponent = GetTestComponent();
|
||||
testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(10);
|
||||
|
||||
Assert.AreEqual(10, testComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(0, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
var serverComponent = GetServerComponent();
|
||||
serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue = 20;
|
||||
|
||||
Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
WaitForMessageReceivedWithTimeTravel<NetworkVariableDeltaMessage>(m_ClientNetworkManagers.ToList());
|
||||
|
||||
Assert.AreEqual(25, testComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
// However, the authoritative value still gets updated
|
||||
Assert.AreEqual(20, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
|
||||
// Other client got the server value and had made no anticipation, so it applies it to the anticipated value as well.
|
||||
var otherClientComponent = GetOtherClientComponent();
|
||||
Assert.AreEqual(25, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value);
|
||||
Assert.AreEqual(20, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74e627a9d18dcd04e9c56ab2539a6593
|
||||
2994
Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs
Normal file
2994
Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d01969a8bbbd7146a24490a5190ea7e
|
||||
165
Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs
Normal file
165
Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
#if !NGO_MINIMALPROJECT
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
[TestFixtureSource(nameof(TestDataSource))]
|
||||
internal class NetworkVariableInheritanceTests : NetcodeIntegrationTest
|
||||
{
|
||||
public NetworkVariableInheritanceTests(HostOrServer hostOrServer)
|
||||
: base(hostOrServer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
public static IEnumerable<TestFixtureData> TestDataSource() =>
|
||||
Enum.GetValues(typeof(HostOrServer)).OfType<HostOrServer>().Select(x => new TestFixtureData(x));
|
||||
|
||||
internal class ComponentA : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<int> PublicFieldA = new NetworkVariable<int>(1);
|
||||
protected NetworkVariable<int> m_ProtectedFieldA = new NetworkVariable<int>(2);
|
||||
private NetworkVariable<int> m_PrivateFieldA = new NetworkVariable<int>(3);
|
||||
|
||||
public void ChangeValuesA(int pub, int pro, int pri)
|
||||
{
|
||||
PublicFieldA.Value = pub;
|
||||
m_ProtectedFieldA.Value = pro;
|
||||
m_PrivateFieldA.Value = pri;
|
||||
}
|
||||
|
||||
public bool CompareValuesA(ComponentA other)
|
||||
{
|
||||
return PublicFieldA.Value == other.PublicFieldA.Value &&
|
||||
m_ProtectedFieldA.Value == other.m_ProtectedFieldA.Value &&
|
||||
m_PrivateFieldA.Value == other.m_PrivateFieldA.Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ComponentB : ComponentA
|
||||
{
|
||||
public NetworkVariable<int> PublicFieldB = new NetworkVariable<int>(11);
|
||||
protected NetworkVariable<int> m_ProtectedFieldB = new NetworkVariable<int>(22);
|
||||
private NetworkVariable<int> m_PrivateFieldB = new NetworkVariable<int>(33);
|
||||
|
||||
public void ChangeValuesB(int pub, int pro, int pri)
|
||||
{
|
||||
PublicFieldB.Value = pub;
|
||||
m_ProtectedFieldB.Value = pro;
|
||||
m_PrivateFieldB.Value = pri;
|
||||
}
|
||||
|
||||
public bool CompareValuesB(ComponentB other)
|
||||
{
|
||||
return PublicFieldB.Value == other.PublicFieldB.Value &&
|
||||
m_ProtectedFieldB.Value == other.m_ProtectedFieldB.Value &&
|
||||
m_PrivateFieldB.Value == other.m_PrivateFieldB.Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ComponentC : ComponentB
|
||||
{
|
||||
public NetworkVariable<int> PublicFieldC = new NetworkVariable<int>(111);
|
||||
protected NetworkVariable<int> m_ProtectedFieldC = new NetworkVariable<int>(222);
|
||||
private NetworkVariable<int> m_PrivateFieldC = new NetworkVariable<int>(333);
|
||||
|
||||
public void ChangeValuesC(int pub, int pro, int pri)
|
||||
{
|
||||
PublicFieldC.Value = pub;
|
||||
m_ProtectedFieldA.Value = pro;
|
||||
m_PrivateFieldC.Value = pri;
|
||||
}
|
||||
|
||||
public bool CompareValuesC(ComponentC other)
|
||||
{
|
||||
return PublicFieldC.Value == other.PublicFieldC.Value &&
|
||||
m_ProtectedFieldC.Value == other.m_ProtectedFieldC.Value &&
|
||||
m_PrivateFieldC.Value == other.m_PrivateFieldC.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject m_TestObjectPrefab;
|
||||
private ulong m_TestObjectId = 0;
|
||||
|
||||
protected override void OnOneTimeSetup()
|
||||
{
|
||||
NetworkVariableBase.IgnoreInitializeWarning = true;
|
||||
base.OnOneTimeSetup();
|
||||
}
|
||||
|
||||
protected override void OnOneTimeTearDown()
|
||||
{
|
||||
NetworkVariableBase.IgnoreInitializeWarning = false;
|
||||
base.OnOneTimeTearDown();
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_TestObjectPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableInheritanceTests)}.{nameof(m_TestObjectPrefab)}]");
|
||||
m_TestObjectPrefab.AddComponent<ComponentA>();
|
||||
m_TestObjectPrefab.AddComponent<ComponentB>();
|
||||
m_TestObjectPrefab.AddComponent<ComponentC>();
|
||||
}
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
var serverTestObject = SpawnObject(m_TestObjectPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>();
|
||||
m_TestObjectId = serverTestObject.NetworkObjectId;
|
||||
|
||||
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
|
||||
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
|
||||
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
|
||||
|
||||
serverTestComponentA.ChangeValuesA(1000, 2000, 3000);
|
||||
serverTestComponentB.ChangeValuesA(1000, 2000, 3000);
|
||||
serverTestComponentB.ChangeValuesB(1100, 2200, 3300);
|
||||
serverTestComponentC.ChangeValuesA(1000, 2000, 3000);
|
||||
serverTestComponentC.ChangeValuesB(1100, 2200, 3300);
|
||||
serverTestComponentC.ChangeValuesC(1110, 2220, 3330);
|
||||
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||
}
|
||||
|
||||
private bool CheckTestObjectComponentValuesOnAll()
|
||||
{
|
||||
var serverTestObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
|
||||
var serverTestComponentA = serverTestObject.GetComponent<ComponentA>();
|
||||
var serverTestComponentB = serverTestObject.GetComponent<ComponentB>();
|
||||
var serverTestComponentC = serverTestObject.GetComponent<ComponentC>();
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
var clientTestObject = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId];
|
||||
var clientTestComponentA = clientTestObject.GetComponent<ComponentA>();
|
||||
var clientTestComponentB = clientTestObject.GetComponent<ComponentB>();
|
||||
var clientTestComponentC = clientTestObject.GetComponent<ComponentC>();
|
||||
if (!serverTestComponentA.CompareValuesA(clientTestComponentA) ||
|
||||
!serverTestComponentB.CompareValuesA(clientTestComponentB) ||
|
||||
!serverTestComponentB.CompareValuesB(clientTestComponentB) ||
|
||||
!serverTestComponentC.CompareValuesA(clientTestComponentC) ||
|
||||
!serverTestComponentC.CompareValuesB(clientTestComponentC) ||
|
||||
!serverTestComponentC.CompareValuesC(clientTestComponentC))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestInheritedFields()
|
||||
{
|
||||
yield return WaitForConditionOrTimeOut(CheckTestObjectComponentValuesOnAll);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, nameof(CheckTestObjectComponentValuesOnAll));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41d4aef8f33a8eb4e87879075f868e66
|
||||
306
Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs
Normal file
306
Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
#if !NGO_MINIMALPROJECT
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
[TestFixtureSource(nameof(TestDataSource))]
|
||||
internal class NetworkVariablePermissionTests : NetcodeIntegrationTest
|
||||
{
|
||||
public static IEnumerable<TestFixtureData> TestDataSource()
|
||||
{
|
||||
NetworkVariableBase.IgnoreInitializeWarning = true;
|
||||
foreach (HostOrServer hostOrServer in Enum.GetValues(typeof(HostOrServer)))
|
||||
{
|
||||
// DANGO-EXP TODO: Add support for distributed authority mode
|
||||
if (hostOrServer == HostOrServer.DAHost)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
yield return new TestFixtureData(hostOrServer);
|
||||
}
|
||||
|
||||
NetworkVariableBase.IgnoreInitializeWarning = false;
|
||||
}
|
||||
|
||||
protected override int NumberOfClients => 3;
|
||||
|
||||
public NetworkVariablePermissionTests(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||
|
||||
private GameObject m_TestObjPrefab;
|
||||
private ulong m_TestObjId = 0;
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_TestObjPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariablePermissionTests)}.{nameof(m_TestObjPrefab)}]");
|
||||
var testComp = m_TestObjPrefab.AddComponent<NetVarPermTestComp>();
|
||||
}
|
||||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
m_TestObjId = SpawnObject(m_TestObjPrefab, m_ServerNetworkManager).GetComponent<NetworkObject>().NetworkObjectId;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
private IEnumerator WaitForPositionsAreEqual(NetworkVariable<Vector3> netvar, Vector3 expected)
|
||||
{
|
||||
yield return WaitForConditionOrTimeOut(() => netvar.Value == expected);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
||||
}
|
||||
|
||||
private IEnumerator WaitForOwnerWritableAreEqualOnAll()
|
||||
{
|
||||
yield return WaitForConditionOrTimeOut(CheckOwnerWritableAreEqualOnAll);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
||||
}
|
||||
|
||||
private bool CheckOwnerWritableAreEqualOnAll()
|
||||
{
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
if (testObjServer.OwnerClientId != testObjClient.OwnerClientId ||
|
||||
testCompServer.OwnerWritable_Position.Value != testCompClient.OwnerWritable_Position.Value ||
|
||||
testCompServer.OwnerWritable_Position.ReadPerm != testCompClient.OwnerWritable_Position.ReadPerm ||
|
||||
testCompServer.OwnerWritable_Position.WritePerm != testCompClient.OwnerWritable_Position.WritePerm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerator WaitForServerWritableAreEqualOnAll()
|
||||
{
|
||||
yield return WaitForConditionOrTimeOut(CheckServerWritableAreEqualOnAll);
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut);
|
||||
}
|
||||
|
||||
private bool CheckServerWritableAreEqualOnAll()
|
||||
{
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
if (testCompServer.ServerWritable_Position.Value != testCompClient.ServerWritable_Position.Value ||
|
||||
testCompServer.ServerWritable_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm ||
|
||||
testCompServer.ServerWritable_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckOwnerReadWriteAreEqualOnOwnerAndServer()
|
||||
{
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
if (testObjServer.OwnerClientId == testObjClient.OwnerClientId &&
|
||||
testCompServer.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value &&
|
||||
testCompServer.OwnerReadWrite_Position.ReadPerm == testCompClient.ServerWritable_Position.ReadPerm &&
|
||||
testCompServer.OwnerReadWrite_Position.WritePerm == testCompClient.ServerWritable_Position.WritePerm)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(NetVarPermTestComp ownerReadWriteObject)
|
||||
{
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
if (testObjClient.OwnerClientId != ownerReadWriteObject.OwnerClientId ||
|
||||
ownerReadWriteObject.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value ||
|
||||
ownerReadWriteObject.OwnerReadWrite_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm ||
|
||||
ownerReadWriteObject.OwnerReadWrite_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ServerChangesOwnerWritableNetVar()
|
||||
{
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
testCompServer.OwnerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, newValue);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ServerChangesServerWritableNetVar()
|
||||
{
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
var oldValue = testCompServer.ServerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
testCompServer.ServerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue);
|
||||
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ClientChangesOwnerWritableNetVar()
|
||||
{
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
|
||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
var oldValue = testCompClient.OwnerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
testCompClient.OwnerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This tests the scenario where a client owner has both read and write
|
||||
/// permissions set. The server should be the only instance that can read
|
||||
/// the NetworkVariable. ServerCannotChangeOwnerWritableNetVar performs
|
||||
/// the same check to make sure the server cannot write to a client owner
|
||||
/// NetworkVariable with owner write permissions.
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator ClientOwnerWithReadWriteChangesNetVar()
|
||||
{
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
|
||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
var oldValue = testCompClient.OwnerReadWrite_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
testCompClient.OwnerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
||||
|
||||
// Verify the client owner and server match
|
||||
yield return CheckOwnerReadWriteAreEqualOnOwnerAndServer();
|
||||
|
||||
// Verify the non-owner clients do not have the same Value but do have the same permissions
|
||||
yield return CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(testCompClient);
|
||||
}
|
||||
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ClientCannotChangeServerWritableNetVar()
|
||||
{
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 2);
|
||||
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
|
||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
var oldValue = testCompClient.ServerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
LogAssert.Expect(LogType.Error, testCompClient.ServerWritable_Position.GetWritePermissionError());
|
||||
testCompClient.ServerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, oldValue);
|
||||
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
|
||||
testCompServer.ServerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue);
|
||||
|
||||
yield return WaitForServerWritableAreEqualOnAll();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ServerCannotChangeOwnerWritableNetVar()
|
||||
{
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
int clientManagerIndex = m_ClientNetworkManagers.Length - 1;
|
||||
var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId;
|
||||
testObjServer.ChangeOwnership(newOwnerClientId);
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 4);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var oldValue = testCompServer.OwnerWritable_Position.Value;
|
||||
var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f));
|
||||
|
||||
LogAssert.Expect(LogType.Error, testCompServer.OwnerWritable_Position.GetWritePermissionError());
|
||||
testCompServer.OwnerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, oldValue);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
|
||||
var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId];
|
||||
var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
|
||||
|
||||
testCompClient.OwnerWritable_Position.Value = newValue;
|
||||
yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue);
|
||||
|
||||
yield return WaitForOwnerWritableAreEqualOnAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60d49d322bef8ff4ebb8c4abf57e18e3
|
||||
5093
Tests/Runtime/NetworkVariable/NetworkVariableTests.cs
Normal file
5093
Tests/Runtime/NetworkVariable/NetworkVariableTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Tests/Runtime/NetworkVariable/NetworkVariableTests.cs.meta
Normal file
11
Tests/Runtime/NetworkVariable/NetworkVariableTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d271d8738dbbb5e4aa0cae91b663f183
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
937
Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs
Normal file
937
Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs
Normal file
@@ -0,0 +1,937 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
internal class NetVarPermTestComp : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<Vector3> OwnerWritable_Position = new NetworkVariable<Vector3>(Vector3.one, NetworkVariableBase.DefaultReadPerm, NetworkVariableWritePermission.Owner);
|
||||
public NetworkVariable<Vector3> ServerWritable_Position = new NetworkVariable<Vector3>(Vector3.one, NetworkVariableBase.DefaultReadPerm, NetworkVariableWritePermission.Server);
|
||||
public NetworkVariable<Vector3> OwnerReadWrite_Position = new NetworkVariable<Vector3>(Vector3.one, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Owner);
|
||||
}
|
||||
|
||||
internal class NetworkVariableMiddleclass<TMiddleclassName> : NetworkVariable<TMiddleclassName>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class NetworkVariableSubclass<TSubclassName> : NetworkVariableMiddleclass<TSubclassName>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class NetworkBehaviourWithNetVarArray : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<int> Int0 = new NetworkVariable<int>();
|
||||
public NetworkVariable<int> Int1 = new NetworkVariable<int>();
|
||||
public NetworkVariable<int> Int2 = new NetworkVariable<int>();
|
||||
public NetworkVariable<int> Int3 = new NetworkVariable<int>();
|
||||
public NetworkVariable<int> Int4 = new NetworkVariable<int>();
|
||||
public NetworkVariable<int>[] AllInts = new NetworkVariable<int>[5];
|
||||
|
||||
public int InitializedFieldCount => NetworkVariableFields.Count;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
AllInts[0] = Int0;
|
||||
AllInts[1] = Int1;
|
||||
AllInts[2] = Int2;
|
||||
AllInts[3] = Int3;
|
||||
AllInts[4] = Int4;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct TypeReferencedOnlyInCustomSerialization1 : INetworkSerializeByMemcpy
|
||||
{
|
||||
public int I;
|
||||
}
|
||||
|
||||
internal struct TypeReferencedOnlyInCustomSerialization2 : INetworkSerializeByMemcpy
|
||||
{
|
||||
public int I;
|
||||
}
|
||||
|
||||
internal struct TypeReferencedOnlyInCustomSerialization3 : INetworkSerializeByMemcpy
|
||||
{
|
||||
public int I;
|
||||
}
|
||||
|
||||
internal struct TypeReferencedOnlyInCustomSerialization4 : INetworkSerializeByMemcpy
|
||||
{
|
||||
public int I;
|
||||
}
|
||||
|
||||
internal struct TypeReferencedOnlyInCustomSerialization5 : INetworkSerializeByMemcpy
|
||||
{
|
||||
public int I;
|
||||
}
|
||||
|
||||
internal struct TypeReferencedOnlyInCustomSerialization6 : INetworkSerializeByMemcpy
|
||||
{
|
||||
public int I;
|
||||
}
|
||||
|
||||
// Both T and U are serializable
|
||||
[GenerateSerializationForGenericParameter(0)]
|
||||
[GenerateSerializationForGenericParameter(1)]
|
||||
internal class CustomSerializableClass<TSerializableType1, TSerializableType2>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Only U is serializable
|
||||
[GenerateSerializationForGenericParameter(1)]
|
||||
internal class CustomSerializableBaseClass<TUnserializableType, TSerializableType>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// T is serializable, passes TypeReferencedOnlyInCustomSerialization3 as U to the subclass, making it serializable
|
||||
[GenerateSerializationForGenericParameter(0)]
|
||||
internal class CustomSerializableSubclass<TSerializableType> : CustomSerializableBaseClass<TSerializableType, TypeReferencedOnlyInCustomSerialization3>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// T is serializable, passes TypeReferencedOnlyInCustomSerialization3 as U to the subclass, making it serializable
|
||||
[GenerateSerializationForGenericParameter(0)]
|
||||
internal class CustomSerializableSubclassWithNativeArray<TSerializableType> : CustomSerializableBaseClass<TSerializableType, NativeArray<TypeReferencedOnlyInCustomSerialization3>>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class CustomGenericSerializationTestBehaviour : NetworkBehaviour
|
||||
{
|
||||
public CustomSerializableClass<TypeReferencedOnlyInCustomSerialization1, TypeReferencedOnlyInCustomSerialization2> Value1;
|
||||
public CustomSerializableClass<NativeArray<TypeReferencedOnlyInCustomSerialization1>, NativeArray<TypeReferencedOnlyInCustomSerialization2>> Value2;
|
||||
public CustomSerializableSubclass<TypeReferencedOnlyInCustomSerialization4> Value3;
|
||||
public CustomSerializableSubclassWithNativeArray<NativeArray<TypeReferencedOnlyInCustomSerialization4>> Value4;
|
||||
}
|
||||
|
||||
[GenerateSerializationForType(typeof(TypeReferencedOnlyInCustomSerialization5))]
|
||||
[GenerateSerializationForType(typeof(NativeArray<TypeReferencedOnlyInCustomSerialization5>))]
|
||||
internal struct SomeRandomStruct
|
||||
{
|
||||
[GenerateSerializationForType(typeof(TypeReferencedOnlyInCustomSerialization6))]
|
||||
[GenerateSerializationForType(typeof(NativeArray<TypeReferencedOnlyInCustomSerialization6>))]
|
||||
public void Foo()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal struct TemplatedValueOnlyReferencedByNetworkVariableSubclass<T> : INetworkSerializeByMemcpy
|
||||
where T : unmanaged
|
||||
{
|
||||
public T Value;
|
||||
}
|
||||
|
||||
public enum ByteEnum : byte
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = byte.MaxValue
|
||||
}
|
||||
public enum SByteEnum : sbyte
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = sbyte.MaxValue
|
||||
}
|
||||
public enum ShortEnum : short
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = short.MaxValue
|
||||
}
|
||||
public enum UShortEnum : ushort
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = ushort.MaxValue
|
||||
}
|
||||
public enum IntEnum : int
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = int.MaxValue
|
||||
}
|
||||
public enum UIntEnum : uint
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = uint.MaxValue
|
||||
}
|
||||
public enum LongEnum : long
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = long.MaxValue
|
||||
}
|
||||
public enum ULongEnum : ulong
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = ulong.MaxValue
|
||||
}
|
||||
|
||||
internal struct HashableNetworkVariableTestStruct : INetworkSerializeByMemcpy, IEquatable<HashableNetworkVariableTestStruct>
|
||||
{
|
||||
public byte A;
|
||||
public short B;
|
||||
public ushort C;
|
||||
public int D;
|
||||
public uint E;
|
||||
public long F;
|
||||
public ulong G;
|
||||
public bool H;
|
||||
public char I;
|
||||
public float J;
|
||||
public double K;
|
||||
|
||||
public bool Equals(HashableNetworkVariableTestStruct other)
|
||||
{
|
||||
return A == other.A && B == other.B && C == other.C && D == other.D && E == other.E && F == other.F && G == other.G && H == other.H && I == other.I && J.Equals(other.J) && K.Equals(other.K);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is HashableNetworkVariableTestStruct other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = new HashCode();
|
||||
hashCode.Add(A);
|
||||
hashCode.Add(B);
|
||||
hashCode.Add(C);
|
||||
hashCode.Add(D);
|
||||
hashCode.Add(E);
|
||||
hashCode.Add(F);
|
||||
hashCode.Add(G);
|
||||
hashCode.Add(H);
|
||||
hashCode.Add(I);
|
||||
hashCode.Add(J);
|
||||
hashCode.Add(K);
|
||||
return hashCode.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
internal struct HashMapKeyStruct : INetworkSerializeByMemcpy, IEquatable<HashMapKeyStruct>
|
||||
{
|
||||
public byte A;
|
||||
public short B;
|
||||
public ushort C;
|
||||
public int D;
|
||||
public uint E;
|
||||
public long F;
|
||||
public ulong G;
|
||||
public bool H;
|
||||
public char I;
|
||||
public float J;
|
||||
public double K;
|
||||
|
||||
public bool Equals(HashMapKeyStruct other)
|
||||
{
|
||||
return A == other.A && B == other.B && C == other.C && D == other.D && E == other.E && F == other.F && G == other.G && H == other.H && I == other.I && J.Equals(other.J) && K.Equals(other.K);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is HashMapKeyStruct other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = new HashCode();
|
||||
hashCode.Add(A);
|
||||
hashCode.Add(B);
|
||||
hashCode.Add(C);
|
||||
hashCode.Add(D);
|
||||
hashCode.Add(E);
|
||||
hashCode.Add(F);
|
||||
hashCode.Add(G);
|
||||
hashCode.Add(H);
|
||||
hashCode.Add(I);
|
||||
hashCode.Add(J);
|
||||
hashCode.Add(K);
|
||||
return hashCode.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
internal struct HashMapValStruct : INetworkSerializeByMemcpy, IEquatable<HashMapValStruct>
|
||||
{
|
||||
public byte A;
|
||||
public short B;
|
||||
public ushort C;
|
||||
public int D;
|
||||
public uint E;
|
||||
public long F;
|
||||
public ulong G;
|
||||
public bool H;
|
||||
public char I;
|
||||
public float J;
|
||||
public double K;
|
||||
|
||||
public bool Equals(HashMapValStruct other)
|
||||
{
|
||||
return A == other.A && B == other.B && C == other.C && D == other.D && E == other.E && F == other.F && G == other.G && H == other.H && I == other.I && J.Equals(other.J) && K.Equals(other.K);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is HashMapValStruct other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = new HashCode();
|
||||
hashCode.Add(A);
|
||||
hashCode.Add(B);
|
||||
hashCode.Add(C);
|
||||
hashCode.Add(D);
|
||||
hashCode.Add(E);
|
||||
hashCode.Add(F);
|
||||
hashCode.Add(G);
|
||||
hashCode.Add(H);
|
||||
hashCode.Add(I);
|
||||
hashCode.Add(J);
|
||||
hashCode.Add(K);
|
||||
return hashCode.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
internal struct NetworkVariableTestStruct : INetworkSerializeByMemcpy
|
||||
{
|
||||
public byte A;
|
||||
public short B;
|
||||
public ushort C;
|
||||
public int D;
|
||||
public uint E;
|
||||
public long F;
|
||||
public ulong G;
|
||||
public bool H;
|
||||
public char I;
|
||||
public float J;
|
||||
public double K;
|
||||
|
||||
private static System.Random s_Random = new System.Random();
|
||||
|
||||
public static NetworkVariableTestStruct GetTestStruct()
|
||||
{
|
||||
var testStruct = new NetworkVariableTestStruct
|
||||
{
|
||||
A = (byte)s_Random.Next(),
|
||||
B = (short)s_Random.Next(),
|
||||
C = (ushort)s_Random.Next(),
|
||||
D = s_Random.Next(),
|
||||
E = (uint)s_Random.Next(),
|
||||
F = ((long)s_Random.Next() << 32) + s_Random.Next(),
|
||||
G = ((ulong)s_Random.Next() << 32) + (ulong)s_Random.Next(),
|
||||
H = true,
|
||||
I = '\u263a',
|
||||
J = (float)s_Random.NextDouble(),
|
||||
K = s_Random.NextDouble(),
|
||||
};
|
||||
|
||||
return testStruct;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class HashableNetworkVariableTestClass : INetworkSerializable, IEquatable<HashableNetworkVariableTestClass>
|
||||
{
|
||||
public HashableNetworkVariableTestStruct Data;
|
||||
|
||||
public bool Equals(HashableNetworkVariableTestClass other)
|
||||
{
|
||||
return Data.Equals(other.Data);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is HashableNetworkVariableTestClass other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Data.GetHashCode();
|
||||
}
|
||||
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
serializer.SerializeValue(ref Data);
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapKeyClass : INetworkSerializable, IEquatable<HashMapKeyClass>
|
||||
{
|
||||
public HashMapKeyStruct Data;
|
||||
|
||||
public bool Equals(HashMapKeyClass other)
|
||||
{
|
||||
return Data.Equals(other.Data);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is HashMapKeyClass other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Data.GetHashCode();
|
||||
}
|
||||
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
serializer.SerializeValue(ref Data);
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapValClass : INetworkSerializable, IEquatable<HashMapValClass>
|
||||
{
|
||||
public HashMapValStruct Data;
|
||||
|
||||
public bool Equals(HashMapValClass other)
|
||||
{
|
||||
return Data.Equals(other.Data);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is HashMapValClass other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Data.GetHashCode();
|
||||
}
|
||||
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
serializer.SerializeValue(ref Data);
|
||||
}
|
||||
}
|
||||
|
||||
internal class NetworkVariableTestClass : INetworkSerializable, IEquatable<NetworkVariableTestClass>
|
||||
{
|
||||
public NetworkVariableTestStruct Data;
|
||||
|
||||
public bool Equals(NetworkVariableTestClass other)
|
||||
{
|
||||
return NetworkVariableSerialization<NetworkVariableTestStruct>.AreEqual(ref Data, ref other.Data);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is NetworkVariableTestClass other && Equals(other);
|
||||
}
|
||||
|
||||
// This type is not used for hashing, we just need to implement IEquatable to verify lists match.
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
serializer.SerializeValue(ref Data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The ILPP code for NetworkVariables to determine how to serialize them relies on them existing as fields of a NetworkBehaviour to find them.
|
||||
// Some of the tests below create NetworkVariables on the stack, so this class is here just to make sure the relevant types are all accounted for.
|
||||
internal class NetVarILPPClassForTests : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<byte> ByteVar;
|
||||
public NetworkVariable<NativeArray<byte>> ByteArrayVar;
|
||||
public NetworkVariable<List<byte>> ByteManagedListVar;
|
||||
public NetworkVariable<HashSet<byte>> ByteManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<byte>> ByteListVar;
|
||||
public NetworkVariable<NativeHashSet<byte>> ByteHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, byte>> ByteByteHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, byte>> ULongByteHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, byte>> Vector2ByteHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, byte>> HashMapKeyStructByteHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, byte>> ByteByteDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, byte>> ULongByteDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, byte>> Vector2ByteDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, byte>> HashMapKeyClassByteDictionaryVar;
|
||||
|
||||
public NetworkVariable<sbyte> SbyteVar;
|
||||
public NetworkVariable<NativeArray<sbyte>> SbyteArrayVar;
|
||||
public NetworkVariable<List<sbyte>> SbyteManagedListVar;
|
||||
public NetworkVariable<HashSet<sbyte>> SbyteManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<sbyte>> SbyteListVar;
|
||||
public NetworkVariable<NativeHashSet<sbyte>> SbyteHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, sbyte>> ByteSbyteHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, sbyte>> ULongSbyteHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, sbyte>> Vector2SbyteHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, sbyte>> HashMapKeyStructSbyteHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, sbyte>> ByteSbyteDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, sbyte>> ULongSbyteDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, sbyte>> Vector2SbyteDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, sbyte>> HashMapKeyClassSbyteDictionaryVar;
|
||||
|
||||
public NetworkVariable<short> ShortVar;
|
||||
public NetworkVariable<NativeArray<short>> ShortArrayVar;
|
||||
public NetworkVariable<List<short>> ShortManagedListVar;
|
||||
public NetworkVariable<HashSet<short>> ShortManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<short>> ShortListVar;
|
||||
public NetworkVariable<NativeHashSet<short>> ShortHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, short>> ByteShortHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, short>> ULongShortHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, short>> Vector2ShortHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, short>> HashMapKeyStructShortHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, short>> ByteShortDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, short>> ULongShortDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, short>> Vector2ShortDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, short>> HashMapKeyClassShortDictionaryVar;
|
||||
|
||||
public NetworkVariable<ushort> UshortVar;
|
||||
public NetworkVariable<NativeArray<ushort>> UshortArrayVar;
|
||||
public NetworkVariable<List<ushort>> UshortManagedListVar;
|
||||
public NetworkVariable<HashSet<ushort>> UshortManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<ushort>> UshortListVar;
|
||||
public NetworkVariable<NativeHashSet<ushort>> UshortHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, ushort>> ByteUshortHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, ushort>> ULongUshortHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, ushort>> Vector2UshortHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, ushort>> HashMapKeyStructUshortHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, ushort>> ByteUshortDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, ushort>> ULongUshortDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, ushort>> Vector2UshortDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, ushort>> HashMapKeyClassUshortDictionaryVar;
|
||||
|
||||
public NetworkVariable<int> IntVar;
|
||||
public NetworkVariable<NativeArray<int>> IntArrayVar;
|
||||
public NetworkVariable<List<int>> IntManagedListVar;
|
||||
public NetworkVariable<HashSet<int>> IntManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<int>> IntListVar;
|
||||
public NetworkVariable<NativeHashSet<int>> IntHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, int>> ByteIntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, int>> ULongIntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, int>> Vector2IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, int>> HashMapKeyStructIntHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, int>> ByteIntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, int>> ULongIntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, int>> Vector2IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, int>> HashMapKeyClassIntDictionaryVar;
|
||||
|
||||
public NetworkVariable<uint> UintVar;
|
||||
public NetworkVariable<NativeArray<uint>> UintArrayVar;
|
||||
public NetworkVariable<List<uint>> UintManagedListVar;
|
||||
public NetworkVariable<HashSet<uint>> UintManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<uint>> UintListVar;
|
||||
public NetworkVariable<NativeHashSet<uint>> UintHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, uint>> ByteUintHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, uint>> ULongUintHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, uint>> Vector2UintHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, uint>> HashMapKeyStructUintHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, uint>> ByteUintDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, uint>> ULongUintDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, uint>> Vector2UintDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, uint>> HashMapKeyClassUintDictionaryVar;
|
||||
|
||||
public NetworkVariable<long> LongVar;
|
||||
public NetworkVariable<NativeArray<long>> LongArrayVar;
|
||||
public NetworkVariable<List<long>> LongManagedListVar;
|
||||
public NetworkVariable<HashSet<long>> LongManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<long>> LongListVar;
|
||||
public NetworkVariable<NativeHashSet<long>> LongHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, long>> ByteLongHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, long>> ULongLongHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, long>> Vector2LongHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, long>> HashMapKeyStructLongHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, long>> ByteLongDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, long>> ULongLongDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, long>> Vector2LongDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, long>> HashMapKeyClassLongDictionaryVar;
|
||||
|
||||
public NetworkVariable<ulong> UlongVar;
|
||||
public NetworkVariable<NativeArray<ulong>> UlongArrayVar;
|
||||
public NetworkVariable<List<ulong>> UlongManagedListVar;
|
||||
public NetworkVariable<HashSet<ulong>> UlongManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<ulong>> UlongListVar;
|
||||
public NetworkVariable<NativeHashSet<ulong>> UlongHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, ulong>> ByteUlongHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, ulong>> ULongUlongHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, ulong>> Vector2UlongHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, ulong>> HashMapKeyStructUlongHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, ulong>> ByteUlongDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, ulong>> ULongUlongDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, ulong>> Vector2UlongDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, ulong>> HashMapKeyClassUlongDictionaryVar;
|
||||
|
||||
public NetworkVariable<bool> BoolVar;
|
||||
public NetworkVariable<NativeArray<bool>> BoolArrayVar;
|
||||
public NetworkVariable<List<bool>> BoolManagedListVar;
|
||||
public NetworkVariable<HashSet<bool>> BoolManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<bool>> BoolListVar;
|
||||
public NetworkVariable<NativeHashSet<bool>> BoolHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, bool>> ByteBoolHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, bool>> ULongBoolHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, bool>> Vector2BoolHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, bool>> HashMapKeyStructBoolHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, bool>> ByteBoolDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, bool>> ULongBoolDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, bool>> Vector2BoolDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, bool>> HashMapKeyClassBoolDictionaryVar;
|
||||
|
||||
public NetworkVariable<char> CharVar;
|
||||
public NetworkVariable<NativeArray<char>> CharArrayVar;
|
||||
public NetworkVariable<List<char>> CharManagedListVar;
|
||||
public NetworkVariable<HashSet<char>> CharManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<char>> CharListVar;
|
||||
public NetworkVariable<NativeHashSet<char>> CharHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, char>> ByteCharHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, char>> ULongCharHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, char>> Vector2CharHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, char>> HashMapKeyStructCharHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, char>> ByteCharDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, char>> ULongCharDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, char>> Vector2CharDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, char>> HashMapKeyClassCharDictionaryVar;
|
||||
|
||||
public NetworkVariable<float> FloatVar;
|
||||
public NetworkVariable<NativeArray<float>> FloatArrayVar;
|
||||
public NetworkVariable<List<float>> FloatManagedListVar;
|
||||
public NetworkVariable<HashSet<float>> FloatManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<float>> FloatListVar;
|
||||
public NetworkVariable<NativeHashSet<float>> FloatHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, float>> ByteFloatHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, float>> ULongFloatHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, float>> Vector2FloatHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, float>> HashMapKeyStructFloatHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, float>> ByteFloatDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, float>> ULongFloatDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, float>> Vector2FloatDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, float>> HashMapKeyClassFloatDictionaryVar;
|
||||
|
||||
public NetworkVariable<double> DoubleVar;
|
||||
public NetworkVariable<NativeArray<double>> DoubleArrayVar;
|
||||
public NetworkVariable<List<double>> DoubleManagedListVar;
|
||||
public NetworkVariable<HashSet<double>> DoubleManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<double>> DoubleListVar;
|
||||
public NetworkVariable<NativeHashSet<double>> DoubleHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, double>> ByteDoubleHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, double>> ULongDoubleHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, double>> Vector2DoubleHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, double>> HashMapKeyStructDoubleHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, double>> ByteDoubleDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, double>> ULongDoubleDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, double>> Vector2DoubleDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, double>> HashMapKeyClassDoubleDictionaryVar;
|
||||
|
||||
public NetworkVariable<ByteEnum> ByteEnumVar;
|
||||
public NetworkVariable<NativeArray<ByteEnum>> ByteEnumArrayVar;
|
||||
public NetworkVariable<List<ByteEnum>> ByteEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<ByteEnum>> ByteEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<SByteEnum> SByteEnumVar;
|
||||
public NetworkVariable<NativeArray<SByteEnum>> SByteEnumArrayVar;
|
||||
public NetworkVariable<List<SByteEnum>> SByteEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<SByteEnum>> SByteEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<ShortEnum> ShortEnumVar;
|
||||
public NetworkVariable<NativeArray<ShortEnum>> ShortEnumArrayVar;
|
||||
public NetworkVariable<List<ShortEnum>> ShortEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<ShortEnum>> ShortEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<UShortEnum> UShortEnumVar;
|
||||
public NetworkVariable<NativeArray<UShortEnum>> UShortEnumArrayVar;
|
||||
public NetworkVariable<List<UShortEnum>> UShortEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<UShortEnum>> UShortEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<IntEnum> IntEnumVar;
|
||||
public NetworkVariable<NativeArray<IntEnum>> IntEnumArrayVar;
|
||||
public NetworkVariable<List<IntEnum>> IntEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<IntEnum>> IntEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<UIntEnum> UIntEnumVar;
|
||||
public NetworkVariable<NativeArray<UIntEnum>> UIntEnumArrayVar;
|
||||
public NetworkVariable<List<UIntEnum>> UIntEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<UIntEnum>> UIntEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<LongEnum> LongEnumVar;
|
||||
public NetworkVariable<NativeArray<LongEnum>> LongEnumArrayVar;
|
||||
public NetworkVariable<List<LongEnum>> LongEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<LongEnum>> LongEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<ULongEnum> ULongEnumVar;
|
||||
public NetworkVariable<NativeArray<ULongEnum>> ULongEnumArrayVar;
|
||||
public NetworkVariable<List<ULongEnum>> ULongEnumManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<ULongEnum>> ULongEnumListVar;
|
||||
#endif
|
||||
public NetworkVariable<Vector2> Vector2Var;
|
||||
public NetworkVariable<NativeArray<Vector2>> Vector2ArrayVar;
|
||||
public NetworkVariable<List<Vector2>> Vector2ManagedListVar;
|
||||
public NetworkVariable<HashSet<Vector2>> Vector2ManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Vector2>> Vector2ListVar;
|
||||
public NetworkVariable<NativeHashSet<Vector2>> Vector2HashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, Vector2>> ByteVector2HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, Vector2>> ULongVector2HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, Vector2>> Vector2Vector2HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, Vector2>> HashMapKeyStructVector2HashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, Vector2>> ByteVector2DictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, Vector2>> ULongVector2DictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, Vector2>> Vector2Vector2DictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, Vector2>> HashMapKeyClassVector2DictionaryVar;
|
||||
|
||||
public NetworkVariable<Vector3> Vector3Var;
|
||||
public NetworkVariable<NativeArray<Vector3>> Vector3ArrayVar;
|
||||
public NetworkVariable<List<Vector3>> Vector3ManagedListVar;
|
||||
public NetworkVariable<HashSet<Vector3>> Vector3ManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Vector3>> Vector3ListVar;
|
||||
public NetworkVariable<NativeHashSet<Vector3>> Vector3HashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, Vector3>> ByteVector3HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, Vector3>> ULongVector3HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, Vector3>> Vector2Vector3HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, Vector3>> HashMapKeyStructVector3HashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, Vector3>> ByteVector3DictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, Vector3>> ULongVector3DictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, Vector3>> Vector2Vector3DictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, Vector3>> HashMapKeyClassVector3DictionaryVar;
|
||||
|
||||
public NetworkVariable<Vector2Int> Vector2IntVar;
|
||||
public NetworkVariable<NativeArray<Vector2Int>> Vector2IntArrayVar;
|
||||
public NetworkVariable<List<Vector2Int>> Vector2IntManagedListVar;
|
||||
public NetworkVariable<HashSet<Vector2Int>> Vector2IntManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Vector2Int>> Vector2IntListVar;
|
||||
public NetworkVariable<NativeHashSet<Vector2Int>> Vector2IntHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, Vector2Int>> ByteVector2IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, Vector2Int>> ULongVector2IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, Vector2Int>> Vector2Vector2IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, Vector2Int>> HashMapKeyStructVector2IntHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, Vector2Int>> ByteVector2IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, Vector2Int>> ULongVector2IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, Vector2Int>> Vector2Vector2IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, Vector2Int>> HashMapKeyClassVector2IntDictionaryVar;
|
||||
|
||||
public NetworkVariable<Vector3Int> Vector3IntVar;
|
||||
public NetworkVariable<NativeArray<Vector3Int>> Vector3IntArrayVar;
|
||||
public NetworkVariable<List<Vector3Int>> Vector3IntManagedListVar;
|
||||
public NetworkVariable<HashSet<Vector3Int>> Vector3IntManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Vector3Int>> Vector3IntListVar;
|
||||
public NetworkVariable<NativeHashSet<Vector3Int>> Vector3IntHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, Vector3Int>> ByteVector3IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, Vector3Int>> ULongVector3IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, Vector3Int>> Vector2Vector3IntHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, Vector3Int>> HashMapKeyStructVector3IntHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, Vector3Int>> ByteVector3IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, Vector3Int>> ULongVector3IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, Vector3Int>> Vector2Vector3IntDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, Vector3Int>> HashMapKeyClassVector3IntDictionaryVar;
|
||||
|
||||
public NetworkVariable<Vector4> Vector4Var;
|
||||
public NetworkVariable<NativeArray<Vector4>> Vector4ArrayVar;
|
||||
public NetworkVariable<List<Vector4>> Vector4ManagedListVar;
|
||||
public NetworkVariable<HashSet<Vector4>> Vector4ManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Vector4>> Vector4ListVar;
|
||||
public NetworkVariable<NativeHashSet<Vector4>> Vector4HashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, Vector4>> ByteVector4HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, Vector4>> ULongVector4HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, Vector4>> Vector2Vector4HashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, Vector4>> HashMapKeyStructVector4HashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, Vector4>> ByteVector4DictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, Vector4>> ULongVector4DictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, Vector4>> Vector2Vector4DictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, Vector4>> HashMapKeyClassVector4DictionaryVar;
|
||||
|
||||
public NetworkVariable<Quaternion> QuaternionVar;
|
||||
public NetworkVariable<NativeArray<Quaternion>> QuaternionArrayVar;
|
||||
public NetworkVariable<List<Quaternion>> QuaternionManagedListVar;
|
||||
public NetworkVariable<HashSet<Quaternion>> QuaternionManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Quaternion>> QuaternionListVar;
|
||||
public NetworkVariable<NativeHashSet<Quaternion>> QuaternionHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, Quaternion>> ByteQuaternionHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, Quaternion>> ULongQuaternionHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, Quaternion>> Vector2QuaternionHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, Quaternion>> HashMapKeyStructQuaternionHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, Quaternion>> ByteQuaternionDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, Quaternion>> ULongQuaternionDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, Quaternion>> Vector2QuaternionDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, Quaternion>> HashMapKeyClassQuaternionDictionaryVar;
|
||||
|
||||
public NetworkVariable<Color> ColorVar;
|
||||
public NetworkVariable<NativeArray<Color>> ColorArrayVar;
|
||||
public NetworkVariable<List<Color>> ColorManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Color>> ColorListVar;
|
||||
#endif
|
||||
public NetworkVariable<Color32> Color32Var;
|
||||
public NetworkVariable<NativeArray<Color32>> Color32ArrayVar;
|
||||
public NetworkVariable<List<Color32>> Color32ManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Color32>> Color32ListVar;
|
||||
#endif
|
||||
public NetworkVariable<Ray> RayVar;
|
||||
public NetworkVariable<NativeArray<Ray>> RayArrayVar;
|
||||
public NetworkVariable<List<Ray>> RayManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Ray>> RayListVar;
|
||||
#endif
|
||||
public NetworkVariable<Ray2D> Ray2DVar;
|
||||
public NetworkVariable<NativeArray<Ray2D>> Ray2DArrayVar;
|
||||
public NetworkVariable<List<Ray2D>> Ray2DManagedListVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<Ray2D>> Ray2DListVar;
|
||||
#endif
|
||||
public NetworkVariable<NetworkVariableTestStruct> TestStructVar;
|
||||
public NetworkVariable<NativeArray<NetworkVariableTestStruct>> TestStructArrayVar;
|
||||
public NetworkVariable<List<NetworkVariableTestClass>> TestStructManagedListVar;
|
||||
public NetworkVariable<HashSet<HashableNetworkVariableTestClass>> TestStructManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<NetworkVariableTestStruct>> TestStructListVar;
|
||||
public NetworkVariable<NativeHashSet<HashableNetworkVariableTestStruct>> TestStructHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, HashMapValStruct>> ByteTestStructHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, HashMapValStruct>> ULongTestStructHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, HashMapValStruct>> Vector2TestStructHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, HashMapValStruct>> HashMapKeyStructTestStructHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, HashMapValClass>> ByteTestStructDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, HashMapValClass>> ULongTestStructDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, HashMapValClass>> Vector2TestStructDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, HashMapValClass>> HashMapKeyClassTestStructDictionaryVar;
|
||||
|
||||
|
||||
public NetworkVariable<FixedString32Bytes> FixedStringVar;
|
||||
public NetworkVariable<NativeArray<FixedString32Bytes>> FixedStringArrayVar;
|
||||
public NetworkVariable<List<FixedString32Bytes>> FixedStringManagedListVar;
|
||||
public NetworkVariable<HashSet<FixedString32Bytes>> FixedStringManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<FixedString32Bytes>> FixedStringListVar;
|
||||
public NetworkVariable<NativeHashSet<FixedString32Bytes>> FixedStringHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, FixedString32Bytes>> ByteFixedStringHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, FixedString32Bytes>> ULongFixedStringHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, FixedString32Bytes>> Vector2FixedStringHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, FixedString32Bytes>> HashMapKeyStructFixedStringHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, FixedString32Bytes>> ByteFixedStringDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, FixedString32Bytes>> ULongFixedStringDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, FixedString32Bytes>> Vector2FixedStringDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, FixedString32Bytes>> HashMapKeyClassFixedStringDictionaryVar;
|
||||
|
||||
|
||||
public NetworkVariable<UnmanagedNetworkSerializableType> UnmanagedNetworkSerializableTypeVar;
|
||||
public NetworkVariable<HashSet<UnmanagedNetworkSerializableType>> UnmanagedNetworkSerializableManagedHashSetVar;
|
||||
#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT
|
||||
public NetworkVariable<NativeList<UnmanagedNetworkSerializableType>> UnmanagedNetworkSerializableListVar;
|
||||
public NetworkVariable<NativeHashSet<UnmanagedNetworkSerializableType>> UnmanagedNetworkSerializableHashSetVar;
|
||||
public NetworkVariable<NativeHashMap<byte, UnmanagedNetworkSerializableType>> ByteUnmanagedNetworkSerializableHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<ulong, UnmanagedNetworkSerializableType>> ULongUnmanagedNetworkSerializableHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<Vector2, UnmanagedNetworkSerializableType>> Vector2UnmanagedNetworkSerializableHashMapVar;
|
||||
public NetworkVariable<NativeHashMap<HashMapKeyStruct, UnmanagedNetworkSerializableType>> HashMapKeyStructUnmanagedNetworkSerializableHashMapVar;
|
||||
#endif
|
||||
public NetworkVariable<Dictionary<byte, UnmanagedNetworkSerializableType>> ByteUnmanagedNetworkSerializableDictionaryVar;
|
||||
public NetworkVariable<Dictionary<ulong, UnmanagedNetworkSerializableType>> ULongUnmanagedNetworkSerializableDictionaryVar;
|
||||
public NetworkVariable<Dictionary<Vector2, UnmanagedNetworkSerializableType>> Vector2UnmanagedNetworkSerializableDictionaryVar;
|
||||
public NetworkVariable<Dictionary<HashMapKeyClass, UnmanagedNetworkSerializableType>> HashMapKeyClassUnmanagedNetworkSerializableDictionaryVar;
|
||||
|
||||
public NetworkVariable<NativeArray<UnmanagedNetworkSerializableType>> UnmanagedNetworkSerializableArrayVar;
|
||||
public NetworkVariable<List<UnmanagedNetworkSerializableType>> UnmanagedNetworkSerializableManagedListVar;
|
||||
|
||||
public NetworkVariable<ManagedNetworkSerializableType> ManagedNetworkSerializableTypeVar;
|
||||
|
||||
public NetworkVariable<string> StringVar;
|
||||
public NetworkVariable<Guid> GuidVar;
|
||||
public NetworkVariableSubclass<TemplatedValueOnlyReferencedByNetworkVariableSubclass<int>> SubclassVar;
|
||||
}
|
||||
|
||||
internal class TemplateNetworkBehaviourType<T> : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<T> TheVar;
|
||||
}
|
||||
|
||||
internal class IntermediateNetworkBehavior<T> : TemplateNetworkBehaviourType<T>
|
||||
{
|
||||
public NetworkVariable<T> TheVar2;
|
||||
}
|
||||
#if !NGO_MINIMALPROJECT
|
||||
internal class ClassHavingNetworkBehaviour : IntermediateNetworkBehavior<TestClass>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Please do not reference TestClass_ReferencedOnlyByTemplateNetworkBehavourType anywhere other than here!
|
||||
internal class ClassHavingNetworkBehaviour2 : TemplateNetworkBehaviourType<TestClass_ReferencedOnlyByTemplateNetworkBehaviourType>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class StructHavingNetworkBehaviour : TemplateNetworkBehaviourType<TestStruct>
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
internal struct StructUsedOnlyInNetworkList : IEquatable<StructUsedOnlyInNetworkList>, INetworkSerializeByMemcpy
|
||||
{
|
||||
public int Value;
|
||||
|
||||
public bool Equals(StructUsedOnlyInNetworkList other)
|
||||
{
|
||||
return Value == other.Value;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is StructUsedOnlyInNetworkList other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a580aaafc247486193f372174a99fae4
|
||||
timeCreated: 1705098783
|
||||
138
Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs
Normal file
138
Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
internal class NetworkVariableTraitsComponent : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<float> TheVariable = new NetworkVariable<float>();
|
||||
}
|
||||
|
||||
internal class NetworkVariableTraitsTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
protected override bool m_EnableTimeTravel => true;
|
||||
protected override bool m_SetupIsACoroutine => false;
|
||||
protected override bool m_TearDownIsACoroutine => false;
|
||||
|
||||
protected override void OnPlayerPrefabGameObjectCreated()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<NetworkVariableTraitsComponent>();
|
||||
}
|
||||
|
||||
public NetworkVariableTraitsComponent GetTestComponent()
|
||||
{
|
||||
return m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent<NetworkVariableTraitsComponent>();
|
||||
}
|
||||
|
||||
public NetworkVariableTraitsComponent GetServerComponent()
|
||||
{
|
||||
foreach (var obj in Object.FindObjectsByType<NetworkVariableTraitsComponent>(FindObjectsSortMode.None))
|
||||
{
|
||||
if (obj.NetworkManager == m_ServerNetworkManager && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNewValueIsLessThanThreshold_VariableIsNotSerialized()
|
||||
{
|
||||
var serverComponent = GetServerComponent();
|
||||
var testComponent = GetTestComponent();
|
||||
serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1;
|
||||
|
||||
serverComponent.TheVariable.Value = 0.05f;
|
||||
|
||||
TimeTravel(2, 120);
|
||||
|
||||
Assert.AreEqual(0.05f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0, testComponent.TheVariable.Value); ;
|
||||
}
|
||||
[Test]
|
||||
public void WhenNewValueIsGreaterThanThreshold_VariableIsSerialized()
|
||||
{
|
||||
var serverComponent = GetServerComponent();
|
||||
var testComponent = GetTestComponent();
|
||||
serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1;
|
||||
|
||||
serverComponent.TheVariable.Value = 0.15f;
|
||||
|
||||
TimeTravel(2, 120);
|
||||
|
||||
Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0.15f, testComponent.TheVariable.Value); ;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNewValueIsLessThanThresholdButMaxTimeHasPassed_VariableIsSerialized()
|
||||
{
|
||||
var serverComponent = GetServerComponent();
|
||||
var testComponent = GetTestComponent();
|
||||
serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1;
|
||||
serverComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MaxSecondsBetweenUpdates = 2 });
|
||||
serverComponent.TheVariable.LastUpdateSent = m_ServerNetworkManager.NetworkTimeSystem.LocalTime;
|
||||
|
||||
serverComponent.TheVariable.Value = 0.05f;
|
||||
|
||||
TimeTravel(1 / 60f * 119, 119);
|
||||
|
||||
Assert.AreEqual(0.05f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0, testComponent.TheVariable.Value); ;
|
||||
|
||||
TimeTravel(1 / 60f * 4, 4);
|
||||
|
||||
Assert.AreEqual(0.05f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0.05f, testComponent.TheVariable.Value); ;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNewValueIsGreaterThanThresholdButMinTimeHasNotPassed_VariableIsNotSerialized()
|
||||
{
|
||||
var serverComponent = GetServerComponent();
|
||||
var testComponent = GetTestComponent();
|
||||
serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1;
|
||||
serverComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 2 });
|
||||
serverComponent.TheVariable.LastUpdateSent = m_ServerNetworkManager.NetworkTimeSystem.LocalTime;
|
||||
|
||||
serverComponent.TheVariable.Value = 0.15f;
|
||||
|
||||
TimeTravel(1 / 60f * 119, 119);
|
||||
|
||||
Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0, testComponent.TheVariable.Value); ;
|
||||
|
||||
TimeTravel(1 / 60f * 4, 4);
|
||||
|
||||
Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0.15f, testComponent.TheVariable.Value); ;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNoThresholdIsSetButMinTimeHasNotPassed_VariableIsNotSerialized()
|
||||
{
|
||||
var serverComponent = GetServerComponent();
|
||||
var testComponent = GetTestComponent();
|
||||
serverComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 2 });
|
||||
serverComponent.TheVariable.LastUpdateSent = m_ServerNetworkManager.NetworkTimeSystem.LocalTime;
|
||||
|
||||
serverComponent.TheVariable.Value = 0.15f;
|
||||
|
||||
TimeTravel(1 / 60f * 119, 119);
|
||||
|
||||
Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0, testComponent.TheVariable.Value); ;
|
||||
|
||||
TimeTravel(1 / 60f * 4, 4);
|
||||
|
||||
Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ;
|
||||
Assert.AreEqual(0.15f, testComponent.TheVariable.Value); ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49f46ca2b4327464498a7465891647bb
|
||||
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
internal struct MyTypeOne
|
||||
{
|
||||
public int Value;
|
||||
}
|
||||
internal struct MyTypeTwo
|
||||
{
|
||||
public int Value;
|
||||
}
|
||||
internal struct MyTypeThree
|
||||
{
|
||||
public int Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to help track instances of any child derived class
|
||||
/// </summary>
|
||||
internal class WorkingUserNetworkVariableComponentBase : NetworkBehaviour
|
||||
{
|
||||
private static Dictionary<ulong, WorkingUserNetworkVariableComponentBase> s_Instances = new Dictionary<ulong, WorkingUserNetworkVariableComponentBase>();
|
||||
|
||||
internal static T GetRelativeInstance<T>(ulong clientId) where T : NetworkBehaviour
|
||||
{
|
||||
if (s_Instances.ContainsKey(clientId))
|
||||
{
|
||||
return s_Instances[clientId] as T;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
s_Instances.Clear();
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (!s_Instances.ContainsKey(NetworkManager.LocalClientId))
|
||||
{
|
||||
s_Instances.Add(NetworkManager.LocalClientId, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"{name} is spawned but client id {NetworkManager.LocalClientId} instance already exists!");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
if (s_Instances.ContainsKey(NetworkManager.LocalClientId))
|
||||
{
|
||||
s_Instances.Remove(NetworkManager.LocalClientId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"{name} is was never spawned but client id {NetworkManager.LocalClientId} is trying to despawn it!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class WorkingUserNetworkVariableComponent : WorkingUserNetworkVariableComponentBase
|
||||
{
|
||||
public NetworkVariable<MyTypeOne> NetworkVariable = new NetworkVariable<MyTypeOne>();
|
||||
}
|
||||
|
||||
internal class WorkingUserNetworkVariableComponentUsingExtensionMethod : WorkingUserNetworkVariableComponentBase
|
||||
{
|
||||
public NetworkVariable<MyTypeTwo> NetworkVariable = new NetworkVariable<MyTypeTwo>();
|
||||
}
|
||||
internal class NonWorkingUserNetworkVariableComponent : NetworkBehaviour
|
||||
{
|
||||
public NetworkVariable<MyTypeThree> NetworkVariable = new NetworkVariable<MyTypeThree>();
|
||||
}
|
||||
|
||||
internal static class NetworkVariableUserSerializableTypesTestsExtensionMethods
|
||||
{
|
||||
public static void WriteValueSafe(this FastBufferWriter writer, in MyTypeTwo value)
|
||||
{
|
||||
writer.WriteValueSafe(value.Value);
|
||||
}
|
||||
|
||||
public static void ReadValueSafe(this FastBufferReader reader, out MyTypeTwo value)
|
||||
{
|
||||
value = new MyTypeTwo();
|
||||
reader.ReadValueSafe(out value.Value);
|
||||
}
|
||||
}
|
||||
|
||||
internal class NetworkVariableUserSerializableTypesTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 1;
|
||||
|
||||
public NetworkVariableUserSerializableTypesTests()
|
||||
: base(HostOrServer.Server)
|
||||
{
|
||||
}
|
||||
|
||||
private GameObject m_WorkingPrefab;
|
||||
private GameObject m_ExtensionMethodPrefab;
|
||||
private GameObject m_NonWorkingPrefab;
|
||||
|
||||
protected override IEnumerator OnSetup()
|
||||
{
|
||||
WorkingUserNetworkVariableComponentBase.Reset();
|
||||
|
||||
UserNetworkVariableSerialization<MyTypeOne>.WriteValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeOne>.ReadValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeOne>.DuplicateValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.WriteValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.ReadValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.DuplicateValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeThree>.WriteValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeThree>.ReadValue = null;
|
||||
UserNetworkVariableSerialization<MyTypeThree>.DuplicateValue = null;
|
||||
return base.OnSetup();
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_WorkingPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableUserSerializableTypesTests)}.{nameof(m_WorkingPrefab)}]");
|
||||
m_ExtensionMethodPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableUserSerializableTypesTests)}.{nameof(m_ExtensionMethodPrefab)}]");
|
||||
m_NonWorkingPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableUserSerializableTypesTests)}.{nameof(m_NonWorkingPrefab)}]");
|
||||
m_WorkingPrefab.AddComponent<WorkingUserNetworkVariableComponent>();
|
||||
m_ExtensionMethodPrefab.AddComponent<WorkingUserNetworkVariableComponentUsingExtensionMethod>();
|
||||
m_NonWorkingPrefab.AddComponent<NonWorkingUserNetworkVariableComponent>();
|
||||
}
|
||||
|
||||
private bool CheckForClientInstance<T>() where T : WorkingUserNetworkVariableComponentBase
|
||||
{
|
||||
var instance = WorkingUserNetworkVariableComponentBase.GetRelativeInstance<T>(m_ClientNetworkManagers[0].LocalClientId);
|
||||
return instance != null && instance.IsSpawned;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WhenUsingAUserSerializableNetworkVariableWithUserSerialization_ReplicationWorks()
|
||||
{
|
||||
UserNetworkVariableSerialization<MyTypeOne>.WriteValue = (FastBufferWriter writer, in MyTypeOne value) =>
|
||||
{
|
||||
writer.WriteValueSafe(value.Value);
|
||||
};
|
||||
UserNetworkVariableSerialization<MyTypeOne>.ReadValue = (FastBufferReader reader, out MyTypeOne value) =>
|
||||
{
|
||||
value = new MyTypeOne();
|
||||
reader.ReadValueSafe(out value.Value);
|
||||
};
|
||||
UserNetworkVariableSerialization<MyTypeOne>.DuplicateValue = (in MyTypeOne value, ref MyTypeOne duplicatedValue) =>
|
||||
{
|
||||
duplicatedValue = value;
|
||||
};
|
||||
|
||||
var serverObject = SpawnObject(m_WorkingPrefab, m_ServerNetworkManager);
|
||||
var serverNetworkObject = serverObject.GetComponent<NetworkObject>();
|
||||
|
||||
// Wait for the client instance to be spawned, which removes the need to check for two NetworkVariableDeltaMessages
|
||||
yield return WaitForConditionOrTimeOut(() => CheckForClientInstance<WorkingUserNetworkVariableComponent>());
|
||||
AssertOnTimeout($"Timed out waiting for the client side object to spawn!");
|
||||
|
||||
// Get server and client instances of the test component
|
||||
var clientInstance = WorkingUserNetworkVariableComponentBase.GetRelativeInstance<WorkingUserNetworkVariableComponent>(m_ClientNetworkManagers[0].LocalClientId);
|
||||
var serverInstance = serverNetworkObject.GetComponent<WorkingUserNetworkVariableComponent>();
|
||||
|
||||
// Set the server side value
|
||||
serverInstance.NetworkVariable.Value = new MyTypeOne { Value = 20 };
|
||||
|
||||
// Wait for the NetworkVariableDeltaMessage
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived<NetworkVariableDeltaMessage>(m_ClientNetworkManagers[0]);
|
||||
|
||||
// Wait for the client side value to be updated to the server side value (can take an additional frame)
|
||||
yield return WaitForConditionOrTimeOut(() => clientInstance.NetworkVariable.Value.Value == serverInstance.NetworkVariable.Value.Value);
|
||||
Assert.AreEqual(serverNetworkObject.GetComponent<WorkingUserNetworkVariableComponent>().NetworkVariable.Value.Value, clientInstance.NetworkVariable.Value.Value);
|
||||
Assert.AreEqual(20, clientInstance.NetworkVariable.Value.Value);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WhenUsingAUserSerializableNetworkVariableWithUserSerializationViaExtensionMethod_ReplicationWorks()
|
||||
{
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.WriteValue = NetworkVariableUserSerializableTypesTestsExtensionMethods.WriteValueSafe;
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.ReadValue = NetworkVariableUserSerializableTypesTestsExtensionMethods.ReadValueSafe;
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.DuplicateValue = (in MyTypeTwo value, ref MyTypeTwo duplicatedValue) =>
|
||||
{
|
||||
duplicatedValue = value;
|
||||
};
|
||||
|
||||
var serverObject = SpawnObject(m_ExtensionMethodPrefab, m_ServerNetworkManager);
|
||||
var serverNetworkObject = serverObject.GetComponent<NetworkObject>();
|
||||
|
||||
// Wait for the client instance to be spawned, which removes the need to check for two NetworkVariableDeltaMessages
|
||||
yield return WaitForConditionOrTimeOut(() => CheckForClientInstance<WorkingUserNetworkVariableComponentUsingExtensionMethod>());
|
||||
AssertOnTimeout($"Timed out waiting for the client side object to spawn!");
|
||||
|
||||
// Get server and client instances of the test component
|
||||
var clientInstance = WorkingUserNetworkVariableComponentBase.GetRelativeInstance<WorkingUserNetworkVariableComponentUsingExtensionMethod>(m_ClientNetworkManagers[0].LocalClientId);
|
||||
var serverInstance = serverNetworkObject.GetComponent<WorkingUserNetworkVariableComponentUsingExtensionMethod>();
|
||||
// Set the server side value
|
||||
serverInstance.NetworkVariable.Value = new MyTypeTwo { Value = 20 };
|
||||
|
||||
// Wait for the NetworkVariableDeltaMessage
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived<NetworkVariableDeltaMessage>(m_ClientNetworkManagers[0]);
|
||||
|
||||
// Wait for the client side value to be updated to the server side value (can take an additional frame)
|
||||
yield return WaitForConditionOrTimeOut(() => clientInstance.NetworkVariable.Value.Value == serverInstance.NetworkVariable.Value.Value);
|
||||
AssertOnTimeout($"Timed out waiting for the client side object's value ({clientInstance.NetworkVariable.Value.Value}) to equal the server side objects value ({serverInstance.NetworkVariable.Value.Value})!");
|
||||
Assert.AreEqual(serverInstance.NetworkVariable.Value.Value, clientInstance.NetworkVariable.Value.Value);
|
||||
Assert.AreEqual(20, clientInstance.NetworkVariable.Value.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenUsingAUserSerializableNetworkVariableWithoutUserSerialization_ReplicationFails()
|
||||
{
|
||||
var serverObject = Object.Instantiate(m_NonWorkingPrefab);
|
||||
var serverNetworkObject = serverObject.GetComponent<NetworkObject>();
|
||||
serverNetworkObject.NetworkManagerOwner = m_ServerNetworkManager;
|
||||
Assert.Throws<ArgumentException>(
|
||||
() =>
|
||||
{
|
||||
serverNetworkObject.Spawn();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected override IEnumerator OnTearDown()
|
||||
{
|
||||
// These have to get set to SOMETHING, otherwise we will get an exception thrown because Object.Destroy()
|
||||
// calls __initializeNetworkVariables, and the network variable initialization attempts to call FallbackSerializer<T>,
|
||||
// which throws an exception if any of these values are null. They don't have to DO anything, they just have to
|
||||
// be non-null to keep the test from failing during teardown.
|
||||
// None of this is related to what's being tested above, and in reality, these values being null is an invalid
|
||||
// use case. But one of the tests is explicitly testing that invalid use case, and the values are being set
|
||||
// to null in OnSetup to ensure test isolation. This wouldn't be a situation a user would have to think about
|
||||
// in a real world use case.
|
||||
UserNetworkVariableSerialization<MyTypeOne>.WriteValue = (FastBufferWriter writer, in MyTypeOne value) => { };
|
||||
UserNetworkVariableSerialization<MyTypeOne>.ReadValue = (FastBufferReader reader, out MyTypeOne value) => { value = new MyTypeOne(); };
|
||||
UserNetworkVariableSerialization<MyTypeOne>.DuplicateValue = (in MyTypeOne value, ref MyTypeOne duplicatedValue) =>
|
||||
{
|
||||
duplicatedValue = value;
|
||||
};
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.WriteValue = (FastBufferWriter writer, in MyTypeTwo value) => { };
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.ReadValue = (FastBufferReader reader, out MyTypeTwo value) => { value = new MyTypeTwo(); };
|
||||
UserNetworkVariableSerialization<MyTypeTwo>.DuplicateValue = (in MyTypeTwo value, ref MyTypeTwo duplicatedValue) =>
|
||||
{
|
||||
duplicatedValue = value;
|
||||
};
|
||||
UserNetworkVariableSerialization<MyTypeThree>.WriteValue = (FastBufferWriter writer, in MyTypeThree value) => { };
|
||||
UserNetworkVariableSerialization<MyTypeThree>.ReadValue = (FastBufferReader reader, out MyTypeThree value) => { value = new MyTypeThree(); };
|
||||
UserNetworkVariableSerialization<MyTypeThree>.DuplicateValue = (in MyTypeThree value, ref MyTypeThree duplicatedValue) =>
|
||||
{
|
||||
duplicatedValue = value;
|
||||
};
|
||||
return base.OnTearDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1195640cf744e85b58c5af6d11eeb34
|
||||
timeCreated: 1652907276
|
||||
114
Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs
Normal file
114
Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
// This is a bit of a quirky test.
|
||||
// Addresses MTT-4386 #2109
|
||||
// Where the NetworkVariable updates would be repeated on some clients.
|
||||
// The twist comes fom the updates needing to happens very specifically for the issue to repro in tests
|
||||
|
||||
internal class OwnerModifiedObject : NetworkBehaviour, INetworkUpdateSystem
|
||||
{
|
||||
public NetworkList<int> MyNetworkList;
|
||||
|
||||
internal static int Updates = 0;
|
||||
|
||||
public static bool EnableVerbose;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
MyNetworkList = new NetworkList<int>(new List<int>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
|
||||
MyNetworkList.OnListChanged += Changed;
|
||||
}
|
||||
|
||||
public void Changed(NetworkListEvent<int> listEvent)
|
||||
{
|
||||
var expected = 0;
|
||||
var listString = "";
|
||||
foreach (var i in MyNetworkList)
|
||||
{
|
||||
Assert.AreEqual(i, expected);
|
||||
expected++;
|
||||
listString += i.ToString();
|
||||
}
|
||||
if (EnableVerbose)
|
||||
{
|
||||
Debug.Log($"[{NetworkManager.LocalClientId}] Value changed to {listString}");
|
||||
}
|
||||
|
||||
Updates++;
|
||||
}
|
||||
|
||||
public bool AddValues;
|
||||
|
||||
public NetworkUpdateStage NetworkUpdateStageToCheck;
|
||||
|
||||
private int m_ValueToUpdate;
|
||||
|
||||
public void NetworkUpdate(NetworkUpdateStage updateStage)
|
||||
{
|
||||
if (updateStage == NetworkUpdateStageToCheck)
|
||||
{
|
||||
if (AddValues)
|
||||
{
|
||||
MyNetworkList.Add(m_ValueToUpdate++);
|
||||
AddValues = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
NetworkUpdateLoop.UnregisterAllNetworkUpdates(this);
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
public void InitializeLastCient()
|
||||
{
|
||||
NetworkUpdateLoop.RegisterAllNetworkUpdates(this);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture(HostOrServer.DAHost)]
|
||||
[TestFixture(HostOrServer.Host)]
|
||||
internal class OwnerModifiedTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
public OwnerModifiedTests(HostOrServer hostOrServer) : base(hostOrServer) { }
|
||||
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<OwnerModifiedObject>();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator OwnerModifiedTest()
|
||||
{
|
||||
OwnerModifiedObject.EnableVerbose = m_EnableVerboseDebug;
|
||||
// We use this to assure we are the "last client" connected.
|
||||
yield return CreateAndStartNewClient();
|
||||
var ownerModLastClient = m_ClientNetworkManagers[2].LocalClient.PlayerObject.GetComponent<OwnerModifiedObject>();
|
||||
ownerModLastClient.InitializeLastCient();
|
||||
|
||||
// Run through all update loops setting the value once every 5 frames
|
||||
foreach (var updateLoopType in System.Enum.GetValues(typeof(NetworkUpdateStage)))
|
||||
{
|
||||
ownerModLastClient.NetworkUpdateStageToCheck = (NetworkUpdateStage)updateLoopType;
|
||||
VerboseDebug($"Testing Update Stage: {ownerModLastClient.NetworkUpdateStageToCheck}");
|
||||
ownerModLastClient.AddValues = true;
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 5);
|
||||
}
|
||||
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 5);
|
||||
|
||||
// We'll have at least one update per stage per client, if all goes well.
|
||||
Assert.True(OwnerModifiedObject.Updates > 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs.meta
Normal file
11
Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 419d83ebac7544ea9b0a9d5c3eab2c71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
181
Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs
Normal file
181
Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
internal class OwnerPermissionObject : NetworkBehaviour
|
||||
{
|
||||
// indexed by [object, machine]
|
||||
public static OwnerPermissionObject[,] Objects = new OwnerPermissionObject[3, 3];
|
||||
public static int CurrentlySpawning = 0;
|
||||
|
||||
public static List<OwnerPermissionObject> ClientTargetedNetworkObjects = new List<OwnerPermissionObject>();
|
||||
// a client-owned NetworkVariable
|
||||
public NetworkVariable<int> MyNetworkVariableOwner;
|
||||
// a server-owned NetworkVariable
|
||||
public NetworkVariable<int> MyNetworkVariableServer;
|
||||
|
||||
// a client-owned NetworkVariable
|
||||
public NetworkList<int> MyNetworkListOwner;
|
||||
// a server-owned NetworkVariable
|
||||
public NetworkList<int> MyNetworkListServer;
|
||||
|
||||
// verifies two lists are identical
|
||||
public static void CheckLists(NetworkList<int> listA, NetworkList<int> listB)
|
||||
{
|
||||
Debug.Assert(listA.Count == listB.Count);
|
||||
for (var i = 0; i < listA.Count; i++)
|
||||
{
|
||||
Debug.Assert(listA[i] == listB[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// verifies all objects have consistent lists on all clients
|
||||
public static void VerifyConsistency()
|
||||
{
|
||||
for (var objectIndex = 0; objectIndex < 3; objectIndex++)
|
||||
{
|
||||
CheckLists(Objects[objectIndex, 0].MyNetworkListOwner, Objects[objectIndex, 1].MyNetworkListOwner);
|
||||
CheckLists(Objects[objectIndex, 0].MyNetworkListOwner, Objects[objectIndex, 2].MyNetworkListOwner);
|
||||
|
||||
CheckLists(Objects[objectIndex, 0].MyNetworkListServer, Objects[objectIndex, 1].MyNetworkListServer);
|
||||
CheckLists(Objects[objectIndex, 0].MyNetworkListServer, Objects[objectIndex, 2].MyNetworkListServer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
Objects[CurrentlySpawning, NetworkManager.LocalClientId] = GetComponent<OwnerPermissionObject>();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
MyNetworkVariableOwner = new NetworkVariable<int>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
MyNetworkVariableOwner.OnValueChanged += OwnerChanged;
|
||||
|
||||
MyNetworkVariableServer = new NetworkVariable<int>(writePerm: NetworkVariableWritePermission.Server);
|
||||
MyNetworkVariableServer.OnValueChanged += ServerChanged;
|
||||
|
||||
MyNetworkListOwner = new NetworkList<int>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
MyNetworkListOwner.OnListChanged += ListOwnerChanged;
|
||||
|
||||
MyNetworkListServer = new NetworkList<int>(writePerm: NetworkVariableWritePermission.Server);
|
||||
MyNetworkListServer.OnListChanged += ListServerChanged;
|
||||
}
|
||||
|
||||
public void OwnerChanged(int before, int after)
|
||||
{
|
||||
}
|
||||
|
||||
public void ServerChanged(int before, int after)
|
||||
{
|
||||
}
|
||||
|
||||
public void ListOwnerChanged(NetworkListEvent<int> listEvent)
|
||||
{
|
||||
}
|
||||
|
||||
public void ListServerChanged(NetworkListEvent<int> listEvent)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal class OwnerPermissionHideTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
private GameObject m_PrefabToSpawn;
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_PrefabToSpawn = CreateNetworkObjectPrefab("OwnerPermissionObject");
|
||||
m_PrefabToSpawn.AddComponent<OwnerPermissionObject>();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator OwnerPermissionTest()
|
||||
{
|
||||
// create 3 objects
|
||||
for (var objectIndex = 0; objectIndex < 3; objectIndex++)
|
||||
{
|
||||
OwnerPermissionObject.CurrentlySpawning = objectIndex;
|
||||
|
||||
NetworkManager ownerManager = m_ServerNetworkManager;
|
||||
if (objectIndex != 0)
|
||||
{
|
||||
ownerManager = m_ClientNetworkManagers[objectIndex - 1];
|
||||
}
|
||||
SpawnObject(m_PrefabToSpawn, ownerManager);
|
||||
|
||||
// wait for each object to spawn on each client
|
||||
for (var clientIndex = 0; clientIndex < 3; clientIndex++)
|
||||
{
|
||||
while (OwnerPermissionObject.Objects[objectIndex, clientIndex] == null)
|
||||
{
|
||||
yield return new WaitForSeconds(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var nextValueToWrite = 1;
|
||||
var serverIndex = 0;
|
||||
|
||||
for (var objectIndex = 0; objectIndex < 3; objectIndex++)
|
||||
{
|
||||
for (var clientWriting = 0; clientWriting < 3; clientWriting++)
|
||||
{
|
||||
// ==== Server-writable NetworkVariable ====
|
||||
VerboseDebug($"Writing to server-write variable on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
nextValueToWrite++;
|
||||
if (clientWriting != serverIndex)
|
||||
{
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.GetWritePermissionError());
|
||||
}
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.Value = nextValueToWrite;
|
||||
|
||||
// ==== Owner-writable NetworkVariable ====
|
||||
VerboseDebug($"Writing to owner-write variable on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
nextValueToWrite++;
|
||||
if (clientWriting != objectIndex)
|
||||
{
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.GetWritePermissionError());
|
||||
}
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.Value = nextValueToWrite;
|
||||
|
||||
// ==== Server-writable NetworkList ====
|
||||
VerboseDebug($"Writing to [Add] server-write NetworkList on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
nextValueToWrite++;
|
||||
if (clientWriting != serverIndex)
|
||||
{
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.GetWritePermissionError());
|
||||
}
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.Add(nextValueToWrite);
|
||||
|
||||
// ==== Owner-writable NetworkList ====
|
||||
VerboseDebug($"Writing to [Add] owner-write NetworkList on object {objectIndex} on client {clientWriting}");
|
||||
|
||||
nextValueToWrite++;
|
||||
if (clientWriting != objectIndex)
|
||||
{
|
||||
LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.GetWritePermissionError());
|
||||
}
|
||||
OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.Add(nextValueToWrite);
|
||||
|
||||
yield return WaitForTicks(m_ServerNetworkManager, 5);
|
||||
yield return WaitForTicks(m_ClientNetworkManagers[0], 5);
|
||||
yield return WaitForTicks(m_ClientNetworkManagers[1], 5);
|
||||
|
||||
OwnerPermissionObject.VerifyConsistency();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs.meta
Normal file
11
Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88c657dcbe9a2414ba551b60dab19acd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user