Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal struct NetworkVariableDeltaMessage : INetworkMessage

private Dictionary<ulong, List<int>> m_ForwardUpdates;

private List<int> m_UpdatedNetworkVariables;
private NativeList<int> m_UpdatedNetworkVariables;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WriteNetworkVariable(ref FastBufferWriter writer, ref NetworkVariableBase networkVariable, bool ensureNetworkVariableLengthSafety, int nonfragmentedSize, int fragmentedSize)
Expand Down Expand Up @@ -217,7 +217,7 @@ public void Handle(ref NetworkContext context)
var networkBehaviour = networkObject.GetNetworkBehaviourAtOrderIndex(NetworkBehaviourIndex);
var isServerAndDeltaForwarding = m_ReceivedMessageVersion >= k_ServerDeltaForwardingAndNetworkDelivery && networkManager.IsServer;
var markNetworkVariableDirty = m_ReceivedMessageVersion >= k_ServerDeltaForwardingAndNetworkDelivery ? false : networkManager.IsServer;
m_UpdatedNetworkVariables = new List<int>();
m_UpdatedNetworkVariables = new NativeList<int>(Allocator.Temp);

if (networkBehaviour == null)
{
Expand Down Expand Up @@ -396,9 +396,9 @@ public void Handle(ref NetworkContext context)
// When a server forwards delta updates to connected clients, it needs to preserve the previous value
// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This
// is invoked after it is done forwarding the deltas.
foreach (var fieldIndex in m_UpdatedNetworkVariables)
for (int i = 0; i < m_UpdatedNetworkVariables.Length; i++)
{
networkBehaviour.NetworkVariableFields[fieldIndex].PostDeltaRead();
networkBehaviour.NetworkVariableFields[m_UpdatedNetworkVariables[i]].PostDeltaRead();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,8 @@
{
networkManager.Log.Exception(ex, new Context(LogLevel.Error, "Unhandled RPC exception!").AddNetworkBehaviour(networkBehaviour));

var methodId = metadata.NetworkRpcMethodId;
networkManager.Log.Info(new Context(LogLevel.Developer, "RPC Table Contents").AddCollection(rpcsForBehaviour, entry =>
{
var invokePermission = NetworkBehaviour.__rpc_permission_table[networkBehaviour.GetType()][methodId];
return $"{entry.Key} | {entry.Value.Method.Name} | {invokePermission}";
}));
var invokePermission = permission;
networkManager.Log.Info(new Context(LogLevel.Developer, "RPC Table Contents").AddCollection(rpcsForBehaviour, entry => $"{entry.Key} | {entry.Value.Method.Name} | {invokePermission}"));

Check warning on line 87 in com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs#L86-L87

Added lines #L86 - L87 were not covered by tests
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,9 @@ internal void CleanupDisconnectedClients()
m_DisconnectedClients.Clear();
}

public static int CreateMessageAndGetVersion<T>() where T : INetworkMessage, new()
public static int CreateMessageAndGetVersion<T>() where T : struct, INetworkMessage
{
return new T().Version;
return default(T).Version;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -538,10 +538,10 @@ internal int GetMessageVersion(Type type, ulong clientId, bool forReceive = fals



public static void ReceiveMessage<T>(FastBufferReader reader, ref NetworkContext context, NetworkMessageManager manager) where T : INetworkMessage, new()
public static void ReceiveMessage<T>(FastBufferReader reader, ref NetworkContext context, NetworkMessageManager manager) where T : struct, INetworkMessage
{
var messageType = typeof(T);
var message = new T();
var message = default(T);
var messageVersion = 0;

// Special cases because these are the messages that carry the version info - thus the version info isn't
Expand Down Expand Up @@ -633,8 +633,9 @@ internal int SendMessage<TMessageType, TClientIdListType>(ref TMessageType messa
return largestSerializedSize;
}

internal unsafe int SendPreSerializedMessage<TMessageType>(in FastBufferWriter tmpSerializer, int maxSize, ref TMessageType message, NetworkDelivery delivery, in IReadOnlyList<ulong> clientIds, int messageVersionFilter)
internal unsafe int SendPreSerializedMessage<TMessageType, TClientIdListType>(in FastBufferWriter tmpSerializer, int maxSize, ref TMessageType message, NetworkDelivery delivery, in TClientIdListType clientIds, int messageVersionFilter)
where TMessageType : INetworkMessage
where TClientIdListType : IReadOnlyList<ulong>
{
using var headerSerializer = new FastBufferWriter(FastBufferWriter.GetWriteSize<NetworkMessageHeader>(), Allocator.Temp);

Expand Down
23 changes: 21 additions & 2 deletions com.unity.netcode.gameobjects/Runtime/Metrics/MetricHooks.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;

namespace Unity.Netcode
{
internal class MetricHooks : INetworkHooks
{
private readonly NetworkManager m_NetworkManager;
private readonly Dictionary<Type, string> m_CachedTypeNames = new();

public MetricHooks(NetworkManager networkManager)
{
Expand All @@ -17,12 +19,12 @@ public void OnBeforeSendMessage<T>(ulong clientId, ref T message, NetworkDeliver

public void OnAfterSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage
{
m_NetworkManager.NetworkMetrics.TrackNetworkMessageSent(clientId, typeof(T).Name, messageSizeBytes);
m_NetworkManager.NetworkMetrics.TrackNetworkMessageSent(clientId, GetNameForType(typeof(T)), messageSizeBytes);
}

public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes)
{
m_NetworkManager.NetworkMetrics.TrackNetworkMessageReceived(senderId, messageType.Name, messageSizeBytes);
m_NetworkManager.NetworkMetrics.TrackNetworkMessageReceived(senderId, GetNameForType(messageType), messageSizeBytes);
}

public void OnAfterReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes)
Expand Down Expand Up @@ -66,5 +68,22 @@ public void OnAfterHandleMessage<T>(ref T message, ref NetworkContext context) w
{
// TODO: Per-message metrics recording moved here
}

/// <summary>
/// Gets the Name from a given type.
/// </summary>
private string GetNameForType(Type type)
{
if (m_CachedTypeNames.TryGetValue(type, out var cachedName))
{
return cachedName;
}

// type.Name does a reflection lookup that does a GC allocation
// Grab the name once and save to a cache.
var name = type.Name;
m_CachedTypeNames.Add(type, name);
return name;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ public override void WriteDelta(FastBufferWriter writer)
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private T ReadValue(FastBufferReader reader)
{
// T is constrained to unmanaged, use default rather than new() to avoid an allocation.
var value = default(T);
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
return value;
}

/// <inheritdoc cref="NetworkVariable{T}.WriteField"/>
public override void WriteField(FastBufferWriter writer)
{
Expand All @@ -154,9 +163,7 @@ public override void ReadField(FastBufferReader reader)
reader.ReadValueSafe(out ushort count);
for (int i = 0; i < count; i++)
{
var value = new T();
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
m_List.Add(value);
m_List.Add(ReadValue(reader));
}
}

Expand All @@ -178,8 +185,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
{
case NetworkListEvent<T>.EventType.Add:
{
var value = new T();
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
var value = ReadValue(reader);
m_List.Add(value);

if (OnListChanged != null)
Expand All @@ -188,7 +194,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
{
Type = eventType,
Index = m_List.Length - 1,
Value = m_List[m_List.Length - 1]
Value = value
});
}

Expand All @@ -198,7 +204,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
{
Type = eventType,
Index = m_List.Length - 1,
Value = m_List[m_List.Length - 1]
Value = value
});
// Preserve the legacy way of handling this
if (keepDirtyDelta)
Expand All @@ -211,8 +217,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
case NetworkListEvent<T>.EventType.Insert:
{
ByteUnpacker.ReadValueBitPacked(reader, out int index);
var value = new T();
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
var value = ReadValue(reader);

if (index < m_List.Length)
{
Expand All @@ -230,7 +235,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
{
Type = eventType,
Index = index,
Value = m_List[index]
Value = value
});
}

Expand All @@ -240,7 +245,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
{
Type = eventType,
Index = index,
Value = m_List[index]
Value = value
});
// Preserve the legacy way of handling this
if (keepDirtyDelta)
Expand All @@ -252,8 +257,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
break;
case NetworkListEvent<T>.EventType.Remove:
{
var value = new T();
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
var value = ReadValue(reader);
int index = m_List.IndexOf(value);
if (index == -1)
{
Expand Down Expand Up @@ -323,8 +327,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
case NetworkListEvent<T>.EventType.Value:
{
ByteUnpacker.ReadValueBitPacked(reader, out int index);
var value = new T();
NetworkVariableSerialization<T>.Serializer.Read(reader, ref value);
var value = ReadValue(reader);
if (index >= m_List.Length)
{
throw new Exception("Shouldn't be here, index is higher than list length");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public unsafe void ReadBit(out bool bit)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe void ReadPartialValue<T>(out T value, int bytesToRead, int offsetBytes = 0) where T : unmanaged
{
var val = new T();
var val = default(T);
byte* ptr = ((byte*)&val) + offsetBytes;
byte* bufferPointer = m_BufferPointer + BytePosition;
UnsafeUtility.MemCpy(ptr, bufferPointer, bytesToRead);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ public unsafe void ReadPartialValue<T>(out T value, int bytesToRead, int offsetB
}
#endif

var val = new T();
var val = default(T);
byte* ptr = ((byte*)&val) + offsetBytes;
byte* bufferPointer = Handle->BufferPointer + Handle->Position;
UnsafeUtility.MemCpy(ptr, bufferPointer, bytesToRead);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.Internal;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.TestTools.Constraints;
using Is = NUnit.Framework.Is;

namespace Unity.Netcode.EditorTests
{
Expand Down Expand Up @@ -95,22 +96,23 @@ public void WhenHandlingAMessage_ReceiveMethodIsCalled()
};
var message = GetMessage();

var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
{
writer.TryBeginWrite(FastBufferWriter.GetWriteSize(message));
writer.WriteValue(message);
using var writer = new FastBufferWriter(1300, Allocator.Temp);
writer.TryBeginWrite(FastBufferWriter.GetWriteSize(message));
writer.WriteValue(message);

var reader = new FastBufferReader(writer, Allocator.Temp);
using (reader)
{
m_MessageManager.HandleMessage(messageHeader, reader, 0, 0, 0);
Assert.IsTrue(TestMessage.Deserialized);
Assert.IsTrue(TestMessage.Handled);
Assert.AreEqual(1, TestMessage.DeserializedValues.Count);
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);
}
}
using var reader = new FastBufferReader(writer, Allocator.Temp);
m_MessageManager.HandleMessage(messageHeader, reader, 0, 0, 0);
Assert.IsTrue(TestMessage.Deserialized);
Assert.IsTrue(TestMessage.Handled);
Assert.AreEqual(1, TestMessage.DeserializedValues.Count);
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);

// Check for GC Allocations
Assert.That(() =>
{
reader.Seek(0);
m_MessageManager.HandleMessage(messageHeader, reader, 0, 0, 0);
}, Is.Not.AllocatingGCMemory());
}

[Test]
Expand Down Expand Up @@ -220,44 +222,45 @@ public unsafe void WhenReceivingMultipleMessagesAndProcessingMessageQueue_Receiv
var message = GetMessage();
var message2 = GetMessage();

var writer = new FastBufferWriter(1300, Allocator.Temp);
using (writer)
using var writer = new FastBufferWriter(1300, Allocator.Temp);
writer.WriteValueSafe(batchHeader);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize);
writer.WriteValueSafe(message);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize);
writer.WriteValueSafe(message2);

// Fill out the rest of the batch header
writer.Seek(0);
batchHeader = new NetworkBatchHeader
{
writer.WriteValueSafe(batchHeader);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize);
writer.WriteValueSafe(message);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType);
BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize);
writer.WriteValueSafe(message2);
Magic = NetworkBatchHeader.MagicValue,
BatchSize = writer.Length,
BatchHash = XXHash.Hash64(writer.GetUnsafePtr() + sizeof(NetworkBatchHeader), writer.Length - sizeof(NetworkBatchHeader)),
BatchCount = 2
};
writer.WriteValue(batchHeader);

// Fill out the rest of the batch header
writer.Seek(0);
batchHeader = new NetworkBatchHeader
{
Magic = NetworkBatchHeader.MagicValue,
BatchSize = writer.Length,
BatchHash = XXHash.Hash64(writer.GetUnsafePtr() + sizeof(NetworkBatchHeader), writer.Length - sizeof(NetworkBatchHeader)),
BatchCount = 2
};
writer.WriteValue(batchHeader);
var data = new ArraySegment<byte>(writer.ToArray());
m_MessageManager.HandleIncomingData(0, data, 0);
Assert.IsFalse(TestMessage.Deserialized);
Assert.IsFalse(TestMessage.Handled);
Assert.IsEmpty(TestMessage.DeserializedValues);

var reader = new FastBufferReader(writer, Allocator.Temp);
using (reader)
{
m_MessageManager.HandleIncomingData(0, new ArraySegment<byte>(writer.ToArray()), 0);
Assert.IsFalse(TestMessage.Deserialized);
Assert.IsFalse(TestMessage.Handled);
Assert.IsEmpty(TestMessage.DeserializedValues);
m_MessageManager.ProcessIncomingMessageQueue();
Assert.IsTrue(TestMessage.Deserialized);
Assert.IsTrue(TestMessage.Handled);
Assert.AreEqual(2, TestMessage.DeserializedValues.Count);
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);
Assert.AreEqual(message2, TestMessage.DeserializedValues[1]);

m_MessageManager.ProcessIncomingMessageQueue();
Assert.IsTrue(TestMessage.Deserialized);
Assert.IsTrue(TestMessage.Handled);
Assert.AreEqual(2, TestMessage.DeserializedValues.Count);
Assert.AreEqual(message, TestMessage.DeserializedValues[0]);
Assert.AreEqual(message2, TestMessage.DeserializedValues[1]);
}
}
// Check for GC Allocations
Assert.That(() =>
{
m_MessageManager.HandleIncomingData(0, data, 0);
m_MessageManager.ProcessIncomingMessageQueue();
}, Is.Not.AllocatingGCMemory());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private unsafe void RunTypeTest<T>(T value) where T : unmanaged
using (reader)
{

var outVal = new T();
var outVal = default(T);
MethodInfo method;
if (value is Enum)
{
Expand Down
Loading