fix: Fixed instability issues in the tests and optimized them so they would not take as long to run. (#2860)

This commit is contained in:
Kitty Draper 2024-04-03 16:14:29 -05:00 коммит произвёл GitHub
Родитель 0c70ae30b4
Коммит b097d74947
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
11 изменённых файлов: 1010 добавлений и 605 удалений

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Unity.Collections;
using Random = UnityEngine.Random;
namespace Unity.Netcode.TestHelpers.Runtime
@ -9,12 +10,14 @@ namespace Unity.Netcode.TestHelpers.Runtime
private struct MessageData
{
public ulong FromClientId;
public ArraySegment<byte> Payload;
public FastBufferReader Payload;
public NetworkEvent Event;
public float AvailableTime;
public int Sequence;
public NetworkDelivery Delivery;
}
private static Dictionary<ulong, Queue<MessageData>> s_MessageQueue = new Dictionary<ulong, Queue<MessageData>>();
private static Dictionary<ulong, List<MessageData>> s_MessageQueue = new Dictionary<ulong, List<MessageData>>();
public override ulong ServerClientId { get; } = 0;
@ -25,39 +28,89 @@ namespace Unity.Netcode.TestHelpers.Runtime
public float PacketDropRate;
public float LatencyJitter;
public Dictionary<ulong, int> LastSentSequence = new Dictionary<ulong, int>();
public Dictionary<ulong, int> LastReceivedSequence = new Dictionary<ulong, int>();
public NetworkManager NetworkManager;
public override void Send(ulong clientId, ArraySegment<byte> payload, NetworkDelivery networkDelivery)
{
if (Random.Range(0, 1) < PacketDropRate)
if ((networkDelivery == NetworkDelivery.Unreliable || networkDelivery == NetworkDelivery.UnreliableSequenced) && Random.Range(0, 1) < PacketDropRate)
{
return;
}
var copy = new byte[payload.Array.Length];
Array.Copy(payload.Array, copy, payload.Array.Length);
s_MessageQueue[clientId].Enqueue(new MessageData { FromClientId = TransportId, Payload = new ArraySegment<byte>(copy, payload.Offset, payload.Count), Event = NetworkEvent.Data, AvailableTime = NetworkManager.RealTimeProvider.UnscaledTime + SimulatedLatencySeconds + Random.Range(-LatencyJitter, LatencyJitter) });
if (!LastSentSequence.ContainsKey(clientId))
{
LastSentSequence[clientId] = 1;
}
var reader = new FastBufferReader(payload, Allocator.TempJob);
s_MessageQueue[clientId].Add(new MessageData
{
FromClientId = TransportId,
Payload = reader,
Event = NetworkEvent.Data,
AvailableTime = NetworkManager.RealTimeProvider.UnscaledTime + SimulatedLatencySeconds + Random.Range(-LatencyJitter, LatencyJitter),
Sequence = ++LastSentSequence[clientId],
Delivery = networkDelivery
});
s_MessageQueue[clientId].Sort(((a, b) => a.AvailableTime.CompareTo(b.AvailableTime)));
}
public override NetworkEvent PollEvent(out ulong clientId, out ArraySegment<byte> payload, out float receiveTime)
{
if (s_MessageQueue[TransportId].Count > 0)
{
var data = s_MessageQueue[TransportId].Peek();
if (data.AvailableTime > NetworkManager.RealTimeProvider.UnscaledTime)
MessageData data;
for (; ; )
{
clientId = 0;
payload = new ArraySegment<byte>();
receiveTime = 0;
return NetworkEvent.Nothing;
data = s_MessageQueue[TransportId][0];
if (data.AvailableTime > NetworkManager.RealTimeProvider.UnscaledTime)
{
clientId = 0;
payload = new ArraySegment<byte>();
receiveTime = 0;
return NetworkEvent.Nothing;
}
s_MessageQueue[TransportId].RemoveAt(0);
clientId = data.FromClientId;
if (data.Event == NetworkEvent.Data && data.Delivery == NetworkDelivery.UnreliableSequenced && LastReceivedSequence.ContainsKey(clientId) && data.Sequence <= LastReceivedSequence[clientId])
{
continue;
}
break;
}
if (data.Delivery == NetworkDelivery.UnreliableSequenced)
{
LastReceivedSequence[clientId] = data.Sequence;
}
payload = new ArraySegment<byte>();
if (data.Event == NetworkEvent.Data)
{
payload = data.Payload.ToArray();
data.Payload.Dispose();
}
s_MessageQueue[TransportId].Dequeue();
clientId = data.FromClientId;
payload = data.Payload;
receiveTime = NetworkManager.RealTimeProvider.RealTimeSinceStartup;
if (NetworkManager.IsServer && data.Event == NetworkEvent.Connect)
{
s_MessageQueue[data.FromClientId].Enqueue(new MessageData { Event = NetworkEvent.Connect, FromClientId = ServerClientId, Payload = new ArraySegment<byte>() });
if (!LastSentSequence.ContainsKey(data.FromClientId))
{
LastSentSequence[data.FromClientId] = 1;
}
s_MessageQueue[data.FromClientId].Add(
new MessageData
{
Event = NetworkEvent.Connect,
FromClientId = ServerClientId,
AvailableTime = NetworkManager.RealTimeProvider.UnscaledTime + SimulatedLatencySeconds + Random.Range(-LatencyJitter, LatencyJitter),
Sequence = ++LastSentSequence[data.FromClientId]
});
}
return data.Event;
}
@ -70,30 +123,45 @@ namespace Unity.Netcode.TestHelpers.Runtime
public override bool StartClient()
{
TransportId = ++HighTransportId;
s_MessageQueue[TransportId] = new Queue<MessageData>();
s_MessageQueue[ServerClientId].Enqueue(new MessageData { Event = NetworkEvent.Connect, FromClientId = TransportId, Payload = new ArraySegment<byte>() });
s_MessageQueue[TransportId] = new List<MessageData>();
s_MessageQueue[ServerClientId].Add(
new MessageData
{
Event = NetworkEvent.Connect,
FromClientId = TransportId,
});
return true;
}
public override bool StartServer()
{
s_MessageQueue[ServerClientId] = new Queue<MessageData>();
s_MessageQueue[ServerClientId] = new List<MessageData>();
return true;
}
public override void DisconnectRemoteClient(ulong clientId)
{
s_MessageQueue[clientId].Enqueue(new MessageData { Event = NetworkEvent.Disconnect, FromClientId = TransportId, Payload = new ArraySegment<byte>() });
s_MessageQueue[clientId].Add(
new MessageData
{
Event = NetworkEvent.Disconnect,
FromClientId = TransportId,
});
}
public override void DisconnectLocalClient()
{
s_MessageQueue[ServerClientId].Enqueue(new MessageData { Event = NetworkEvent.Disconnect, FromClientId = TransportId, Payload = new ArraySegment<byte>() });
s_MessageQueue[ServerClientId].Add(
new MessageData
{
Event = NetworkEvent.Disconnect,
FromClientId = TransportId,
});
}
public override ulong GetCurrentRtt(ulong clientId)
{
return 0;
return (ulong)(SimulatedLatencySeconds * 1000);
}
public override void Shutdown()
@ -105,14 +173,30 @@ namespace Unity.Netcode.TestHelpers.Runtime
NetworkManager = networkManager;
}
protected static void DisposeQueueItems()
{
foreach (var kvp in s_MessageQueue)
{
foreach (var value in kvp.Value)
{
if (value.Event == NetworkEvent.Data)
{
value.Payload.Dispose();
}
}
}
}
public static void Reset()
{
DisposeQueueItems();
s_MessageQueue.Clear();
HighTransportId = 0;
}
public static void ClearQueues()
{
DisposeQueueItems();
foreach (var kvp in s_MessageQueue)
{
kvp.Value.Clear();

Просмотреть файл

@ -542,10 +542,7 @@ namespace Unity.Netcode.TestHelpers.Runtime
protected IEnumerator StopOneClient(NetworkManager networkManager, bool destroy = false)
{
NetcodeIntegrationTestHelpers.StopOneClient(networkManager, destroy);
if (destroy)
{
AddRemoveNetworkManager(networkManager, false);
}
AddRemoveNetworkManager(networkManager, false);
yield return WaitForConditionOrTimeOut(() => !networkManager.IsConnectedClient);
}
@ -1043,6 +1040,17 @@ namespace Unity.Netcode.TestHelpers.Runtime
VerboseDebug($"Exiting {nameof(TearDown)}");
LogWaitForMessages();
NetcodeLogAssert.Dispose();
if (m_EnableTimeTravel)
{
if (m_NetworkManagerInstatiationMode == NetworkManagerInstatiationMode.AllTests)
{
MockTransport.ClearQueues();
}
else
{
MockTransport.Reset();
}
}
}
/// <summary>
@ -1592,8 +1600,17 @@ namespace Unity.Netcode.TestHelpers.Runtime
/// </summary>
/// <param name="amountOfTimeInSeconds"></param>
/// <param name="numFramesToSimulate"></param>
protected static void TimeTravel(double amountOfTimeInSeconds, int numFramesToSimulate)
protected static void TimeTravel(double amountOfTimeInSeconds, int numFramesToSimulate = -1)
{
if (numFramesToSimulate < 0)
{
var frameRate = Application.targetFrameRate;
if (frameRate <= 0)
{
frameRate = 60;
}
numFramesToSimulate = Math.Max((int)(amountOfTimeInSeconds / frameRate), 1);
}
var interval = amountOfTimeInSeconds / numFramesToSimulate;
for (var i = 0; i < numFramesToSimulate; ++i)
{
@ -1651,6 +1668,16 @@ namespace Unity.Netcode.TestHelpers.Runtime
TimeTravel(timePassed, frames);
}
private struct UpdateData
{
public MethodInfo Update;
public MethodInfo FixedUpdate;
public MethodInfo LateUpdate;
}
private static object[] s_EmptyObjectArray = { };
private static Dictionary<Type, UpdateData> s_UpdateFunctionCache = new Dictionary<Type, UpdateData>();
/// <summary>
/// Simulates one SDK frame. This can be used even without TimeTravel, though it's of somewhat less use
/// without TimeTravel, as, without the mock transport, it will likely not provide enough time for any
@ -1673,34 +1700,34 @@ namespace Unity.Netcode.TestHelpers.Runtime
stage = NetworkUpdateStage.PostScriptLateUpdate;
}
NetworkUpdateLoop.RunNetworkUpdateStage(stage);
string methodName = string.Empty;
switch (stage)
{
case NetworkUpdateStage.FixedUpdate:
methodName = "FixedUpdate"; // mapping NetworkUpdateStage.FixedUpdate to MonoBehaviour.FixedUpdate
break;
case NetworkUpdateStage.Update:
methodName = "Update"; // mapping NetworkUpdateStage.Update to MonoBehaviour.Update
break;
case NetworkUpdateStage.PreLateUpdate:
methodName = "LateUpdate"; // mapping NetworkUpdateStage.PreLateUpdate to MonoBehaviour.LateUpdate
break;
}
if (!string.IsNullOrEmpty(methodName))
if (stage == NetworkUpdateStage.Update || stage == NetworkUpdateStage.FixedUpdate || stage == NetworkUpdateStage.PreLateUpdate)
{
#if UNITY_2023_1_OR_NEWER
foreach (var obj in Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.InstanceID))
#else
foreach (var obj in Object.FindObjectsOfType<NetworkObject>())
#endif
foreach (var behaviour in Object.FindObjectsByType<NetworkBehaviour>(FindObjectsSortMode.None))
{
var method = obj.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
method?.Invoke(obj, new object[] { });
foreach (var behaviour in obj.ChildNetworkBehaviours)
var type = behaviour.GetType();
if (!s_UpdateFunctionCache.TryGetValue(type, out var updateData))
{
var behaviourMethod = behaviour.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
behaviourMethod?.Invoke(behaviour, new object[] { });
updateData = new UpdateData
{
Update = type.GetMethod("Update", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance),
FixedUpdate = type.GetMethod("FixedUpdate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance),
LateUpdate = type.GetMethod("LateUpdate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance),
};
s_UpdateFunctionCache[type] = updateData;
}
switch (stage)
{
case NetworkUpdateStage.FixedUpdate:
updateData.FixedUpdate?.Invoke(behaviour, new object[] { });
break;
case NetworkUpdateStage.Update:
updateData.Update?.Invoke(behaviour, new object[] { });
break;
case NetworkUpdateStage.PreLateUpdate:
updateData.LateUpdate?.Invoke(behaviour, new object[] { });
break;
}
}
}

Просмотреть файл

@ -146,6 +146,8 @@ namespace Unity.Netcode.RuntimeTests
m_TransportClientId = m_ServerNetworkManager.ConnectionManager.ClientIdToTransportId(m_ClientId);
var clientManager = m_ClientNetworkManagers[0];
if (clientDisconnectType == ClientDisconnectType.ServerDisconnectsClient)
{
m_ClientNetworkManagers[0].OnClientDisconnectCallback += OnClientDisconnectCallback;
@ -169,8 +171,8 @@ namespace Unity.Netcode.RuntimeTests
{
Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ServerNetworkManager), $"Could not find the server {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent[m_ServerNetworkManager].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the server {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ClientNetworkManagers[0]), $"Could not find the client {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent[m_ClientNetworkManagers[0]].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the client {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent.ContainsKey(clientManager), $"Could not find the client {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent[clientManager].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the client {nameof(NetworkManager)} disconnect event entry!");
// Unregister for this event otherwise it will be invoked during teardown
m_ServerNetworkManager.OnConnectionEvent -= OnConnectionEvent;
}
@ -178,8 +180,8 @@ namespace Unity.Netcode.RuntimeTests
{
Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ServerNetworkManager), $"Could not find the server {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent[m_ServerNetworkManager].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the server {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ClientNetworkManagers[0]), $"Could not find the client {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent[m_ClientNetworkManagers[0]].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the client {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent.ContainsKey(clientManager), $"Could not find the client {nameof(NetworkManager)} disconnect event entry!");
Assert.IsTrue(m_DisconnectedEvent[clientManager].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the client {nameof(NetworkManager)} disconnect event entry!");
}
if (m_OwnerPersistence == OwnerPersistence.DestroyWithOwner)

Просмотреть файл

@ -1,10 +1,8 @@
// TODO: Rewrite test to use the tools package. Debug simulator not available in UTP 2.X.
#if !UTP_TRANSPORT_2_0_ABOVE
using System.Collections;
using NUnit.Framework;
using Unity.Netcode.Components;
using UnityEngine;
using UnityEngine.TestTools;
namespace Unity.Netcode.RuntimeTests
{
@ -38,32 +36,37 @@ namespace Unity.Netcode.RuntimeTests
base(testWithHost, authority, rotationCompression, rotation, precision)
{ }
protected override void OnServerAndClientsCreated()
{
base.OnServerAndClientsCreated();
protected override bool m_EnableTimeTravel => true;
protected override bool m_SetupIsACoroutine => true;
protected override bool m_TearDownIsACoroutine => true;
var unityTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as Transports.UTP.UnityTransport;
unityTransport.SetDebugSimulatorParameters(k_Latency, 0, k_PacketLoss);
protected override void OnTimeTravelServerAndClientsConnected()
{
base.OnTimeTravelServerAndClientsConnected();
SetTimeTravelSimulatedLatency(k_Latency * 0.001f);
SetTimeTravelSimulatedDropRate(k_PacketLoss * 0.01f);
}
/// <summary>
/// Handles validating all children of the test objects have matching local and global space vaues.
/// </summary>
private IEnumerator AllChildrenLocalTransformValuesMatch(bool useSubChild, ChildrenTransformCheckType checkType)
private void AllChildrenLocalTransformValuesMatch(bool useSubChild, ChildrenTransformCheckType checkType)
{
// We don't assert on timeout here because we want to log this information during PostAllChildrenLocalTransformValuesMatch
yield return WaitForConditionOrTimeOut(() => AllInstancesKeptLocalTransformValues(useSubChild));
WaitForConditionOrTimeOutWithTimeTravel(() => AllInstancesKeptLocalTransformValues(useSubChild));
var success = true;
m_InfoMessage.AppendLine($"[{checkType}][{useSubChild}] Timed out waiting for all children to have the correct local space values:\n");
if (s_GlobalTimeoutHelper.TimedOut)
{
var waitForMs = new WaitForSeconds(0.001f);
//var waitForMs = new WaitForSeconds(0.001f);
// If we timed out, then wait for a full range of ticks to assure all data has been synchronized before declaring this a failed test.
for (int j = 0; j < m_ServerNetworkManager.NetworkConfig.TickRate; j++)
{
var instances = useSubChild ? ChildObjectComponent.SubInstances : ChildObjectComponent.Instances;
success = PostAllChildrenLocalTransformValuesMatch(useSubChild);
yield return waitForMs;
TimeTravel(0.001f);
//yield return waitForMs;
}
}
@ -78,8 +81,8 @@ namespace Unity.Netcode.RuntimeTests
/// parented under another NetworkTransform under all of the possible axial conditions
/// as well as when the parent has a varying scale.
/// </summary>
[UnityTest]
public IEnumerator ParentedNetworkTransformTest([Values] Interpolation interpolation, [Values] bool worldPositionStays, [Values(0.5f, 1.0f, 5.0f)] float scale)
[Test]
public void ParentedNetworkTransformTest([Values] Interpolation interpolation, [Values] bool worldPositionStays, [Values(0.5f, 1.0f, 5.0f)] float scale)
{
ChildObjectComponent.EnableChildLog = m_EnableVerboseDebug;
if (m_EnableVerboseDebug)
@ -101,7 +104,7 @@ namespace Unity.Netcode.RuntimeTests
var serverSideSubChild = SpawnObject(m_SubChildObject.gameObject, authorityNetworkManager).GetComponent<NetworkObject>();
// Assure all of the child object instances are spawned before proceeding to parenting
yield return WaitForConditionOrTimeOut(AllChildObjectInstancesAreSpawned);
WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesAreSpawned);
AssertOnTimeout("Timed out waiting for all child instances to be spawned!");
// Get the authority parent and child instances
@ -139,7 +142,7 @@ namespace Unity.Netcode.RuntimeTests
// Allow one tick for authority to update these changes
yield return WaitForConditionOrTimeOut(PositionRotationScaleMatches);
WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches);
AssertOnTimeout("All transform values did not match prior to parenting!");
@ -150,37 +153,37 @@ namespace Unity.Netcode.RuntimeTests
Assert.True(serverSideSubChild.TrySetParent(serverSideChild.transform, worldPositionStays), "[Server-Side SubChild] Failed to set sub-child's parent!");
// This waits for all child instances to be parented
yield return WaitForConditionOrTimeOut(AllChildObjectInstancesHaveChild);
WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesHaveChild);
AssertOnTimeout("Timed out waiting for all instances to have parented a child!");
var latencyWait = new WaitForSeconds(k_Latency * 0.003f);
var latencyWait = k_Latency * 0.003f;
// Wait for at least 3x designated latency period
yield return latencyWait;
TimeTravel(latencyWait);
// This validates each child instance has preserved their local space values
yield return AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Connected_Clients);
AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Connected_Clients);
// This validates each sub-child instance has preserved their local space values
yield return AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Connected_Clients);
AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Connected_Clients);
// Verify that a late joining client will synchronize to the parented NetworkObjects properly
yield return CreateAndStartNewClient();
CreateAndStartNewClientWithTimeTravel();
// Assure all of the child object instances are spawned (basically for the newly connected client)
yield return WaitForConditionOrTimeOut(AllChildObjectInstancesAreSpawned);
WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesAreSpawned);
AssertOnTimeout("Timed out waiting for all child instances to be spawned!");
// This waits for all child instances to be parented
yield return WaitForConditionOrTimeOut(AllChildObjectInstancesHaveChild);
WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesHaveChild);
AssertOnTimeout("Timed out waiting for all instances to have parented a child!");
// Wait for at least 3x designated latency period
yield return latencyWait;
TimeTravel(latencyWait);
// This validates each child instance has preserved their local space values
yield return AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Late_Join_Client);
AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Late_Join_Client);
// This validates each sub-child instance has preserved their local space values
yield return AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Late_Join_Client);
AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Late_Join_Client);
}
/// <summary>
@ -192,10 +195,10 @@ namespace Unity.Netcode.RuntimeTests
/// When testing 3 axis: Interpolation is enabled, sometimes an axis is intentionally excluded during a
/// delta update, and it runs through 8 delta updates per unique test.
/// </remarks>
[UnityTest]
public IEnumerator NetworkTransformMultipleChangesOverTime([Values] TransformSpace testLocalTransform, [Values] Axis axis)
[Test]
public void NetworkTransformMultipleChangesOverTime([Values] TransformSpace testLocalTransform, [Values] Axis axis)
{
yield return s_DefaultWaitForTick;
TimeTravelAdvanceTick();
// Just test for OverrideState.Update (they are already being tested for functionality in normal NetworkTransformTests)
var overideState = OverrideState.Update;
var tickRelativeTime = new WaitForSeconds(1.0f / m_ServerNetworkManager.NetworkConfig.TickRate);
@ -255,7 +258,7 @@ namespace Unity.Netcode.RuntimeTests
// Wait for the deltas to be pushed
yield return WaitForConditionOrTimeOut(() => m_AuthoritativeTransform.StatePushed);
WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed);
// Just in case we drop the first few state updates
if (s_GlobalTimeoutHelper.TimedOut)
@ -266,17 +269,17 @@ namespace Unity.Netcode.RuntimeTests
state.InLocalSpace = !m_AuthoritativeTransform.InLocalSpace;
m_AuthoritativeTransform.LocalAuthoritativeNetworkState = state;
// Wait for the deltas to be pushed
yield return WaitForConditionOrTimeOut(() => m_AuthoritativeTransform.StatePushed);
WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed);
}
AssertOnTimeout("State was never pushed!");
// Allow the precision settings to propagate first as changing precision
// causes a teleport event to occur
yield return s_DefaultWaitForTick;
yield return s_DefaultWaitForTick;
yield return s_DefaultWaitForTick;
yield return s_DefaultWaitForTick;
yield return s_DefaultWaitForTick;
TimeTravelAdvanceTick();
TimeTravelAdvanceTick();
TimeTravelAdvanceTick();
TimeTravelAdvanceTick();
TimeTravelAdvanceTick();
var iterations = axisCount == 3 ? k_PositionRotationScaleIterations3Axis : k_PositionRotationScaleIterations;
// Move and rotate within the same tick, validate the non-authoritative instance updates
@ -311,7 +314,7 @@ namespace Unity.Netcode.RuntimeTests
MoveRotateAndScaleAuthority(position, rotation, scale, overideState);
// Wait for the deltas to be pushed (unlike the original test, we don't wait for state to be updated as that could be dropped here)
yield return WaitForConditionOrTimeOut(() => m_AuthoritativeTransform.StatePushed);
WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed);
AssertOnTimeout($"[Non-Interpolate {i}] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed})!");
// For 3 axis, we will skip validating that the non-authority interpolates to its target point at least once.
@ -321,7 +324,7 @@ namespace Unity.Netcode.RuntimeTests
if (m_AxisExcluded || axisCount < 3)
{
// Wait for deltas to synchronize on non-authoritative side
yield return WaitForConditionOrTimeOut(PositionRotationScaleMatches);
WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches);
// Provide additional debug info about what failed (if it fails)
if (s_GlobalTimeoutHelper.TimedOut)
{
@ -335,7 +338,7 @@ namespace Unity.Netcode.RuntimeTests
// If we matched, then something was dropped and recovered when synchronized
break;
}
yield return s_DefaultWaitForTick;
TimeTravelAdvanceTick();
}
// Only if we still didn't match
@ -354,7 +357,7 @@ namespace Unity.Netcode.RuntimeTests
if (axisCount == 3)
{
// As a final test, wait for deltas to synchronize on non-authoritative side to assure it interpolates to the correct values
yield return WaitForConditionOrTimeOut(PositionRotationScaleMatches);
WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches);
// Provide additional debug info about what failed (if it fails)
if (s_GlobalTimeoutHelper.TimedOut)
{
@ -368,7 +371,7 @@ namespace Unity.Netcode.RuntimeTests
// If we matched, then something was dropped and recovered when synchronized
break;
}
yield return s_DefaultWaitForTick;
TimeTravelAdvanceTick();
}
// Only if we still didn't match
@ -392,8 +395,8 @@ namespace Unity.Netcode.RuntimeTests
/// - While in local space and world space
/// - While interpolation is enabled and disabled
/// </summary>
[UnityTest]
public IEnumerator TestAuthoritativeTransformChangeOneAtATime([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation)
[Test]
public void TestAuthoritativeTransformChangeOneAtATime([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation)
{
// Just test for OverrideState.Update (they are already being tested for functionality in normal NetworkTransformTests)
m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate;
@ -411,7 +414,7 @@ namespace Unity.Netcode.RuntimeTests
m_AuthoritativeTransform.transform.position = GetRandomVector3(2f, 30f);
yield return WaitForConditionOrTimeOut(() => PositionsMatch());
WaitForConditionOrTimeOutWithTimeTravel(() => PositionsMatch());
AssertOnTimeout($"Timed out waiting for positions to match {m_AuthoritativeTransform.transform.position} | {m_NonAuthoritativeTransform.transform.position}");
// test rotation
@ -420,19 +423,19 @@ namespace Unity.Netcode.RuntimeTests
m_AuthoritativeTransform.transform.rotation = Quaternion.Euler(GetRandomVector3(5, 60)); // using euler angles instead of quaternions directly to really see issues users might encounter
// Make sure the values match
yield return WaitForConditionOrTimeOut(() => RotationsMatch());
WaitForConditionOrTimeOutWithTimeTravel(() => RotationsMatch());
AssertOnTimeout($"Timed out waiting for rotations to match");
m_AuthoritativeTransform.StatePushed = false;
m_AuthoritativeTransform.transform.localScale = GetRandomVector3(1, 6);
// Make sure the scale values match
yield return WaitForConditionOrTimeOut(() => ScaleValuesMatch());
WaitForConditionOrTimeOutWithTimeTravel(() => ScaleValuesMatch());
AssertOnTimeout($"Timed out waiting for scale values to match");
}
[UnityTest]
public IEnumerator TestSameFrameDeltaStateAndTeleport([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation)
[Test]
public void TestSameFrameDeltaStateAndTeleport([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation)
{
m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate;
@ -449,10 +452,10 @@ namespace Unity.Netcode.RuntimeTests
m_RandomPosition = GetRandomVector3(2f, 30f);
m_AuthoritativeTransform.transform.position = m_RandomPosition;
m_Teleported = false;
yield return WaitForConditionOrTimeOut(() => m_Teleported);
WaitForConditionOrTimeOutWithTimeTravel(() => m_Teleported);
AssertOnTimeout($"Timed out waiting for random position to be pushed!");
yield return WaitForConditionOrTimeOut(() => PositionsMatch());
WaitForConditionOrTimeOutWithTimeTravel(() => PositionsMatch());
AssertOnTimeout($"Timed out waiting for positions to match {m_AuthoritativeTransform.transform.position} | {m_NonAuthoritativeTransform.transform.position}");
var authPosition = m_AuthoritativeTransform.GetSpaceRelativePosition();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,6 @@
#if !MULTIPLAYER_TOOLS && !NGO_MINIMALPROJECT
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -7,6 +9,7 @@ using NUnit.Framework;
using Unity.Collections;
using Unity.Netcode.TestHelpers.Runtime;
using UnityEngine;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;
using Random = System.Random;
@ -451,6 +454,9 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
public class UniversalRpcTestsBase : NetcodeIntegrationTest
{
public static int YieldCheck = 0;
public const int YieldCycleCount = 10;
protected override int NumberOfClients => 2;
public UniversalRpcTestsBase(HostOrServer hostOrServer) : base(hostOrServer)
@ -491,6 +497,7 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
protected override void OnInlineTearDown()
{
MockTransport.ClearQueues();
Clear();
}
@ -1168,27 +1175,40 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
}
[Test]
public void TestSendingWithSingleOverride(
[Values] SendTo defaultSendTo,
[Values(0u, 1u, 2u)] ulong recipient,
[Values(0u, 1u, 2u)] ulong objectOwner,
[Values(0u, 1u, 2u)] ulong sender
)
[UnityTest]
public IEnumerator TestSendingWithSingleOverride()
{
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
foreach (var defaultSendTo in Enum.GetValues(typeof(SendTo)))
{
for (ulong recipient = 0u; recipient <= 2u; ++recipient)
{
for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner)
{
for (ulong sender = 0u; sender <= 2u; ++sender)
{
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
var senderObject = GetPlayerObject(objectOwner, sender);
var target = senderObject.RpcTarget.Single(recipient, RpcTargetUse.Temp);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
var senderObject = GetPlayerObject(objectOwner, sender);
var target = senderObject.RpcTarget.Single(recipient, RpcTargetUse.Temp);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, new[] { recipient }, false);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray());
VerifyRemoteReceived(objectOwner, sender, sendMethodName, new[] { recipient }, false);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray());
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray());
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray());
OnInlineTearDown();
}
}
}
}
}
}
@ -1202,27 +1222,40 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
}
[Test]
public void TestSendingWithSingleNotOverride(
[Values] SendTo defaultSendTo,
[Values(0u, 1u, 2u)] ulong recipient,
[Values(0u, 1u, 2u)] ulong objectOwner,
[Values(0u, 1u, 2u)] ulong sender
)
[UnityTest]
public IEnumerator TestSendingWithSingleNotOverride()
{
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
foreach (var defaultSendTo in Enum.GetValues(typeof(SendTo)))
{
for (ulong recipient = 0u; recipient <= 2u; ++recipient)
{
for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner)
{
for (ulong sender = 0u; sender <= 2u; ++sender)
{
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
var senderObject = GetPlayerObject(objectOwner, sender);
var target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
var senderObject = GetPlayerObject(objectOwner, sender);
var target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient != c).ToArray(), false);
VerifyNotReceived(objectOwner, new[] { recipient });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient != c).ToArray(), false);
VerifyNotReceived(objectOwner, new[] { recipient });
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, new[] { recipient });
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, new[] { recipient });
OnInlineTearDown();
}
}
}
}
}
}
@ -1252,56 +1285,72 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
List
}
[Test]
public void TestSendingWithGroupOverride(
[Values] SendTo defaultSendTo,
[ValueSource(nameof(RecipientGroups))] ulong[] recipient,
[Values(0u, 1u, 2u)] ulong objectOwner,
[Values(0u, 1u, 2u)] ulong sender,
[Values] AllocationType allocationType
)
[UnityTest]
public IEnumerator TestSendingWithGroupOverride()
{
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
var senderObject = GetPlayerObject(objectOwner, sender);
BaseRpcTarget target = null;
switch (allocationType)
foreach (var defaultSendTo in Enum.GetValues(typeof(SendTo)))
{
case AllocationType.Array:
target = senderObject.RpcTarget.Group(recipient, RpcTargetUse.Temp);
break;
case AllocationType.List:
target = senderObject.RpcTarget.Group(recipient.ToList(), RpcTargetUse.Temp);
break;
case AllocationType.NativeArray:
var arr = new NativeArray<ulong>(recipient, Allocator.Temp);
target = senderObject.RpcTarget.Group(arr, RpcTargetUse.Temp);
arr.Dispose();
break;
case AllocationType.NativeList:
// For some reason on 2020.3, calling list.AsArray() and passing that to the next function
// causes Allocator.Temp allocations to become invalid somehow. This is not an issue on later
// versions of Unity.
var list = new NativeList<ulong>(recipient.Length, Allocator.TempJob);
foreach (var id in recipient)
foreach (var recipient in RecipientGroups)
{
for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner)
{
list.Add(id);
for (ulong sender = 0u; sender <= 2u; ++sender)
{
foreach (var allocationType in Enum.GetValues(typeof(AllocationType)))
{
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
var senderObject = GetPlayerObject(objectOwner, sender);
BaseRpcTarget target = null;
switch (allocationType)
{
case AllocationType.Array:
target = senderObject.RpcTarget.Group(recipient, RpcTargetUse.Temp);
break;
case AllocationType.List:
target = senderObject.RpcTarget.Group(recipient.ToList(), RpcTargetUse.Temp);
break;
case AllocationType.NativeArray:
var arr = new NativeArray<ulong>(recipient, Allocator.Temp);
target = senderObject.RpcTarget.Group(arr, RpcTargetUse.Temp);
arr.Dispose();
break;
case AllocationType.NativeList:
// For some reason on 2020.3, calling list.AsArray() and passing that to the next function
// causes Allocator.Temp allocations to become invalid somehow. This is not an issue on later
// versions of Unity.
var list = new NativeList<ulong>(recipient.Length, Allocator.TempJob);
foreach (var id in recipient)
{
list.Add(id);
}
target = senderObject.RpcTarget.Group(list, RpcTargetUse.Temp);
list.Dispose();
break;
}
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient.Contains(c)).ToArray(), false);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray());
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray());
OnInlineTearDown();
}
}
}
target = senderObject.RpcTarget.Group(list, RpcTargetUse.Temp);
list.Dispose();
break;
}
}
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient.Contains(c)).ToArray(), false);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray());
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray());
}
}
[TestFixture(HostOrServer.Host)]
@ -1329,54 +1378,69 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
List
}
[Test]
public void TestSendingWithGroupNotOverride(
[Values] SendTo defaultSendTo,
[ValueSource(nameof(RecipientGroups))] ulong[] recipient,
[Values(0u, 1u, 2u)] ulong objectOwner,
[Values(0u, 1u, 2u)] ulong sender,
[Values] AllocationType allocationType
)
[UnityTest]
public IEnumerator TestSendingWithGroupNotOverride()
{
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
var senderObject = GetPlayerObject(objectOwner, sender);
BaseRpcTarget target = null;
switch (allocationType)
foreach (var defaultSendTo in Enum.GetValues(typeof(SendTo)))
{
case AllocationType.Array:
target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp);
break;
case AllocationType.List:
target = senderObject.RpcTarget.Not(recipient.ToList(), RpcTargetUse.Temp);
break;
case AllocationType.NativeArray:
var arr = new NativeArray<ulong>(recipient, Allocator.Temp);
target = senderObject.RpcTarget.Not(arr, RpcTargetUse.Temp);
arr.Dispose();
break;
case AllocationType.NativeList:
// For some reason on 2020.3, calling list.AsArray() and passing that to the next function
// causes Allocator.Temp allocations to become invalid somehow. This is not an issue on later
// versions of Unity.
var list = new NativeList<ulong>(recipient.Length, Allocator.TempJob);
foreach (var id in recipient)
foreach (var recipient in RecipientGroups)
{
for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner)
{
list.Add(id);
for (ulong sender = 0u; sender <= 2u; ++sender)
{
foreach (var allocationType in Enum.GetValues(typeof(AllocationType)))
{
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc";
var senderObject = GetPlayerObject(objectOwner, sender);
BaseRpcTarget target = null;
switch (allocationType)
{
case AllocationType.Array:
target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp);
break;
case AllocationType.List:
target = senderObject.RpcTarget.Not(recipient.ToList(), RpcTargetUse.Temp);
break;
case AllocationType.NativeArray:
var arr = new NativeArray<ulong>(recipient, Allocator.Temp);
target = senderObject.RpcTarget.Not(arr, RpcTargetUse.Temp);
arr.Dispose();
break;
case AllocationType.NativeList:
// For some reason on 2020.3, calling list.AsArray() and passing that to the next function
// causes Allocator.Temp allocations to become invalid somehow. This is not an issue on later
// versions of Unity.
var list = new NativeList<ulong>(recipient.Length, Allocator.TempJob);
foreach (var id in recipient)
{
list.Add(id);
}
target = senderObject.RpcTarget.Not(list, RpcTargetUse.Temp);
list.Dispose();
break;
}
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray(), false);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray());
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray());
OnInlineTearDown();
}
}
}
target = senderObject.RpcTarget.Not(list, RpcTargetUse.Temp);
list.Dispose();
break;
}
}
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)target });
VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray(), false);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray());
// Pass some time to make sure that no other client ever receives this
TimeTravel(1f, 30);
VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray());
}
}
@ -1400,223 +1464,180 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
}
[Test]
// All the test cases that involve sends that will be delivered locally
[TestCase(SendTo.Everyone, 0u, 0u)]
[TestCase(SendTo.Everyone, 0u, 1u)]
[TestCase(SendTo.Everyone, 0u, 2u)]
[TestCase(SendTo.Everyone, 1u, 0u)]
[TestCase(SendTo.Everyone, 1u, 1u)]
[TestCase(SendTo.Everyone, 1u, 2u)]
[TestCase(SendTo.Everyone, 2u, 0u)]
[TestCase(SendTo.Everyone, 2u, 1u)]
[TestCase(SendTo.Everyone, 2u, 2u)]
[TestCase(SendTo.Me, 0u, 0u)]
[TestCase(SendTo.Me, 0u, 1u)]
[TestCase(SendTo.Me, 0u, 2u)]
[TestCase(SendTo.Me, 1u, 0u)]
[TestCase(SendTo.Me, 1u, 1u)]
[TestCase(SendTo.Me, 1u, 2u)]
[TestCase(SendTo.Me, 2u, 0u)]
[TestCase(SendTo.Me, 2u, 1u)]
[TestCase(SendTo.Me, 2u, 2u)]
[TestCase(SendTo.Owner, 0u, 0u)]
[TestCase(SendTo.Owner, 1u, 1u)]
[TestCase(SendTo.Owner, 2u, 2u)]
[TestCase(SendTo.Server, 0u, 0u)]
[TestCase(SendTo.Server, 1u, 0u)]
[TestCase(SendTo.Server, 2u, 0u)]
[TestCase(SendTo.NotOwner, 0u, 1u)]
[TestCase(SendTo.NotOwner, 0u, 2u)]
[TestCase(SendTo.NotOwner, 1u, 0u)]
[TestCase(SendTo.NotOwner, 1u, 2u)]
[TestCase(SendTo.NotOwner, 2u, 0u)]
[TestCase(SendTo.NotOwner, 2u, 1u)]
[TestCase(SendTo.NotServer, 0u, 1u)]
[TestCase(SendTo.NotServer, 0u, 2u)]
[TestCase(SendTo.NotServer, 1u, 1u)]
[TestCase(SendTo.NotServer, 1u, 2u)]
[TestCase(SendTo.NotServer, 2u, 1u)]
[TestCase(SendTo.NotServer, 2u, 2u)]
[TestCase(SendTo.ClientsAndHost, 0u, 0u)]
[TestCase(SendTo.ClientsAndHost, 0u, 1u)]
[TestCase(SendTo.ClientsAndHost, 0u, 2u)]
[TestCase(SendTo.ClientsAndHost, 1u, 0u)]
[TestCase(SendTo.ClientsAndHost, 1u, 1u)]
[TestCase(SendTo.ClientsAndHost, 1u, 2u)]
[TestCase(SendTo.ClientsAndHost, 2u, 0u)]
[TestCase(SendTo.ClientsAndHost, 2u, 1u)]
[TestCase(SendTo.ClientsAndHost, 2u, 2u)]
public void TestDeferLocal(
SendTo defaultSendTo,
ulong objectOwner,
ulong sender
)
private struct TestData
{
if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost)
public SendTo SendTo;
public ulong ObjectOwner;
public ulong Sender;
public TestData(SendTo sendTo, ulong objectOwner, ulong sender)
{
// Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored
// Just consider this case a success...
return;
SendTo = sendTo;
ObjectOwner = objectOwner;
Sender = sender;
}
var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc";
var verifyMethodName = $"VerifySentTo{defaultSendTo}";
var senderObject = GetPlayerObject(objectOwner, sender);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { new RpcParams() });
VerifyNotReceived(objectOwner, new[] { sender });
// Should be received on the next frame
SimulateOneFrame();
VerifyLocalReceived(objectOwner, sender, sendMethodName, false);
var verifyMethod = GetType().GetMethod(verifyMethodName);
verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName });
}
[Test]
// All the test cases that involve sends that will be delivered locally
[TestCase(SendTo.Everyone, 0u, 0u)]
[TestCase(SendTo.Everyone, 0u, 1u)]
[TestCase(SendTo.Everyone, 0u, 2u)]
[TestCase(SendTo.Everyone, 1u, 0u)]
[TestCase(SendTo.Everyone, 1u, 1u)]
[TestCase(SendTo.Everyone, 1u, 2u)]
[TestCase(SendTo.Everyone, 2u, 0u)]
[TestCase(SendTo.Everyone, 2u, 1u)]
[TestCase(SendTo.Everyone, 2u, 2u)]
[TestCase(SendTo.Me, 0u, 0u)]
[TestCase(SendTo.Me, 0u, 1u)]
[TestCase(SendTo.Me, 0u, 2u)]
[TestCase(SendTo.Me, 1u, 0u)]
[TestCase(SendTo.Me, 1u, 1u)]
[TestCase(SendTo.Me, 1u, 2u)]
[TestCase(SendTo.Me, 2u, 0u)]
[TestCase(SendTo.Me, 2u, 1u)]
[TestCase(SendTo.Me, 2u, 2u)]
[TestCase(SendTo.Owner, 0u, 0u)]
[TestCase(SendTo.Owner, 1u, 1u)]
[TestCase(SendTo.Owner, 2u, 2u)]
[TestCase(SendTo.Server, 0u, 0u)]
[TestCase(SendTo.Server, 1u, 0u)]
[TestCase(SendTo.Server, 2u, 0u)]
[TestCase(SendTo.NotOwner, 0u, 1u)]
[TestCase(SendTo.NotOwner, 0u, 2u)]
[TestCase(SendTo.NotOwner, 1u, 0u)]
[TestCase(SendTo.NotOwner, 1u, 2u)]
[TestCase(SendTo.NotOwner, 2u, 0u)]
[TestCase(SendTo.NotOwner, 2u, 1u)]
[TestCase(SendTo.NotServer, 0u, 1u)]
[TestCase(SendTo.NotServer, 0u, 2u)]
[TestCase(SendTo.NotServer, 1u, 1u)]
[TestCase(SendTo.NotServer, 1u, 2u)]
[TestCase(SendTo.NotServer, 2u, 1u)]
[TestCase(SendTo.NotServer, 2u, 2u)]
[TestCase(SendTo.ClientsAndHost, 0u, 0u)]
[TestCase(SendTo.ClientsAndHost, 0u, 1u)]
[TestCase(SendTo.ClientsAndHost, 0u, 2u)]
[TestCase(SendTo.ClientsAndHost, 1u, 0u)]
[TestCase(SendTo.ClientsAndHost, 1u, 1u)]
[TestCase(SendTo.ClientsAndHost, 1u, 2u)]
[TestCase(SendTo.ClientsAndHost, 2u, 0u)]
[TestCase(SendTo.ClientsAndHost, 2u, 1u)]
[TestCase(SendTo.ClientsAndHost, 2u, 2u)]
public void TestDeferLocalOverrideToTrue(
SendTo defaultSendTo,
ulong objectOwner,
ulong sender
)
private static TestData[] s_LocalDeliveryTestCases =
{
if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost)
new TestData(SendTo.Everyone, 0u, 0u),
new TestData(SendTo.Everyone, 0u, 1u),
new TestData(SendTo.Everyone, 0u, 2u),
new TestData(SendTo.Everyone, 1u, 0u),
new TestData(SendTo.Everyone, 1u, 1u),
new TestData(SendTo.Everyone, 1u, 2u),
new TestData(SendTo.Everyone, 2u, 0u),
new TestData(SendTo.Everyone, 2u, 1u),
new TestData(SendTo.Everyone, 2u, 2u),
new TestData(SendTo.Me, 0u, 0u),
new TestData(SendTo.Me, 0u, 1u),
new TestData(SendTo.Me, 0u, 2u),
new TestData(SendTo.Me, 1u, 0u),
new TestData(SendTo.Me, 1u, 1u),
new TestData(SendTo.Me, 1u, 2u),
new TestData(SendTo.Me, 2u, 0u),
new TestData(SendTo.Me, 2u, 1u),
new TestData(SendTo.Me, 2u, 2u),
new TestData(SendTo.Owner, 0u, 0u),
new TestData(SendTo.Owner, 1u, 1u),
new TestData(SendTo.Owner, 2u, 2u),
new TestData(SendTo.Server, 0u, 0u),
new TestData(SendTo.Server, 1u, 0u),
new TestData(SendTo.Server, 2u, 0u),
new TestData(SendTo.NotOwner, 0u, 1u),
new TestData(SendTo.NotOwner, 0u, 2u),
new TestData(SendTo.NotOwner, 1u, 0u),
new TestData(SendTo.NotOwner, 1u, 2u),
new TestData(SendTo.NotOwner, 2u, 0u),
new TestData(SendTo.NotOwner, 2u, 1u),
new TestData(SendTo.NotServer, 0u, 1u),
new TestData(SendTo.NotServer, 0u, 2u),
new TestData(SendTo.NotServer, 1u, 1u),
new TestData(SendTo.NotServer, 1u, 2u),
new TestData(SendTo.NotServer, 2u, 1u),
new TestData(SendTo.NotServer, 2u, 2u),
new TestData(SendTo.ClientsAndHost, 0u, 0u),
new TestData(SendTo.ClientsAndHost, 0u, 1u),
new TestData(SendTo.ClientsAndHost, 0u, 2u),
new TestData(SendTo.ClientsAndHost, 1u, 0u),
new TestData(SendTo.ClientsAndHost, 1u, 1u),
new TestData(SendTo.ClientsAndHost, 1u, 2u),
new TestData(SendTo.ClientsAndHost, 2u, 0u),
new TestData(SendTo.ClientsAndHost, 2u, 1u),
new TestData(SendTo.ClientsAndHost, 2u, 2u),
};
[UnityTest]
public IEnumerator TestDeferLocal()
{
foreach (var testCase in s_LocalDeliveryTestCases)
{
// Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored
// Just consider this case a success...
return;
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var defaultSendTo = testCase.SendTo;
var sender = testCase.Sender;
var objectOwner = testCase.ObjectOwner;
if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost)
{
// Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored
// Just consider this case a success...
yield break;
}
var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc";
var verifyMethodName = $"VerifySentTo{defaultSendTo}";
var senderObject = GetPlayerObject(objectOwner, sender);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { new RpcParams() });
VerifyNotReceived(objectOwner, new[] { sender });
// Should be received on the next frame
SimulateOneFrame();
VerifyLocalReceived(objectOwner, sender, sendMethodName, false);
var verifyMethod = GetType().GetMethod(verifyMethodName);
verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName });
OnInlineTearDown();
}
var sendMethodName = $"DefaultTo{defaultSendTo}WithRpcParamsRpc";
var verifyMethodName = $"VerifySentTo{defaultSendTo}";
var senderObject = GetPlayerObject(objectOwner, sender);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.Defer });
VerifyNotReceived(objectOwner, new[] { sender });
// Should be received on the next frame
SimulateOneFrame();
VerifyLocalReceived(objectOwner, sender, sendMethodName, false);
var verifyMethod = GetType().GetMethod(verifyMethodName);
verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName });
}
[Test]
// All the test cases that involve sends that will be delivered locally
[TestCase(SendTo.Everyone, 0u, 0u)]
[TestCase(SendTo.Everyone, 0u, 1u)]
[TestCase(SendTo.Everyone, 0u, 2u)]
[TestCase(SendTo.Everyone, 1u, 0u)]
[TestCase(SendTo.Everyone, 1u, 1u)]
[TestCase(SendTo.Everyone, 1u, 2u)]
[TestCase(SendTo.Everyone, 2u, 0u)]
[TestCase(SendTo.Everyone, 2u, 1u)]
[TestCase(SendTo.Everyone, 2u, 2u)]
[TestCase(SendTo.Me, 0u, 0u)]
[TestCase(SendTo.Me, 0u, 1u)]
[TestCase(SendTo.Me, 0u, 2u)]
[TestCase(SendTo.Me, 1u, 0u)]
[TestCase(SendTo.Me, 1u, 1u)]
[TestCase(SendTo.Me, 1u, 2u)]
[TestCase(SendTo.Me, 2u, 0u)]
[TestCase(SendTo.Me, 2u, 1u)]
[TestCase(SendTo.Me, 2u, 2u)]
[TestCase(SendTo.Owner, 0u, 0u)]
[TestCase(SendTo.Owner, 1u, 1u)]
[TestCase(SendTo.Owner, 2u, 2u)]
[TestCase(SendTo.Server, 0u, 0u)]
[TestCase(SendTo.Server, 1u, 0u)]
[TestCase(SendTo.Server, 2u, 0u)]
[TestCase(SendTo.NotOwner, 0u, 1u)]
[TestCase(SendTo.NotOwner, 0u, 2u)]
[TestCase(SendTo.NotOwner, 1u, 0u)]
[TestCase(SendTo.NotOwner, 1u, 2u)]
[TestCase(SendTo.NotOwner, 2u, 0u)]
[TestCase(SendTo.NotOwner, 2u, 1u)]
[TestCase(SendTo.NotServer, 0u, 1u)]
[TestCase(SendTo.NotServer, 0u, 2u)]
[TestCase(SendTo.NotServer, 1u, 1u)]
[TestCase(SendTo.NotServer, 1u, 2u)]
[TestCase(SendTo.NotServer, 2u, 1u)]
[TestCase(SendTo.NotServer, 2u, 2u)]
[TestCase(SendTo.ClientsAndHost, 0u, 0u)]
[TestCase(SendTo.ClientsAndHost, 0u, 1u)]
[TestCase(SendTo.ClientsAndHost, 0u, 2u)]
[TestCase(SendTo.ClientsAndHost, 1u, 0u)]
[TestCase(SendTo.ClientsAndHost, 1u, 1u)]
[TestCase(SendTo.ClientsAndHost, 1u, 2u)]
[TestCase(SendTo.ClientsAndHost, 2u, 0u)]
[TestCase(SendTo.ClientsAndHost, 2u, 1u)]
[TestCase(SendTo.ClientsAndHost, 2u, 2u)]
public void TestDeferLocalOverrideToFalse(
SendTo defaultSendTo,
ulong objectOwner,
ulong sender
)
[UnityTest]
public IEnumerator TestDeferLocalOverrideToTrue()
{
if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost)
foreach (var testCase in s_LocalDeliveryTestCases)
{
// Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored
// Just consider this case a success...
return;
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var defaultSendTo = testCase.SendTo;
var sender = testCase.Sender;
var objectOwner = testCase.ObjectOwner;
if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost)
{
// Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored
// Just consider this case a success...
yield break;
}
var sendMethodName = $"DefaultTo{defaultSendTo}WithRpcParamsRpc";
var verifyMethodName = $"VerifySentTo{defaultSendTo}";
var senderObject = GetPlayerObject(objectOwner, sender);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.Defer });
VerifyNotReceived(objectOwner, new[] { sender });
// Should be received on the next frame
SimulateOneFrame();
VerifyLocalReceived(objectOwner, sender, sendMethodName, false);
var verifyMethod = GetType().GetMethod(verifyMethodName);
verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName });
OnInlineTearDown();
}
var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc";
var verifyMethodName = $"VerifySentTo{defaultSendTo}";
var senderObject = GetPlayerObject(objectOwner, sender);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.SendImmediate });
}
VerifyLocalReceived(objectOwner, sender, sendMethodName, false);
[UnityTest]
public IEnumerator TestDeferLocalOverrideToFalse()
{
foreach (var testCase in s_LocalDeliveryTestCases)
{
if (++YieldCheck % YieldCycleCount == 0)
{
yield return null;
}
OnInlineSetup();
var defaultSendTo = testCase.SendTo;
var sender = testCase.Sender;
var objectOwner = testCase.ObjectOwner;
var verifyMethod = GetType().GetMethod(verifyMethodName);
verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName });
if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost)
{
// Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored
// Just consider this case a success...
yield break;
}
var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc";
var verifyMethodName = $"VerifySentTo{defaultSendTo}";
var senderObject = GetPlayerObject(objectOwner, sender);
var sendMethod = senderObject.GetType().GetMethod(sendMethodName);
sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.SendImmediate });
VerifyLocalReceived(objectOwner, sender, sendMethodName, false);
var verifyMethod = GetType().GetMethod(verifyMethodName);
verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName });
OnInlineTearDown();
}
}
}
@ -1927,3 +1948,4 @@ namespace Unity.Netcode.RuntimeTests.UniversalRpcTests
}
}
#endif

Просмотреть файл

@ -1,7 +1,7 @@
{
"dependencies": {
"com.unity.burst": {
"version": "1.6.4",
"version": "1.6.6",
"depth": 2,
"source": "registry",
"dependencies": {
@ -10,11 +10,11 @@
"url": "https://packages.unity.com"
},
"com.unity.collections": {
"version": "1.2.3",
"version": "1.2.4",
"depth": 2,
"source": "registry",
"dependencies": {
"com.unity.burst": "1.6.4",
"com.unity.burst": "1.6.6",
"com.unity.test-framework": "1.1.31"
},
"url": "https://packages.unity.com"
@ -27,7 +27,7 @@
"url": "https://packages.unity.com"
},
"com.unity.mathematics": {
"version": "1.2.5",
"version": "1.2.6",
"depth": 2,
"source": "registry",
"dependencies": {},
@ -39,7 +39,7 @@
"source": "local",
"dependencies": {
"com.unity.nuget.mono-cecil": "1.10.1",
"com.unity.transport": "1.3.1"
"com.unity.transport": "1.4.0"
}
},
"com.unity.nuget.mono-cecil": {
@ -50,7 +50,7 @@
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.1.31",
"version": "1.1.33",
"depth": 3,
"source": "registry",
"dependencies": {
@ -61,13 +61,13 @@
"url": "https://packages.unity.com"
},
"com.unity.transport": {
"version": "1.3.1",
"version": "1.4.0",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.collections": "1.2.3",
"com.unity.burst": "1.6.4",
"com.unity.mathematics": "1.2.5"
"com.unity.collections": "1.2.4",
"com.unity.burst": "1.6.6",
"com.unity.mathematics": "1.2.6"
},
"url": "https://packages.unity.com"
},

Просмотреть файл

@ -0,0 +1,35 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!387306366 &1
MemorySettings:
m_ObjectHideFlags: 0
m_EditorMemorySettings:
m_MainAllocatorBlockSize: -1
m_ThreadAllocatorBlockSize: -1
m_MainGfxBlockSize: -1
m_ThreadGfxBlockSize: -1
m_CacheBlockSize: -1
m_TypetreeBlockSize: -1
m_ProfilerBlockSize: -1
m_ProfilerEditorBlockSize: -1
m_BucketAllocatorGranularity: -1
m_BucketAllocatorBucketsCount: -1
m_BucketAllocatorBlockSize: -1
m_BucketAllocatorBlockCount: -1
m_ProfilerBucketAllocatorGranularity: -1
m_ProfilerBucketAllocatorBucketsCount: -1
m_ProfilerBucketAllocatorBlockSize: -1
m_ProfilerBucketAllocatorBlockCount: -1
m_TempAllocatorSizeMain: -1
m_JobTempAllocatorBlockSize: -1
m_BackgroundJobTempAllocatorBlockSize: -1
m_JobTempAllocatorReducedBlockSize: -1
m_TempAllocatorSizeGIBakingWorker: -1
m_TempAllocatorSizeNavMeshWorker: -1
m_TempAllocatorSizeAudioWorker: -1
m_TempAllocatorSizeCloudWorker: -1
m_TempAllocatorSizeGfx: -1
m_TempAllocatorSizeJobWorker: -1
m_TempAllocatorSizeBackgroundWorker: -1
m_TempAllocatorSizePreloadManager: -1
m_PlatformMemorySettings: {}

Просмотреть файл

@ -3,7 +3,7 @@
--- !u!129 &1
PlayerSettings:
m_ObjectHideFlags: 0
serializedVersion: 22
serializedVersion: 24
productGUID: 53f9fd541540241529c78965266c29d6
AndroidProfiler: 0
AndroidFilterTouchesWhenObscured: 0
@ -68,6 +68,12 @@ PlayerSettings:
androidRenderOutsideSafeArea: 1
androidUseSwappy: 1
androidBlitType: 0
androidResizableWindow: 0
androidDefaultWindowWidth: 1920
androidDefaultWindowHeight: 1080
androidMinimumWindowWidth: 400
androidMinimumWindowHeight: 300
androidFullscreenMode: 1
defaultIsNativeResolution: 1
macRetinaSupport: 1
runInBackground: 1
@ -121,6 +127,7 @@ PlayerSettings:
vulkanEnableSetSRGBWrite: 0
vulkanEnablePreTransform: 0
vulkanEnableLateAcquireNextImage: 0
vulkanEnableCommandBufferRecycling: 1
m_SupportedAspectRatios:
4:3: 1
5:4: 1
@ -138,21 +145,24 @@ PlayerSettings:
enable360StereoCapture: 0
isWsaHolographicRemotingEnabled: 0
enableFrameTimingStats: 0
enableOpenGLProfilerGPURecorders: 1
useHDRDisplay: 0
D3DHDRBitDepth: 0
m_ColorGamuts: 00000000
targetPixelDensity: 30
resolutionScalingMode: 0
resetResolutionOnWindowResize: 0
androidSupportedAspectRatio: 1
androidMaxAspectRatio: 2.1
applicationIdentifier: {}
applicationIdentifier:
Standalone: com.DefaultCompany.minimalproject
buildNumber:
Standalone: 0
iPhone: 0
tvOS: 0
overrideDefaultApplicationIdentifier: 0
AndroidBundleVersionCode: 1
AndroidMinSdkVersion: 19
AndroidMinSdkVersion: 22
AndroidTargetSdkVersion: 0
AndroidPreferredInstallLocation: 1
aotOptions:
@ -167,10 +177,10 @@ PlayerSettings:
StripUnusedMeshComponents: 1
VertexChannelCompressionMask: 4054
iPhoneSdkVersion: 988
iOSTargetOSVersionString: 11.0
iOSTargetOSVersionString: 12.0
tvOSSdkVersion: 0
tvOSRequireExtendedGameController: 0
tvOSTargetOSVersionString: 11.0
tvOSTargetOSVersionString: 12.0
uIPrerenderedIcon: 0
uIRequiresPersistentWiFi: 0
uIRequiresFullScreen: 1
@ -208,6 +218,7 @@ PlayerSettings:
iOSLaunchScreeniPadCustomStoryboardPath:
iOSDeviceRequirements: []
iOSURLSchemes: []
macOSURLSchemes: []
iOSBackgroundModes: 0
iOSMetalForceHardShadows: 0
metalEditorSupport: 1
@ -235,6 +246,7 @@ PlayerSettings:
useCustomGradlePropertiesTemplate: 0
useCustomProguardFile: 0
AndroidTargetArchitectures: 1
AndroidTargetDevices: 0
AndroidSplashScreenScale: 0
androidSplashScreen: {fileID: 0}
AndroidKeystoreName:
@ -251,13 +263,203 @@ PlayerSettings:
height: 180
banner: {fileID: 0}
androidGamepadSupportLevel: 0
chromeosInputEmulation: 1
AndroidMinifyWithR8: 0
AndroidMinifyRelease: 0
AndroidMinifyDebug: 0
AndroidValidateAppBundleSize: 1
AndroidAppBundleSizeToValidate: 150
m_BuildTargetIcons: []
m_BuildTargetPlatformIcons: []
m_BuildTargetPlatformIcons:
- m_BuildTarget: iPhone
m_Icons:
- m_Textures: []
m_Width: 180
m_Height: 180
m_Kind: 0
m_SubKind: iPhone
- m_Textures: []
m_Width: 120
m_Height: 120
m_Kind: 0
m_SubKind: iPhone
- m_Textures: []
m_Width: 167
m_Height: 167
m_Kind: 0
m_SubKind: iPad
- m_Textures: []
m_Width: 152
m_Height: 152
m_Kind: 0
m_SubKind: iPad
- m_Textures: []
m_Width: 76
m_Height: 76
m_Kind: 0
m_SubKind: iPad
- m_Textures: []
m_Width: 120
m_Height: 120
m_Kind: 3
m_SubKind: iPhone
- m_Textures: []
m_Width: 80
m_Height: 80
m_Kind: 3
m_SubKind: iPhone
- m_Textures: []
m_Width: 80
m_Height: 80
m_Kind: 3
m_SubKind: iPad
- m_Textures: []
m_Width: 40
m_Height: 40
m_Kind: 3
m_SubKind: iPad
- m_Textures: []
m_Width: 87
m_Height: 87
m_Kind: 1
m_SubKind: iPhone
- m_Textures: []
m_Width: 58
m_Height: 58
m_Kind: 1
m_SubKind: iPhone
- m_Textures: []
m_Width: 29
m_Height: 29
m_Kind: 1
m_SubKind: iPhone
- m_Textures: []
m_Width: 58
m_Height: 58
m_Kind: 1
m_SubKind: iPad
- m_Textures: []
m_Width: 29
m_Height: 29
m_Kind: 1
m_SubKind: iPad
- m_Textures: []
m_Width: 60
m_Height: 60
m_Kind: 2
m_SubKind: iPhone
- m_Textures: []
m_Width: 40
m_Height: 40
m_Kind: 2
m_SubKind: iPhone
- m_Textures: []
m_Width: 40
m_Height: 40
m_Kind: 2
m_SubKind: iPad
- m_Textures: []
m_Width: 20
m_Height: 20
m_Kind: 2
m_SubKind: iPad
- m_Textures: []
m_Width: 1024
m_Height: 1024
m_Kind: 4
m_SubKind: App Store
- m_BuildTarget: Android
m_Icons:
- m_Textures: []
m_Width: 432
m_Height: 432
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 324
m_Height: 324
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 216
m_Height: 216
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 162
m_Height: 162
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 108
m_Height: 108
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 81
m_Height: 81
m_Kind: 2
m_SubKind:
- m_Textures: []
m_Width: 192
m_Height: 192
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 144
m_Height: 144
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 96
m_Height: 96
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 72
m_Height: 72
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 48
m_Height: 48
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 36
m_Height: 36
m_Kind: 1
m_SubKind:
- m_Textures: []
m_Width: 192
m_Height: 192
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 144
m_Height: 144
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 96
m_Height: 96
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 72
m_Height: 72
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 48
m_Height: 48
m_Kind: 0
m_SubKind:
- m_Textures: []
m_Width: 36
m_Height: 36
m_Kind: 0
m_SubKind:
m_BuildTargetBatching:
- m_BuildTarget: Standalone
m_StaticBatching: 1
@ -274,6 +476,7 @@ PlayerSettings:
- m_BuildTarget: WebGL
m_StaticBatching: 0
m_DynamicBatching: 0
m_BuildTargetShaderSettings: []
m_BuildTargetGraphicsJobs:
- m_BuildTarget: MacStandaloneSupport
m_GraphicsJobs: 0
@ -309,7 +512,7 @@ PlayerSettings:
m_BuildTargetGraphicsAPIs:
- m_BuildTarget: AndroidPlayer
m_APIs: 150000000b000000
m_Automatic: 0
m_Automatic: 1
- m_BuildTarget: iOSSupport
m_APIs: 10000000
m_Automatic: 1
@ -325,6 +528,8 @@ PlayerSettings:
m_Devices:
- Oculus
- OpenVR
m_DefaultShaderChunkSizeInMB: 16
m_DefaultShaderChunkCount: 0
openGLRequireES31: 0
openGLRequireES31AEP: 0
openGLRequireES32: 0
@ -336,6 +541,7 @@ PlayerSettings:
m_BuildTargetGroupLightmapEncodingQuality: []
m_BuildTargetGroupLightmapSettings: []
m_BuildTargetNormalMapEncoding: []
m_BuildTargetDefaultTextureCompressionFormat: []
playModeTestRunnerEnabled: 0
runPlayModeTestAsEditModeTest: 0
actionOnDotNetUnhandledException: 1
@ -345,6 +551,7 @@ PlayerSettings:
cameraUsageDescription:
locationUsageDescription:
microphoneUsageDescription:
bluetoothUsageDescription:
switchNMETAOverride:
switchNetLibKey:
switchSocketMemoryPoolSize: 6144
@ -353,6 +560,7 @@ PlayerSettings:
switchScreenResolutionBehavior: 2
switchUseCPUProfiler: 0
switchUseGOLDLinker: 0
switchLTOSetting: 0
switchApplicationID: 0x01004b9000490000
switchNSODependencies:
switchTitleNames_0:
@ -428,7 +636,6 @@ PlayerSettings:
switchReleaseVersion: 0
switchDisplayVersion: 1.0.0
switchStartupUserAccount: 0
switchTouchScreenUsage: 0
switchSupportedLanguagesMask: 0
switchLogoType: 0
switchApplicationErrorCodeCategory:
@ -470,6 +677,7 @@ PlayerSettings:
switchNativeFsCacheSize: 32
switchIsHoldTypeHorizontal: 0
switchSupportedNpadCount: 8
switchEnableTouchScreen: 1
switchSocketConfigEnabled: 0
switchTcpInitialSendBufferSize: 32
switchTcpInitialReceiveBufferSize: 64
@ -482,8 +690,11 @@ PlayerSettings:
switchNetworkInterfaceManagerInitializeEnabled: 1
switchPlayerConnectionEnabled: 1
switchUseNewStyleFilepaths: 0
switchUseLegacyFmodPriorities: 1
switchUseMicroSleepForYield: 1
switchEnableRamDiskSupport: 0
switchMicroSleepForYieldTime: 25
switchRamDiskSpaceSize: 12
ps4NPAgeRating: 12
ps4NPTitleSecret:
ps4NPTrophyPackPath:
@ -554,6 +765,7 @@ PlayerSettings:
ps4videoRecordingFeaturesUsed: 0
ps4contentSearchFeaturesUsed: 0
ps4CompatibilityPS5: 0
ps4AllowPS5Detection: 0
ps4GPU800MHz: 1
ps4attribEyeToEyeDistanceSettingVR: 0
ps4IncludedModules: []
@ -578,17 +790,31 @@ PlayerSettings:
webGLLinkerTarget: 1
webGLThreadsSupport: 0
webGLDecompressionFallback: 0
scriptingDefineSymbols: {}
webGLPowerPreference: 2
scriptingDefineSymbols:
Standalone: NGO_MINIMALPROJECT
additionalCompilerArguments: {}
platformArchitecture: {}
scriptingBackend: {}
il2cppCompilerConfiguration: {}
managedStrippingLevel: {}
managedStrippingLevel:
EmbeddedLinux: 1
GameCoreScarlett: 1
GameCoreXboxOne: 1
Lumin: 1
Nintendo Switch: 1
PS4: 1
PS5: 1
Stadia: 1
WebGL: 1
Windows Store Apps: 1
XboxOne: 1
iPhone: 1
tvOS: 1
incrementalIl2cppBuild: {}
suppressCommonWarnings: 1
allowUnsafeCode: 0
useDeterministicCompilation: 1
useReferenceAssemblies: 1
enableRoslynAnalyzers: 1
additionalIl2CppArgs:
scriptingRuntimeVersion: 1
@ -624,6 +850,7 @@ PlayerSettings:
metroFTAName:
metroFTAFileTypes: []
metroProtocolName:
vcxProjDefaultLanguage:
XboxOneProductId:
XboxOneUpdateKey:
XboxOneSandboxId:
@ -667,6 +894,7 @@ PlayerSettings:
m_VersionName:
apiCompatibilityLevel: 6
activeInputHandler: 0
windowsGamepadBackendHint: 0
cloudProjectId:
framebufferDepthMemorylessMode: 0
qualitySettingsNames: []
@ -674,4 +902,6 @@ PlayerSettings:
organizationId:
cloudEnabled: 0
legacyClampBlendShapeWeights: 0
playerDataPath:
forceSRGBBlit: 1
virtualTexturingSupportEnabled: 0

Просмотреть файл

@ -1,2 +1,2 @@
m_EditorVersion: 2020.3.40f1
m_EditorVersionWithRevision: 2020.3.40f1 (ba48d4efcef1)
m_EditorVersion: 2021.3.28f1
m_EditorVersionWithRevision: 2021.3.28f1 (232e59c3f087)

Просмотреть файл