您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

536 行
20 KiB

#if MULTIPLAYER_TOOLS
using System;
using System.Collections.Generic;
using Unity.Multiplayer.Tools;
using Unity.Multiplayer.Tools.MetricTypes;
using Unity.Multiplayer.Tools.NetStats;
using Unity.Profiling;
namespace Unity.Netcode
{
internal class NetworkMetrics : INetworkMetrics
{
private const ulong k_MaxMetricsPerFrame = 1000L;
private static Dictionary<uint, string> s_SceneEventTypeNames;
private static ProfilerMarker s_FrameDispatch = new ProfilerMarker($"{nameof(NetworkMetrics)}.DispatchFrame");
static NetworkMetrics()
{
s_SceneEventTypeNames = new Dictionary<uint, string>();
foreach (SceneEventType type in Enum.GetValues(typeof(SceneEventType)))
{
s_SceneEventTypeNames[(uint)type] = type.ToString();
}
}
private static string GetSceneEventTypeName(uint typeCode)
{
if (!s_SceneEventTypeNames.TryGetValue(typeCode, out string name))
{
name = "Unknown";
}
return name;
}
private readonly Counter m_TransportBytesSent = new Counter(NetworkMetricTypes.TotalBytesSent.Id)
{
ShouldResetOnDispatch = true,
};
private readonly Counter m_TransportBytesReceived = new Counter(NetworkMetricTypes.TotalBytesReceived.Id)
{
ShouldResetOnDispatch = true,
};
private readonly EventMetric<NetworkMessageEvent> m_NetworkMessageSentEvent = new EventMetric<NetworkMessageEvent>(NetworkMetricTypes.NetworkMessageSent.Id);
private readonly EventMetric<NetworkMessageEvent> m_NetworkMessageReceivedEvent = new EventMetric<NetworkMessageEvent>(NetworkMetricTypes.NetworkMessageReceived.Id);
private readonly EventMetric<NamedMessageEvent> m_NamedMessageSentEvent = new EventMetric<NamedMessageEvent>(NetworkMetricTypes.NamedMessageSent.Id);
private readonly EventMetric<NamedMessageEvent> m_NamedMessageReceivedEvent = new EventMetric<NamedMessageEvent>(NetworkMetricTypes.NamedMessageReceived.Id);
private readonly EventMetric<UnnamedMessageEvent> m_UnnamedMessageSentEvent = new EventMetric<UnnamedMessageEvent>(NetworkMetricTypes.UnnamedMessageSent.Id);
private readonly EventMetric<UnnamedMessageEvent> m_UnnamedMessageReceivedEvent = new EventMetric<UnnamedMessageEvent>(NetworkMetricTypes.UnnamedMessageReceived.Id);
private readonly EventMetric<NetworkVariableEvent> m_NetworkVariableDeltaSentEvent = new EventMetric<NetworkVariableEvent>(NetworkMetricTypes.NetworkVariableDeltaSent.Id);
private readonly EventMetric<NetworkVariableEvent> m_NetworkVariableDeltaReceivedEvent = new EventMetric<NetworkVariableEvent>(NetworkMetricTypes.NetworkVariableDeltaReceived.Id);
private readonly EventMetric<OwnershipChangeEvent> m_OwnershipChangeSentEvent = new EventMetric<OwnershipChangeEvent>(NetworkMetricTypes.OwnershipChangeSent.Id);
private readonly EventMetric<OwnershipChangeEvent> m_OwnershipChangeReceivedEvent = new EventMetric<OwnershipChangeEvent>(NetworkMetricTypes.OwnershipChangeReceived.Id);
private readonly EventMetric<ObjectSpawnedEvent> m_ObjectSpawnSentEvent = new EventMetric<ObjectSpawnedEvent>(NetworkMetricTypes.ObjectSpawnedSent.Id);
private readonly EventMetric<ObjectSpawnedEvent> m_ObjectSpawnReceivedEvent = new EventMetric<ObjectSpawnedEvent>(NetworkMetricTypes.ObjectSpawnedReceived.Id);
private readonly EventMetric<ObjectDestroyedEvent> m_ObjectDestroySentEvent = new EventMetric<ObjectDestroyedEvent>(NetworkMetricTypes.ObjectDestroyedSent.Id);
private readonly EventMetric<ObjectDestroyedEvent> m_ObjectDestroyReceivedEvent = new EventMetric<ObjectDestroyedEvent>(NetworkMetricTypes.ObjectDestroyedReceived.Id);
private readonly EventMetric<RpcEvent> m_RpcSentEvent = new EventMetric<RpcEvent>(NetworkMetricTypes.RpcSent.Id);
private readonly EventMetric<RpcEvent> m_RpcReceivedEvent = new EventMetric<RpcEvent>(NetworkMetricTypes.RpcReceived.Id);
private readonly EventMetric<ServerLogEvent> m_ServerLogSentEvent = new EventMetric<ServerLogEvent>(NetworkMetricTypes.ServerLogSent.Id);
private readonly EventMetric<ServerLogEvent> m_ServerLogReceivedEvent = new EventMetric<ServerLogEvent>(NetworkMetricTypes.ServerLogReceived.Id);
private readonly EventMetric<SceneEventMetric> m_SceneEventSentEvent = new EventMetric<SceneEventMetric>(NetworkMetricTypes.SceneEventSent.Id);
private readonly EventMetric<SceneEventMetric> m_SceneEventReceivedEvent = new EventMetric<SceneEventMetric>(NetworkMetricTypes.SceneEventReceived.Id);
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
private readonly Counter m_PacketSentCounter = new Counter(NetworkMetricTypes.PacketsSent.Id)
{
ShouldResetOnDispatch = true,
};
private readonly Counter m_PacketReceivedCounter = new Counter(NetworkMetricTypes.PacketsReceived.Id)
{
ShouldResetOnDispatch = true,
};
private readonly Gauge m_RttToServerGauge = new Gauge(NetworkMetricTypes.RttToServer.Id)
{
ShouldResetOnDispatch = true,
};
private readonly Gauge m_NetworkObjectsGauge = new Gauge(NetworkMetricTypes.NetworkObjects.Id)
{
ShouldResetOnDispatch = true,
};
private readonly Gauge m_ConnectionsGauge = new Gauge(NetworkMetricTypes.ConnectedClients.Id)
{
ShouldResetOnDispatch = true,
};
private readonly Gauge m_PacketLossGauge = new Gauge(NetworkMetricTypes.PacketLoss.Id);
#endif
private ulong m_NumberOfMetricsThisFrame;
public NetworkMetrics()
{
Dispatcher = new MetricDispatcherBuilder()
.WithCounters(m_TransportBytesSent, m_TransportBytesReceived)
.WithMetricEvents(m_NetworkMessageSentEvent, m_NetworkMessageReceivedEvent)
.WithMetricEvents(m_NamedMessageSentEvent, m_NamedMessageReceivedEvent)
.WithMetricEvents(m_UnnamedMessageSentEvent, m_UnnamedMessageReceivedEvent)
.WithMetricEvents(m_NetworkVariableDeltaSentEvent, m_NetworkVariableDeltaReceivedEvent)
.WithMetricEvents(m_OwnershipChangeSentEvent, m_OwnershipChangeReceivedEvent)
.WithMetricEvents(m_ObjectSpawnSentEvent, m_ObjectSpawnReceivedEvent)
.WithMetricEvents(m_ObjectDestroySentEvent, m_ObjectDestroyReceivedEvent)
.WithMetricEvents(m_RpcSentEvent, m_RpcReceivedEvent)
.WithMetricEvents(m_ServerLogSentEvent, m_ServerLogReceivedEvent)
.WithMetricEvents(m_SceneEventSentEvent, m_SceneEventReceivedEvent)
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
.WithCounters(m_PacketSentCounter, m_PacketReceivedCounter)
.WithGauges(m_RttToServerGauge)
.WithGauges(m_NetworkObjectsGauge)
.WithGauges(m_ConnectionsGauge)
.WithGauges(m_PacketLossGauge)
#endif
.Build();
Dispatcher.RegisterObserver(NetcodeObserver.Observer);
}
internal IMetricDispatcher Dispatcher { get; }
private bool CanSendMetrics => m_NumberOfMetricsThisFrame < k_MaxMetricsPerFrame;
public void SetConnectionId(ulong connectionId)
{
Dispatcher.SetConnectionId(connectionId);
}
public void TrackTransportBytesSent(long bytesCount)
{
m_TransportBytesSent.Increment(bytesCount);
}
public void TrackTransportBytesReceived(long bytesCount)
{
m_TransportBytesReceived.Increment(bytesCount);
}
public void TrackNetworkMessageSent(ulong receivedClientId, string messageType, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_NetworkMessageSentEvent.Mark(new NetworkMessageEvent(new ConnectionInfo(receivedClientId), messageType, bytesCount));
IncrementMetricCount();
}
public void TrackNetworkMessageReceived(ulong senderClientId, string messageType, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_NetworkMessageReceivedEvent.Mark(new NetworkMessageEvent(new ConnectionInfo(senderClientId), messageType, bytesCount));
IncrementMetricCount();
}
public void TrackNamedMessageSent(ulong receiverClientId, string messageName, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_NamedMessageSentEvent.Mark(new NamedMessageEvent(new ConnectionInfo(receiverClientId), messageName, bytesCount));
IncrementMetricCount();
}
public void TrackNamedMessageSent(IReadOnlyCollection<ulong> receiverClientIds, string messageName, long bytesCount)
{
foreach (var receiver in receiverClientIds)
{
TrackNamedMessageSent(receiver, messageName, bytesCount);
}
}
public void TrackNamedMessageReceived(ulong senderClientId, string messageName, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_NamedMessageReceivedEvent.Mark(new NamedMessageEvent(new ConnectionInfo(senderClientId), messageName, bytesCount));
IncrementMetricCount();
}
public void TrackUnnamedMessageSent(ulong receiverClientId, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_UnnamedMessageSentEvent.Mark(new UnnamedMessageEvent(new ConnectionInfo(receiverClientId), bytesCount));
IncrementMetricCount();
}
public void TrackUnnamedMessageSent(IReadOnlyCollection<ulong> receiverClientIds, long bytesCount)
{
foreach (var receiverClientId in receiverClientIds)
{
TrackUnnamedMessageSent(receiverClientId, bytesCount);
}
}
public void TrackUnnamedMessageReceived(ulong senderClientId, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_UnnamedMessageReceivedEvent.Mark(new UnnamedMessageEvent(new ConnectionInfo(senderClientId), bytesCount));
IncrementMetricCount();
}
public void TrackNetworkVariableDeltaSent(
ulong receiverClientId,
NetworkObject networkObject,
string variableName,
string networkBehaviourName,
long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_NetworkVariableDeltaSentEvent.Mark(
new NetworkVariableEvent(
new ConnectionInfo(receiverClientId),
GetObjectIdentifier(networkObject),
variableName,
networkBehaviourName,
bytesCount));
IncrementMetricCount();
}
public void TrackNetworkVariableDeltaReceived(
ulong senderClientId,
NetworkObject networkObject,
string variableName,
string networkBehaviourName,
long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_NetworkVariableDeltaReceivedEvent.Mark(
new NetworkVariableEvent(
new ConnectionInfo(senderClientId),
GetObjectIdentifier(networkObject),
variableName,
networkBehaviourName,
bytesCount));
IncrementMetricCount();
}
public void TrackOwnershipChangeSent(ulong receiverClientId, NetworkObject networkObject, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_OwnershipChangeSentEvent.Mark(new OwnershipChangeEvent(new ConnectionInfo(receiverClientId), GetObjectIdentifier(networkObject), bytesCount));
IncrementMetricCount();
}
public void TrackOwnershipChangeReceived(ulong senderClientId, NetworkObject networkObject, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_OwnershipChangeReceivedEvent.Mark(new OwnershipChangeEvent(new ConnectionInfo(senderClientId),
GetObjectIdentifier(networkObject), bytesCount));
IncrementMetricCount();
}
public void TrackObjectSpawnSent(ulong receiverClientId, NetworkObject networkObject, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_ObjectSpawnSentEvent.Mark(new ObjectSpawnedEvent(new ConnectionInfo(receiverClientId), GetObjectIdentifier(networkObject), bytesCount));
IncrementMetricCount();
}
public void TrackObjectSpawnReceived(ulong senderClientId, NetworkObject networkObject, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_ObjectSpawnReceivedEvent.Mark(new ObjectSpawnedEvent(new ConnectionInfo(senderClientId), GetObjectIdentifier(networkObject), bytesCount));
IncrementMetricCount();
}
public void TrackObjectDestroySent(ulong receiverClientId, NetworkObject networkObject, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_ObjectDestroySentEvent.Mark(new ObjectDestroyedEvent(new ConnectionInfo(receiverClientId), GetObjectIdentifier(networkObject), bytesCount));
IncrementMetricCount();
}
public void TrackObjectDestroyReceived(ulong senderClientId, NetworkObject networkObject, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_ObjectDestroyReceivedEvent.Mark(new ObjectDestroyedEvent(new ConnectionInfo(senderClientId), GetObjectIdentifier(networkObject), bytesCount));
IncrementMetricCount();
}
public void TrackRpcSent(
ulong receiverClientId,
NetworkObject networkObject,
string rpcName,
string networkBehaviourName,
long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_RpcSentEvent.Mark(
new RpcEvent(
new ConnectionInfo(receiverClientId),
GetObjectIdentifier(networkObject),
rpcName,
networkBehaviourName,
bytesCount));
IncrementMetricCount();
}
public void TrackRpcSent(
ulong[] receiverClientIds,
NetworkObject networkObject,
string rpcName,
string networkBehaviourName,
long bytesCount)
{
foreach (var receiverClientId in receiverClientIds)
{
TrackRpcSent(receiverClientId, networkObject, rpcName, networkBehaviourName, bytesCount);
}
}
public void TrackRpcReceived(
ulong senderClientId,
NetworkObject networkObject,
string rpcName,
string networkBehaviourName,
long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_RpcReceivedEvent.Mark(
new RpcEvent(new ConnectionInfo(senderClientId),
GetObjectIdentifier(networkObject),
rpcName,
networkBehaviourName,
bytesCount));
IncrementMetricCount();
}
public void TrackServerLogSent(ulong receiverClientId, uint logType, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_ServerLogSentEvent.Mark(new ServerLogEvent(new ConnectionInfo(receiverClientId), (Multiplayer.Tools.MetricTypes.LogLevel)logType, bytesCount));
IncrementMetricCount();
}
public void TrackServerLogReceived(ulong senderClientId, uint logType, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_ServerLogReceivedEvent.Mark(new ServerLogEvent(new ConnectionInfo(senderClientId), (Multiplayer.Tools.MetricTypes.LogLevel)logType, bytesCount));
IncrementMetricCount();
}
public void TrackSceneEventSent(IReadOnlyList<ulong> receiverClientIds, uint sceneEventType, string sceneName, long bytesCount)
{
foreach (var receiverClientId in receiverClientIds)
{
TrackSceneEventSent(receiverClientId, sceneEventType, sceneName, bytesCount);
}
}
public void TrackSceneEventSent(ulong receiverClientId, uint sceneEventType, string sceneName, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_SceneEventSentEvent.Mark(new SceneEventMetric(new ConnectionInfo(receiverClientId), GetSceneEventTypeName(sceneEventType), sceneName, bytesCount));
IncrementMetricCount();
}
public void TrackSceneEventReceived(ulong senderClientId, uint sceneEventType, string sceneName, long bytesCount)
{
if (!CanSendMetrics)
{
return;
}
m_SceneEventReceivedEvent.Mark(new SceneEventMetric(new ConnectionInfo(senderClientId), GetSceneEventTypeName(sceneEventType), sceneName, bytesCount));
IncrementMetricCount();
}
public void TrackPacketSent(uint packetCount)
{
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
if (!CanSendMetrics)
{
return;
}
m_PacketSentCounter.Increment(packetCount);
IncrementMetricCount();
#endif
}
public void TrackPacketReceived(uint packetCount)
{
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
if (!CanSendMetrics)
{
return;
}
m_PacketReceivedCounter.Increment(packetCount);
IncrementMetricCount();
#endif
}
public void UpdateRttToServer(int rttMilliseconds)
{
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
if (!CanSendMetrics)
{
return;
}
var rttSeconds = rttMilliseconds * 1e-3;
m_RttToServerGauge.Set(rttSeconds);
#endif
}
public void UpdateNetworkObjectsCount(int count)
{
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
if (!CanSendMetrics)
{
return;
}
m_NetworkObjectsGauge.Set(count);
#endif
}
public void UpdateConnectionsCount(int count)
{
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
if (!CanSendMetrics)
{
return;
}
m_ConnectionsGauge.Set(count);
#endif
}
public void UpdatePacketLoss(float packetLoss)
{
#if MULTIPLAYER_TOOLS_1_0_0_PRE_7
if (!CanSendMetrics)
{
return;
}
m_PacketLossGauge.Set(packetLoss);
#endif
}
public void DispatchFrame()
{
s_FrameDispatch.Begin();
Dispatcher.Dispatch();
s_FrameDispatch.End();
m_NumberOfMetricsThisFrame = 0;
}
private void IncrementMetricCount()
{
m_NumberOfMetricsThisFrame++;
}
private static NetworkObjectIdentifier GetObjectIdentifier(NetworkObject networkObject)
{
return new NetworkObjectIdentifier(networkObject.GetNameForMetrics(), networkObject.NetworkObjectId);
}
}
internal class NetcodeObserver
{
public static IMetricObserver Observer { get; } = MetricObserverFactory.Construct();
}
}
#endif