com.unity.netcode.gameobjects@1.0.0-pre.6
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [1.0.0-pre.6] - 2022-03-02 ### Added - NetworkAnimator now properly synchrhonizes all animation layers as well as runtime-adjusted weighting between them (#1765) - Added first set of tests for NetworkAnimator - parameter syncing, trigger set / reset, override network animator (#1735) ### Changed ### Fixed - Fixed an issue where sometimes the first client to connect to the server could see messages from the server as coming from itself. (#1683) - Fixed an issue where clients seemed to be able to send messages to ClientId 1, but these messages would actually still go to the server (id 0) instead of that client. (#1683) - Improved clarity of error messaging when a client attempts to send a message to a destination other than the server, which isn't allowed. (#1683) - Disallowed async keyword in RPCs (#1681) - Fixed an issue where Alpha release versions of Unity (version 2022.2.0a5 and later) will not compile due to the UNet Transport no longer existing (#1678) - Fixed messages larger than 64k being written with incorrectly truncated message size in header (#1686) (credit: @kaen) - Fixed overloading RPC methods causing collisions and failing on IL2CPP targets. (#1694) - Fixed spawn flow to propagate `IsSceneObject` down to children NetworkObjects, decouple implicit relationship between object spawning & `IsSceneObject` flag (#1685) - Fixed error when serializing ConnectionApprovalMessage with scene management disabled when one or more objects is hidden via the CheckObjectVisibility delegate (#1720) - Fixed CheckObjectVisibility delegate not being properly invoked for connecting clients when Scene Management is enabled. (#1680) - Fixed NetworkList to properly call INetworkSerializable's NetworkSerialize() method (#1682) - Fixed NetworkVariables containing more than 1300 bytes of data (such as large NetworkLists) no longer cause an OverflowException (the limit on data size is now whatever limit the chosen transport imposes on fragmented NetworkDelivery mechanisms) (#1725) - Fixed ServerRpcParams and ClientRpcParams must be the last parameter of an RPC in order to function properly. Added a compile-time check to ensure this is the case and trigger an error if they're placed elsewhere (#1721) - Fixed FastBufferReader being created with a length of 1 if provided an input of length 0 (#1724) - Fixed The NetworkConfig's checksum hash includes the NetworkTick so that clients with a different tickrate than the server are identified and not allowed to connect (#1728) - Fixed OwnedObjects not being properly modified when using ChangeOwnership (#1731) - Improved performance in NetworkAnimator (#1735) - Removed the "always sync" network animator (aka "autosend") parameters (#1746)
This commit is contained in:
@@ -5,8 +5,10 @@ using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo("Unity.Netcode.Editor.CodeGen")]
|
||||
[assembly: InternalsVisibleTo("Unity.Netcode.Editor")]
|
||||
[assembly: InternalsVisibleTo("TestProject.EditorTests")]
|
||||
[assembly: InternalsVisibleTo("TestProject.RuntimeTests")]
|
||||
[assembly: InternalsVisibleTo("TestProject.ToolsIntegration.RuntimeTests")]
|
||||
#endif
|
||||
[assembly: InternalsVisibleTo("TestProject.ToolsIntegration.RuntimeTests")]
|
||||
[assembly: InternalsVisibleTo("TestProject.RuntimeTests")]
|
||||
[assembly: InternalsVisibleTo("Unity.Netcode.RuntimeTests")]
|
||||
[assembly: InternalsVisibleTo("Unity.Netcode.TestHelpers.Runtime")]
|
||||
[assembly: InternalsVisibleTo("Unity.Netcode.Adapter.UTP")]
|
||||
|
||||
|
||||
@@ -239,6 +239,8 @@ namespace Unity.Netcode
|
||||
writer.WriteValueSafe(sortedEntry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteValueSafe(TickRate);
|
||||
writer.WriteValueSafe(ConnectionApproval);
|
||||
writer.WriteValueSafe(ForceSamePrefabs);
|
||||
writer.WriteValueSafe(EnableSceneManagement);
|
||||
|
||||
@@ -15,41 +15,56 @@ namespace Unity.Netcode
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
// RuntimeAccessModifiersILPP will make this `protected`
|
||||
internal enum __RpcExecStage
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
{
|
||||
None = 0,
|
||||
Server = 1,
|
||||
Client = 2
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
// NetworkBehaviourILPP will override this in derived classes to return the name of the concrete type
|
||||
internal virtual string __getTypeName() => nameof(NetworkBehaviour);
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
|
||||
#pragma warning disable 414 // disable assigned but its value is never used
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
[NonSerialized]
|
||||
// RuntimeAccessModifiersILPP will make this `protected`
|
||||
internal __RpcExecStage __rpc_exec_stage = __RpcExecStage.None;
|
||||
#pragma warning restore 414 // restore assigned but its value is never used
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
|
||||
#pragma warning disable 414 // disable assigned but its value is never used
|
||||
private const int k_RpcMessageDefaultSize = 1024; // 1k
|
||||
private const int k_RpcMessageMaximumSize = 1024 * 64; // 64k
|
||||
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
// RuntimeAccessModifiersILPP will make this `protected`
|
||||
internal void __sendServerRpc(FastBufferWriter writer, uint rpcMethodId, ServerRpcParams rpcParams, RpcDelivery delivery)
|
||||
#pragma warning restore 414 // restore assigned but its value is never used
|
||||
internal FastBufferWriter __beginSendServerRpc(uint rpcMethodId, ServerRpcParams serverRpcParams, RpcDelivery rpcDelivery)
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
{
|
||||
NetworkDelivery networkDelivery = NetworkDelivery.Reliable;
|
||||
switch (delivery)
|
||||
return new FastBufferWriter(k_RpcMessageDefaultSize, Allocator.Temp, k_RpcMessageMaximumSize);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
// RuntimeAccessModifiersILPP will make this `protected`
|
||||
internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMethodId, ServerRpcParams serverRpcParams, RpcDelivery rpcDelivery)
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
{
|
||||
var serverRpcMessage = new ServerRpcMessage
|
||||
{
|
||||
Metadata = new RpcMetadata
|
||||
{
|
||||
NetworkObjectId = NetworkObjectId,
|
||||
NetworkBehaviourId = NetworkBehaviourId,
|
||||
NetworkRpcMethodId = rpcMethodId,
|
||||
},
|
||||
WriteBuffer = bufferWriter
|
||||
};
|
||||
|
||||
NetworkDelivery networkDelivery;
|
||||
switch (rpcDelivery)
|
||||
{
|
||||
default:
|
||||
case RpcDelivery.Reliable:
|
||||
networkDelivery = NetworkDelivery.ReliableFragmentedSequenced;
|
||||
break;
|
||||
case RpcDelivery.Unreliable:
|
||||
if (writer.Length > MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE - sizeof(RpcMessage.RpcType) - sizeof(ulong) - sizeof(uint) - sizeof(ushort))
|
||||
if (bufferWriter.Length > MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE)
|
||||
{
|
||||
throw new OverflowException("RPC parameters are too large for unreliable delivery.");
|
||||
}
|
||||
@@ -57,42 +72,33 @@ namespace Unity.Netcode
|
||||
break;
|
||||
}
|
||||
|
||||
var message = new RpcMessage
|
||||
{
|
||||
Header = new RpcMessage.HeaderData
|
||||
{
|
||||
Type = RpcMessage.RpcType.Server,
|
||||
NetworkObjectId = NetworkObjectId,
|
||||
NetworkBehaviourId = NetworkBehaviourId,
|
||||
NetworkMethodId = rpcMethodId
|
||||
},
|
||||
RpcData = writer
|
||||
};
|
||||
|
||||
var rpcMessageSize = 0;
|
||||
var rpcWriteSize = 0;
|
||||
|
||||
// If we are a server/host then we just no op and send to ourself
|
||||
if (IsHost || IsServer)
|
||||
{
|
||||
using var tempBuffer = new FastBufferReader(writer, Allocator.Temp);
|
||||
using var tempBuffer = new FastBufferReader(bufferWriter, Allocator.Temp);
|
||||
var context = new NetworkContext
|
||||
{
|
||||
SenderId = NetworkManager.ServerClientId,
|
||||
Timestamp = Time.realtimeSinceStartup,
|
||||
SystemOwner = NetworkManager,
|
||||
// header information isn't valid since it's not a real message.
|
||||
// Passing false to canDefer prevents it being accessed.
|
||||
// RpcMessage doesn't access this stuff so it's just left empty.
|
||||
Header = new MessageHeader(),
|
||||
SerializedHeaderSize = 0,
|
||||
MessageSize = 0
|
||||
};
|
||||
message.Handle(tempBuffer, context, NetworkManager, NetworkManager.ServerClientId, false);
|
||||
rpcMessageSize = tempBuffer.Length;
|
||||
serverRpcMessage.ReadBuffer = tempBuffer;
|
||||
serverRpcMessage.Handle(ref context);
|
||||
rpcWriteSize = tempBuffer.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
rpcMessageSize = NetworkManager.SendMessage(message, networkDelivery, NetworkManager.ServerClientId);
|
||||
rpcWriteSize = NetworkManager.SendMessage(ref serverRpcMessage, networkDelivery, NetworkManager.ServerClientId);
|
||||
}
|
||||
|
||||
bufferWriter.Dispose();
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||
@@ -102,26 +108,44 @@ namespace Unity.Netcode
|
||||
NetworkObject,
|
||||
rpcMethodName,
|
||||
__getTypeName(),
|
||||
rpcMessageSize);
|
||||
rpcWriteSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma warning disable 414 // disable assigned but its value is never used
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
// RuntimeAccessModifiersILPP will make this `protected`
|
||||
internal unsafe void __sendClientRpc(FastBufferWriter writer, uint rpcMethodId, ClientRpcParams rpcParams, RpcDelivery delivery)
|
||||
#pragma warning disable 414 // disable assigned but its value is never used
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
internal FastBufferWriter __beginSendClientRpc(uint rpcMethodId, ClientRpcParams clientRpcParams, RpcDelivery rpcDelivery)
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
{
|
||||
NetworkDelivery networkDelivery = NetworkDelivery.Reliable;
|
||||
switch (delivery)
|
||||
return new FastBufferWriter(k_RpcMessageDefaultSize, Allocator.Temp, k_RpcMessageMaximumSize);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006 // disable naming rule violation check
|
||||
// RuntimeAccessModifiersILPP will make this `protected`
|
||||
internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMethodId, ClientRpcParams clientRpcParams, RpcDelivery rpcDelivery)
|
||||
#pragma warning restore IDE1006 // restore naming rule violation check
|
||||
{
|
||||
var clientRpcMessage = new ClientRpcMessage
|
||||
{
|
||||
Metadata = new RpcMetadata
|
||||
{
|
||||
NetworkObjectId = NetworkObjectId,
|
||||
NetworkBehaviourId = NetworkBehaviourId,
|
||||
NetworkRpcMethodId = rpcMethodId,
|
||||
},
|
||||
WriteBuffer = bufferWriter
|
||||
};
|
||||
|
||||
NetworkDelivery networkDelivery;
|
||||
switch (rpcDelivery)
|
||||
{
|
||||
default:
|
||||
case RpcDelivery.Reliable:
|
||||
networkDelivery = NetworkDelivery.ReliableFragmentedSequenced;
|
||||
break;
|
||||
case RpcDelivery.Unreliable:
|
||||
if (writer.Length > MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE - sizeof(RpcMessage.RpcType) - sizeof(ulong) - sizeof(uint) - sizeof(ushort))
|
||||
if (bufferWriter.Length > MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE)
|
||||
{
|
||||
throw new OverflowException("RPC parameters are too large for unreliable delivery.");
|
||||
}
|
||||
@@ -129,26 +153,15 @@ namespace Unity.Netcode
|
||||
break;
|
||||
}
|
||||
|
||||
var message = new RpcMessage
|
||||
{
|
||||
Header = new RpcMessage.HeaderData
|
||||
{
|
||||
Type = RpcMessage.RpcType.Client,
|
||||
NetworkObjectId = NetworkObjectId,
|
||||
NetworkBehaviourId = NetworkBehaviourId,
|
||||
NetworkMethodId = rpcMethodId
|
||||
},
|
||||
RpcData = writer
|
||||
};
|
||||
int messageSize;
|
||||
var rpcWriteSize = 0;
|
||||
|
||||
// We check to see if we need to shortcut for the case where we are the host/server and we can send a clientRPC
|
||||
// to ourself. Sadly we have to figure that out from the list of clientIds :(
|
||||
bool shouldSendToHost = false;
|
||||
|
||||
if (rpcParams.Send.TargetClientIds != null)
|
||||
if (clientRpcParams.Send.TargetClientIds != null)
|
||||
{
|
||||
foreach (var clientId in rpcParams.Send.TargetClientIds)
|
||||
foreach (var clientId in clientRpcParams.Send.TargetClientIds)
|
||||
{
|
||||
if (clientId == NetworkManager.ServerClientId)
|
||||
{
|
||||
@@ -157,11 +170,11 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
messageSize = NetworkManager.SendMessage(message, networkDelivery, in rpcParams.Send.TargetClientIds);
|
||||
rpcWriteSize = NetworkManager.SendMessage(ref clientRpcMessage, networkDelivery, in clientRpcParams.Send.TargetClientIds);
|
||||
}
|
||||
else if (rpcParams.Send.TargetClientIdsNativeArray != null)
|
||||
else if (clientRpcParams.Send.TargetClientIdsNativeArray != null)
|
||||
{
|
||||
foreach (var clientId in rpcParams.Send.TargetClientIdsNativeArray)
|
||||
foreach (var clientId in clientRpcParams.Send.TargetClientIdsNativeArray)
|
||||
{
|
||||
if (clientId == NetworkManager.ServerClientId)
|
||||
{
|
||||
@@ -170,32 +183,35 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
messageSize = NetworkManager.SendMessage(message, networkDelivery, rpcParams.Send.TargetClientIdsNativeArray.Value);
|
||||
rpcWriteSize = NetworkManager.SendMessage(ref clientRpcMessage, networkDelivery, clientRpcParams.Send.TargetClientIdsNativeArray.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldSendToHost = IsHost;
|
||||
messageSize = NetworkManager.SendMessage(message, networkDelivery, NetworkManager.ConnectedClientsIds);
|
||||
rpcWriteSize = NetworkManager.SendMessage(ref clientRpcMessage, networkDelivery, NetworkManager.ConnectedClientsIds);
|
||||
}
|
||||
|
||||
// If we are a server/host then we just no op and send to ourself
|
||||
if (shouldSendToHost)
|
||||
{
|
||||
using var tempBuffer = new FastBufferReader(writer, Allocator.Temp);
|
||||
using var tempBuffer = new FastBufferReader(bufferWriter, Allocator.Temp);
|
||||
var context = new NetworkContext
|
||||
{
|
||||
SenderId = NetworkManager.ServerClientId,
|
||||
Timestamp = Time.realtimeSinceStartup,
|
||||
SystemOwner = NetworkManager,
|
||||
// header information isn't valid since it's not a real message.
|
||||
// Passing false to canDefer prevents it being accessed.
|
||||
// RpcMessage doesn't access this stuff so it's just left empty.
|
||||
Header = new MessageHeader(),
|
||||
SerializedHeaderSize = 0,
|
||||
MessageSize = 0
|
||||
};
|
||||
message.Handle(tempBuffer, context, NetworkManager, NetworkManager.ServerClientId, false);
|
||||
messageSize = tempBuffer.Length;
|
||||
clientRpcMessage.ReadBuffer = tempBuffer;
|
||||
clientRpcMessage.Handle(ref context);
|
||||
}
|
||||
|
||||
bufferWriter.Dispose();
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName))
|
||||
{
|
||||
@@ -206,7 +222,7 @@ namespace Unity.Netcode
|
||||
NetworkObject,
|
||||
rpcMethodName,
|
||||
__getTypeName(),
|
||||
messageSize);
|
||||
rpcWriteSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -260,9 +276,9 @@ namespace Unity.Netcode
|
||||
{
|
||||
// Only server can MODIFY. So allow modification if network is either not running or we are server
|
||||
return !m_NetworkObject ||
|
||||
(m_NetworkObject.NetworkManager == null ||
|
||||
!m_NetworkObject.NetworkManager.IsListening ||
|
||||
m_NetworkObject.NetworkManager.IsServer);
|
||||
m_NetworkObject.NetworkManager == null ||
|
||||
m_NetworkObject.NetworkManager.IsListening == false ||
|
||||
m_NetworkObject.NetworkManager.IsServer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -284,10 +300,14 @@ namespace Unity.Netcode
|
||||
m_NetworkObject = GetComponentInParent<NetworkObject>();
|
||||
}
|
||||
|
||||
if (m_NetworkObject == null || NetworkManager.Singleton == null ||
|
||||
(NetworkManager.Singleton != null && !NetworkManager.Singleton.ShutdownInProgress))
|
||||
// ShutdownInProgress check:
|
||||
// This prevents an edge case scenario where the NetworkManager is shutting down but user code
|
||||
// in Update and/or in FixedUpdate could still be checking NetworkBehaviour.NetworkObject directly (i.e. does it exist?)
|
||||
// or NetworkBehaviour.IsSpawned (i.e. to early exit if not spawned) which, in turn, could generate several Warning messages
|
||||
// per spawned NetworkObject. Checking for ShutdownInProgress prevents these unnecessary LogWarning messages.
|
||||
if (m_NetworkObject == null && (NetworkManager.Singleton == null || !NetworkManager.Singleton.ShutdownInProgress))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel < LogLevel.Normal)
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning($"Could not get {nameof(NetworkObject)} for the {nameof(NetworkBehaviour)}. Are you missing a {nameof(NetworkObject)} component?");
|
||||
}
|
||||
@@ -349,10 +369,7 @@ namespace Unity.Netcode
|
||||
InitializeVariables();
|
||||
}
|
||||
|
||||
internal void InternalOnNetworkDespawn()
|
||||
{
|
||||
|
||||
}
|
||||
internal void InternalOnNetworkDespawn() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the local client gains ownership of this object
|
||||
@@ -428,8 +445,7 @@ namespace Unity.Netcode
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
instance = (NetworkVariableBase)Activator.CreateInstance(fieldType, true);
|
||||
sortedFields[i].SetValue(this, instance);
|
||||
throw new Exception($"{GetType().FullName}.{sortedFields[i].Name} cannot be null. All {nameof(NetworkVariableBase)} instances must be initialized.");
|
||||
}
|
||||
|
||||
instance.Initialize(this);
|
||||
@@ -542,7 +558,7 @@ namespace Unity.Netcode
|
||||
// so we don't have to do this serialization work if we're not going to use the result.
|
||||
if (IsServer && clientId == NetworkManager.ServerClientId)
|
||||
{
|
||||
var tmpWriter = new FastBufferWriter(MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE, Allocator.Temp);
|
||||
var tmpWriter = new FastBufferWriter(MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE, Allocator.Temp, MessagingSystem.FRAGMENTED_MESSAGE_MAX_SIZE);
|
||||
using (tmpWriter)
|
||||
{
|
||||
message.Serialize(tmpWriter);
|
||||
@@ -550,7 +566,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkManager.SendMessage(message, m_DeliveryTypesForNetworkVariableGroups[j], clientId);
|
||||
NetworkManager.SendMessage(ref message, m_DeliveryTypesForNetworkVariableGroups[j], clientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,11 +85,11 @@ namespace Unity.Netcode
|
||||
m_NetworkManager = manager;
|
||||
}
|
||||
|
||||
public void OnBeforeSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery)
|
||||
public void OnBeforeSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery, int messageSizeBytes)
|
||||
public void OnAfterSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage
|
||||
{
|
||||
}
|
||||
|
||||
@@ -139,6 +139,14 @@ namespace Unity.Netcode
|
||||
|
||||
return !m_NetworkManager.m_StopProcessingMessages;
|
||||
}
|
||||
|
||||
public void OnBeforeHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkManagerMessageSender : IMessageSender
|
||||
@@ -555,6 +563,8 @@ namespace Unity.Netcode
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkConfig.NetworkTransport.NetworkMetrics = NetworkMetrics;
|
||||
|
||||
//This 'if' should never enter
|
||||
if (SnapshotSystem != null)
|
||||
{
|
||||
@@ -583,6 +593,7 @@ namespace Unity.Netcode
|
||||
|
||||
// Always clear our prefab override links before building
|
||||
NetworkConfig.NetworkPrefabOverrideLinks.Clear();
|
||||
NetworkConfig.OverrideToNetworkPrefab.Clear();
|
||||
|
||||
// Build the NetworkPrefabOverrideLinks dictionary
|
||||
for (int i = 0; i < NetworkConfig.NetworkPrefabs.Count; i++)
|
||||
@@ -779,7 +790,7 @@ namespace Unity.Netcode
|
||||
|
||||
NetworkConfig.NetworkTransport.OnTransportEvent += HandleRawTransportPoll;
|
||||
|
||||
NetworkConfig.NetworkTransport.Initialize();
|
||||
NetworkConfig.NetworkTransport.Initialize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1299,7 +1310,7 @@ namespace Unity.Netcode
|
||||
ShouldSendConnectionData = NetworkConfig.ConnectionApproval,
|
||||
ConnectionData = NetworkConfig.ConnectionData
|
||||
};
|
||||
SendMessage(message, NetworkDelivery.ReliableSequenced, ServerClientId);
|
||||
SendMessage(ref message, NetworkDelivery.ReliableSequenced, ServerClientId);
|
||||
}
|
||||
|
||||
private IEnumerator ApprovalTimeout(ulong clientId)
|
||||
@@ -1324,12 +1335,12 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
private ulong TransportIdToClientId(ulong transportId)
|
||||
internal ulong TransportIdToClientId(ulong transportId)
|
||||
{
|
||||
return transportId == m_ServerTransportId ? ServerClientId : m_TransportIdToClientIdMap[transportId];
|
||||
}
|
||||
|
||||
private ulong ClientIdToTransportId(ulong clientId)
|
||||
internal ulong ClientIdToTransportId(ulong clientId)
|
||||
{
|
||||
return clientId == ServerClientId ? m_ServerTransportId : m_ClientIdToTransportIdMap[clientId];
|
||||
}
|
||||
@@ -1344,7 +1355,20 @@ namespace Unity.Netcode
|
||||
s_TransportConnect.Begin();
|
||||
#endif
|
||||
|
||||
clientId = m_NextClientId++;
|
||||
// Assumptions:
|
||||
// - When server receives a connection, it *must be* a client
|
||||
// - When client receives one, it *must be* the server
|
||||
// Client's can't connect to or talk to other clients.
|
||||
// Server is a sentinel so only one exists, if we are server, we can't be
|
||||
// connecting to it.
|
||||
if (IsServer)
|
||||
{
|
||||
clientId = m_NextClientId++;
|
||||
}
|
||||
else
|
||||
{
|
||||
clientId = ServerClientId;
|
||||
}
|
||||
m_ClientIdToTransportIdMap[clientId] = transportId;
|
||||
m_TransportIdToClientIdMap[transportId] = clientId;
|
||||
|
||||
@@ -1422,7 +1446,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<TMessageType, TClientIdListType>(in TMessageType message, NetworkDelivery delivery, in TClientIdListType clientIds)
|
||||
internal unsafe int SendMessage<TMessageType, TClientIdListType>(ref TMessageType message, NetworkDelivery delivery, in TClientIdListType clientIds)
|
||||
where TMessageType : INetworkMessage
|
||||
where TClientIdListType : IReadOnlyList<ulong>
|
||||
{
|
||||
@@ -1445,12 +1469,18 @@ namespace Unity.Netcode
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return MessagingSystem.SendMessage(message, delivery, nonServerIds, newIdx);
|
||||
return MessagingSystem.SendMessage(ref message, delivery, nonServerIds, newIdx);
|
||||
}
|
||||
return MessagingSystem.SendMessage(message, delivery, clientIds);
|
||||
// else
|
||||
if (clientIds.Count != 1 || clientIds[0] != ServerClientId)
|
||||
{
|
||||
throw new ArgumentException($"Clients may only send messages to {nameof(ServerClientId)}");
|
||||
}
|
||||
|
||||
return MessagingSystem.SendMessage(ref message, delivery, clientIds);
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<T>(in T message, NetworkDelivery delivery,
|
||||
internal unsafe int SendMessage<T>(ref T message, NetworkDelivery delivery,
|
||||
ulong* clientIds, int numClientIds)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
@@ -1473,19 +1503,24 @@ namespace Unity.Netcode
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return MessagingSystem.SendMessage(message, delivery, nonServerIds, newIdx);
|
||||
return MessagingSystem.SendMessage(ref message, delivery, nonServerIds, newIdx);
|
||||
}
|
||||
// else
|
||||
if (numClientIds != 1 || clientIds[0] != ServerClientId)
|
||||
{
|
||||
throw new ArgumentException($"Clients may only send messages to {nameof(ServerClientId)}");
|
||||
}
|
||||
|
||||
return MessagingSystem.SendMessage(message, delivery, clientIds, numClientIds);
|
||||
return MessagingSystem.SendMessage(ref message, delivery, clientIds, numClientIds);
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<T>(in T message, NetworkDelivery delivery, in NativeArray<ulong> clientIds)
|
||||
internal unsafe int SendMessage<T>(ref T message, NetworkDelivery delivery, in NativeArray<ulong> clientIds)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
return SendMessage(message, delivery, (ulong*)clientIds.GetUnsafePtr(), clientIds.Length);
|
||||
return SendMessage(ref message, delivery, (ulong*)clientIds.GetUnsafePtr(), clientIds.Length);
|
||||
}
|
||||
|
||||
internal int SendMessage<T>(in T message, NetworkDelivery delivery, ulong clientId)
|
||||
internal int SendMessage<T>(ref T message, NetworkDelivery delivery, ulong clientId)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
// Prevent server sending to itself
|
||||
@@ -1493,7 +1528,18 @@ namespace Unity.Netcode
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return MessagingSystem.SendMessage(message, delivery, clientId);
|
||||
|
||||
if (!IsServer && clientId != ServerClientId)
|
||||
{
|
||||
throw new ArgumentException($"Clients may only send messages to {nameof(ServerClientId)}");
|
||||
}
|
||||
return MessagingSystem.SendMessage(ref message, delivery, clientId);
|
||||
}
|
||||
|
||||
internal int SendPreSerializedMessage<T>(in FastBufferWriter writer, int maxSize, ref T message, NetworkDelivery delivery, ulong clientId)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
return MessagingSystem.SendPreSerializedMessage(writer, maxSize, ref message, delivery, clientId);
|
||||
}
|
||||
|
||||
internal void HandleIncomingData(ulong clientId, ArraySegment<byte> payload, float receiveTime)
|
||||
@@ -1517,7 +1563,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
if (!IsServer)
|
||||
{
|
||||
throw new NotServerException("Only server can disconnect remote clients. Use StopClient instead.");
|
||||
throw new NotServerException($"Only server can disconnect remote clients. Please use `{nameof(Shutdown)}()` instead.");
|
||||
}
|
||||
|
||||
OnClientDisconnectFromServer(clientId);
|
||||
@@ -1614,7 +1660,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
Tick = NetworkTickSystem.ServerTime.Tick
|
||||
};
|
||||
SendMessage(message, NetworkDelivery.Unreliable, ConnectedClientsIds);
|
||||
SendMessage(ref message, NetworkDelivery.Unreliable, ConnectedClientsIds);
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
s_SyncTime.End();
|
||||
#endif
|
||||
@@ -1661,12 +1707,11 @@ namespace Unity.Netcode
|
||||
{
|
||||
if (SpawnManager.SpawnedObjectsList.Count != 0)
|
||||
{
|
||||
message.SceneObjectCount = SpawnManager.SpawnedObjectsList.Count;
|
||||
message.SpawnedObjectsList = SpawnManager.SpawnedObjectsList;
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage(message, NetworkDelivery.ReliableFragmentedSequenced, ownerClientId);
|
||||
SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, ownerClientId);
|
||||
|
||||
// If scene management is enabled, then let NetworkSceneManager handle the initial scene and NetworkObject synchronization
|
||||
if (!NetworkConfig.EnableSceneManagement)
|
||||
@@ -1726,7 +1771,7 @@ namespace Unity.Netcode
|
||||
message.ObjectInfo.Header.HasParent = false;
|
||||
message.ObjectInfo.Header.IsPlayerObject = true;
|
||||
message.ObjectInfo.Header.OwnerClientId = clientId;
|
||||
var size = SendMessage(message, NetworkDelivery.ReliableFragmentedSequenced, clientPair.Key);
|
||||
var size = SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, clientPair.Key);
|
||||
NetworkMetrics.TrackObjectSpawnSent(clientPair.Key, ConnectedClients[clientId].PlayerObject, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Unity.Netcode
|
||||
var globalObjectIdString = UnityEditor.GlobalObjectId.GetGlobalObjectIdSlow(this).ToString();
|
||||
GlobalObjectIdHash = XXHash.Hash32(globalObjectIdString);
|
||||
}
|
||||
#endif
|
||||
#endif // UNITY_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Gets the NetworkManager that owns this NetworkObject instance
|
||||
@@ -328,7 +328,7 @@ namespace Unity.Netcode
|
||||
NetworkObjectId = NetworkObjectId
|
||||
};
|
||||
// Send destroy call
|
||||
var size = NetworkManager.SendMessage(message, NetworkDelivery.ReliableSequenced, clientId);
|
||||
var size = NetworkManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, clientId);
|
||||
NetworkManager.NetworkMetrics.TrackObjectDestroySent(clientId, this, size);
|
||||
}
|
||||
}
|
||||
@@ -714,7 +714,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
NetworkManager.SendMessage(message, NetworkDelivery.ReliableSequenced, clientIds, idx);
|
||||
NetworkManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, clientIds, idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1142,8 +1142,7 @@ namespace Unity.Netcode
|
||||
var globalObjectIdHash = NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash);
|
||||
return globalObjectIdHash == 0 ? GlobalObjectIdHash : globalObjectIdHash;
|
||||
}
|
||||
else
|
||||
if (NetworkManager.NetworkConfig.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash))
|
||||
else if (NetworkManager.NetworkConfig.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash))
|
||||
{
|
||||
return NetworkManager.NetworkConfig.OverrideToNetworkPrefab[GlobalObjectIdHash];
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Unity.Netcode
|
||||
internal List<SentSpawn> SentSpawns = new List<SentSpawn>();
|
||||
}
|
||||
|
||||
internal delegate int MockSendMessage(in SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId);
|
||||
internal delegate int MockSendMessage(ref SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId);
|
||||
internal delegate int MockSpawnObject(SnapshotSpawnCommand spawnCommand);
|
||||
internal delegate int MockDespawnObject(SnapshotDespawnCommand despawnCommand);
|
||||
|
||||
@@ -813,13 +813,22 @@ namespace Unity.Netcode
|
||||
WriteIndex(ref message);
|
||||
WriteSpawns(ref message, clientId);
|
||||
|
||||
if (m_NetworkManager)
|
||||
try
|
||||
{
|
||||
m_NetworkManager.SendMessage(message, NetworkDelivery.Unreliable, clientId);
|
||||
if (m_NetworkManager)
|
||||
{
|
||||
m_NetworkManager.SendMessage(ref message, NetworkDelivery.Unreliable, clientId);
|
||||
}
|
||||
else
|
||||
{
|
||||
MockSendMessage(ref message, NetworkDelivery.Unreliable, clientId);
|
||||
}
|
||||
}
|
||||
else
|
||||
finally
|
||||
{
|
||||
MockSendMessage(message, NetworkDelivery.Unreliable, clientId);
|
||||
message.Entries.Dispose();
|
||||
message.Spawns.Dispose();
|
||||
message.Despawns.Dispose();
|
||||
}
|
||||
|
||||
m_ClientData[clientId].LastReceivedSequence = 0;
|
||||
|
||||
@@ -62,8 +62,7 @@ namespace Unity.Netcode
|
||||
LogType = logType,
|
||||
Message = message
|
||||
};
|
||||
var size = NetworkManager.Singleton.SendMessage(networkMessage, NetworkDelivery.ReliableFragmentedSequenced,
|
||||
NetworkManager.Singleton.ServerClientId);
|
||||
var size = NetworkManager.Singleton.SendMessage(ref networkMessage, NetworkDelivery.ReliableFragmentedSequenced, NetworkManager.Singleton.ServerClientId);
|
||||
|
||||
NetworkManager.Singleton.NetworkMetrics.TrackServerLogSent(NetworkManager.Singleton.ServerClientId, (uint)logType, size);
|
||||
}
|
||||
|
||||
@@ -73,9 +73,9 @@ namespace Unity.Netcode
|
||||
|
||||
var message = new UnnamedMessage
|
||||
{
|
||||
Data = messageBuffer
|
||||
SendData = messageBuffer
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, networkDelivery, clientIds);
|
||||
var size = m_NetworkManager.SendMessage(ref message, networkDelivery, clientIds);
|
||||
|
||||
// Size is zero if we were only sending the message to ourself in which case it isn't sent.
|
||||
if (size != 0)
|
||||
@@ -94,9 +94,9 @@ namespace Unity.Netcode
|
||||
{
|
||||
var message = new UnnamedMessage
|
||||
{
|
||||
Data = messageBuffer
|
||||
SendData = messageBuffer
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, networkDelivery, clientId);
|
||||
var size = m_NetworkManager.SendMessage(ref message, networkDelivery, clientId);
|
||||
// Size is zero if we were only sending the message to ourself in which case it isn't sent.
|
||||
if (size != 0)
|
||||
{
|
||||
@@ -223,9 +223,9 @@ namespace Unity.Netcode
|
||||
var message = new NamedMessage
|
||||
{
|
||||
Hash = hash,
|
||||
Data = messageStream
|
||||
SendData = messageStream,
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, networkDelivery, clientId);
|
||||
var size = m_NetworkManager.SendMessage(ref message, networkDelivery, clientId);
|
||||
|
||||
// Size is zero if we were only sending the message to ourself in which case it isn't sent.
|
||||
if (size != 0)
|
||||
@@ -266,9 +266,9 @@ namespace Unity.Netcode
|
||||
var message = new NamedMessage
|
||||
{
|
||||
Hash = hash,
|
||||
Data = messageStream
|
||||
SendData = messageStream
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, networkDelivery, clientIds);
|
||||
var size = m_NetworkManager.SendMessage(ref message, networkDelivery, clientIds);
|
||||
|
||||
// Size is zero if we were only sending the message to ourself in which case it isn't sent.
|
||||
if (size != 0)
|
||||
|
||||
@@ -13,18 +13,18 @@ namespace Unity.Netcode
|
||||
/// Called before an individual message is sent.
|
||||
/// </summary>
|
||||
/// <param name="clientId">The destination clientId</param>
|
||||
/// <param name="messageType">The type of the message being sent</param>
|
||||
/// <param name="message">The message being sent</param>
|
||||
/// <param name="delivery"></param>
|
||||
void OnBeforeSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery);
|
||||
void OnBeforeSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Called after an individual message is sent.
|
||||
/// </summary>
|
||||
/// <param name="clientId">The destination clientId</param>
|
||||
/// <param name="messageType">The type of the message being sent</param>
|
||||
/// <param name="message">The message being sent</param>
|
||||
/// <param name="delivery"></param>
|
||||
/// <param name="messageSizeBytes">Number of bytes in the message, not including the message header</param>
|
||||
void OnAfterSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery, int messageSizeBytes);
|
||||
void OnAfterSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Called before an individual message is received.
|
||||
@@ -93,5 +93,23 @@ namespace Unity.Netcode
|
||||
/// <param name="messageType">The type of the message</param>
|
||||
/// <returns></returns>
|
||||
bool OnVerifyCanReceive(ulong senderId, Type messageType);
|
||||
|
||||
/// <summary>
|
||||
/// Called after a message is serialized, but before it's handled.
|
||||
/// Differs from OnBeforeReceiveMessage in that the actual message object is passed and can be inspected.
|
||||
/// </summary>
|
||||
/// <param name="message">The message object</param>
|
||||
/// <param name="context">The network context the message is being ahandled in</param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
void OnBeforeHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Called after a message is serialized and handled.
|
||||
/// Differs from OnAfterReceiveMessage in that the actual message object is passed and can be inspected.
|
||||
/// </summary>
|
||||
/// <param name="message">The message object</param>
|
||||
/// <param name="context">The network context the message is being ahandled in</param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
void OnAfterHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Unity.Netcode
|
||||
/// static message handler for receiving messages of the following name and signature:
|
||||
///
|
||||
/// <code>
|
||||
/// public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
/// public static void Receive(FastBufferReader reader, ref NetworkContext context)
|
||||
/// </code>
|
||||
///
|
||||
/// It is the responsibility of the Serialize and Receive methods to ensure there is enough buffer space
|
||||
@@ -40,10 +40,8 @@ namespace Unity.Netcode
|
||||
/// </summary>
|
||||
internal interface INetworkMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to serialize the message.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
void Serialize(FastBufferWriter writer);
|
||||
bool Deserialize(FastBufferReader reader, ref NetworkContext context);
|
||||
void Handle(ref NetworkContext context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,24 +10,28 @@ namespace Unity.Netcode
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsClient)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
reader.ReadValueSafe(out ChangeOwnershipMessage message);
|
||||
message.Handle(reader, context, context.SenderId, networkManager, reader.Length);
|
||||
reader.ReadValueSafe(out this);
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(NetworkObjectId, reader, ref context);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(FastBufferReader reader, in NetworkContext context, ulong senderId, NetworkManager networkManager, int messageSize)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject))
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(NetworkObjectId, reader, context);
|
||||
return;
|
||||
}
|
||||
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
var networkObject = networkManager.SpawnManager.SpawnedObjects[NetworkObjectId];
|
||||
|
||||
if (networkObject.OwnerClientId == networkManager.LocalClientId)
|
||||
{
|
||||
@@ -43,7 +47,7 @@ namespace Unity.Netcode
|
||||
networkObject.InvokeBehaviourOnGainedOwnership();
|
||||
}
|
||||
|
||||
networkManager.NetworkMetrics.TrackOwnershipChangeReceived(senderId, networkObject, messageSize);
|
||||
networkManager.NetworkMetrics.TrackOwnershipChangeReceived(context.SenderId, networkObject, context.MessageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,24 +7,27 @@ namespace Unity.Netcode
|
||||
{
|
||||
public ulong OwnerClientId;
|
||||
public int NetworkTick;
|
||||
public int SceneObjectCount;
|
||||
|
||||
// Not serialized, held as references to serialize NetworkVariable data
|
||||
public HashSet<NetworkObject> SpawnedObjectsList;
|
||||
|
||||
private FastBufferReader m_ReceivedSceneObjectData;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
if (!writer.TryBeginWrite(sizeof(ulong) + sizeof(int) + sizeof(int)))
|
||||
{
|
||||
throw new OverflowException(
|
||||
$"Not enough space in the write buffer to serialize {nameof(ConnectionApprovedMessage)}");
|
||||
throw new OverflowException($"Not enough space in the write buffer to serialize {nameof(ConnectionApprovedMessage)}");
|
||||
}
|
||||
writer.WriteValue(OwnerClientId);
|
||||
writer.WriteValue(NetworkTick);
|
||||
writer.WriteValue(SceneObjectCount);
|
||||
|
||||
if (SceneObjectCount != 0)
|
||||
uint sceneObjectCount = 0;
|
||||
if (SpawnedObjectsList != null)
|
||||
{
|
||||
var pos = writer.Position;
|
||||
writer.Seek(writer.Position + FastBufferWriter.GetWriteSize(sceneObjectCount));
|
||||
|
||||
// Serialize NetworkVariable data
|
||||
foreach (var sobj in SpawnedObjectsList)
|
||||
{
|
||||
@@ -33,34 +36,41 @@ namespace Unity.Netcode
|
||||
sobj.Observers.Add(OwnerClientId);
|
||||
var sceneObject = sobj.GetMessageSceneObject(OwnerClientId);
|
||||
sceneObject.Serialize(writer);
|
||||
++sceneObjectCount;
|
||||
}
|
||||
}
|
||||
writer.Seek(pos);
|
||||
writer.WriteValue(sceneObjectCount);
|
||||
writer.Seek(writer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteValue(sceneObjectCount);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsClient)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!reader.TryBeginRead(sizeof(ulong) + sizeof(int) + sizeof(int)))
|
||||
{
|
||||
throw new OverflowException(
|
||||
$"Not enough space in the buffer to read {nameof(ConnectionApprovedMessage)}");
|
||||
throw new OverflowException($"Not enough space in the buffer to read {nameof(ConnectionApprovedMessage)}");
|
||||
}
|
||||
|
||||
var message = new ConnectionApprovedMessage();
|
||||
reader.ReadValue(out message.OwnerClientId);
|
||||
reader.ReadValue(out message.NetworkTick);
|
||||
reader.ReadValue(out message.SceneObjectCount);
|
||||
message.Handle(reader, context.SenderId, networkManager);
|
||||
reader.ReadValue(out OwnerClientId);
|
||||
reader.ReadValue(out NetworkTick);
|
||||
m_ReceivedSceneObjectData = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(FastBufferReader reader, ulong clientId, NetworkManager networkManager)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
networkManager.LocalClientId = OwnerClientId;
|
||||
networkManager.NetworkMetrics.SetConnectionId(networkManager.LocalClientId);
|
||||
|
||||
@@ -74,20 +84,21 @@ namespace Unity.Netcode
|
||||
if (!networkManager.NetworkConfig.EnableSceneManagement)
|
||||
{
|
||||
networkManager.SpawnManager.DestroySceneObjects();
|
||||
m_ReceivedSceneObjectData.ReadValue(out uint sceneObjectCount);
|
||||
|
||||
// Deserializing NetworkVariable data is deferred from Receive() to Handle to avoid needing
|
||||
// to create a list to hold the data. This is a breach of convention for performance reasons.
|
||||
for (ushort i = 0; i < SceneObjectCount; i++)
|
||||
for (ushort i = 0; i < sceneObjectCount; i++)
|
||||
{
|
||||
var sceneObject = new NetworkObject.SceneObject();
|
||||
sceneObject.Deserialize(reader);
|
||||
NetworkObject.AddSceneObject(sceneObject, reader, networkManager);
|
||||
sceneObject.Deserialize(m_ReceivedSceneObjectData);
|
||||
NetworkObject.AddSceneObject(sceneObject, m_ReceivedSceneObjectData, networkManager);
|
||||
}
|
||||
|
||||
// Mark the client being connected
|
||||
networkManager.IsConnectedClient = true;
|
||||
// When scene management is disabled we notify after everything is synchronized
|
||||
networkManager.InvokeOnClientConnectedCallback(clientId);
|
||||
networkManager.InvokeOnClientConnectedCallback(context.SenderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,19 +21,17 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsServer)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var message = new ConnectionRequestMessage();
|
||||
if (networkManager.NetworkConfig.ConnectionApproval)
|
||||
{
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(message.ConfigHash) +
|
||||
FastBufferWriter.GetWriteSize<int>()))
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(ConfigHash) + FastBufferWriter.GetWriteSize<int>()))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
@@ -41,11 +39,12 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
networkManager.DisconnectClient(context.SenderId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
reader.ReadValue(out message.ConfigHash);
|
||||
|
||||
if (!networkManager.NetworkConfig.CompareConfig(message.ConfigHash))
|
||||
reader.ReadValue(out ConfigHash);
|
||||
|
||||
if (!networkManager.NetworkConfig.CompareConfig(ConfigHash))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
@@ -53,14 +52,14 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
networkManager.DisconnectClient(context.SenderId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
reader.ReadValueSafe(out message.ConnectionData);
|
||||
reader.ReadValueSafe(out ConnectionData);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(message.ConfigHash)))
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(ConfigHash)))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
@@ -68,11 +67,11 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
networkManager.DisconnectClient(context.SenderId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
reader.ReadValue(out message.ConfigHash);
|
||||
reader.ReadValue(out ConfigHash);
|
||||
|
||||
if (!networkManager.NetworkConfig.CompareConfig(message.ConfigHash))
|
||||
if (!networkManager.NetworkConfig.CompareConfig(ConfigHash))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
@@ -80,14 +79,18 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
networkManager.DisconnectClient(context.SenderId);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
message.Handle(networkManager, context.SenderId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(NetworkManager networkManager, ulong senderId)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
var senderId = context.SenderId;
|
||||
|
||||
if (networkManager.PendingClients.TryGetValue(senderId, out PendingClient client))
|
||||
{
|
||||
// Set to pending approval to prevent future connection requests from being approved
|
||||
@@ -102,8 +105,7 @@ namespace Unity.Netcode
|
||||
(createPlayerObject, playerPrefabHash, approved, position, rotation) =>
|
||||
{
|
||||
var localCreatePlayerObject = createPlayerObject;
|
||||
networkManager.HandleApproval(senderId, localCreatePlayerObject, playerPrefabHash, approved,
|
||||
position, rotation);
|
||||
networkManager.HandleApproval(senderId, localCreatePlayerObject, playerPrefabHash, approved, position, rotation);
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
@@ -3,28 +3,33 @@ namespace Unity.Netcode
|
||||
internal struct CreateObjectMessage : INetworkMessage
|
||||
{
|
||||
public NetworkObject.SceneObject ObjectInfo;
|
||||
private FastBufferReader m_ReceivedNetworkVariableData;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
ObjectInfo.Serialize(writer);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsClient)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
var message = new CreateObjectMessage();
|
||||
message.ObjectInfo.Deserialize(reader);
|
||||
message.Handle(context.SenderId, reader, networkManager);
|
||||
|
||||
ObjectInfo.Deserialize(reader);
|
||||
m_ReceivedNetworkVariableData = reader;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ulong senderId, FastBufferReader reader, NetworkManager networkManager)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var networkObject = NetworkObject.AddSceneObject(ObjectInfo, reader, networkManager);
|
||||
networkManager.NetworkMetrics.TrackObjectSpawnReceived(senderId, networkObject, reader.Length);
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
var networkObject = NetworkObject.AddSceneObject(ObjectInfo, m_ReceivedNetworkVariableData, networkManager);
|
||||
|
||||
networkManager.NetworkMetrics.TrackObjectSpawnReceived(context.SenderId, networkObject, context.MessageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,32 +9,27 @@ namespace Unity.Netcode
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsClient)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
reader.ReadValueSafe(out DestroyObjectMessage message);
|
||||
message.Handle(context.SenderId, networkManager, reader.Length);
|
||||
reader.ReadValueSafe(out this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ulong senderId, NetworkManager networkManager, int messageSize)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject))
|
||||
{
|
||||
// This is the same check and log message that happens inside OnDespawnObject, but we have to do it here
|
||||
// while we still have access to the network ID, otherwise the log message will be less useful.
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning($"Trying to destroy {nameof(NetworkObject)} #{NetworkObjectId} but it does not exist in {nameof(NetworkSpawnManager.SpawnedObjects)} anymore!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
networkManager.NetworkMetrics.TrackObjectDestroyReceived(senderId, networkObject, messageSize);
|
||||
networkManager.NetworkMetrics.TrackObjectDestroyReceived(context.SenderId, networkObject, context.MessageSize);
|
||||
networkManager.SpawnManager.OnDespawnObject(networkObject, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,26 @@ namespace Unity.Netcode
|
||||
internal struct NamedMessage : INetworkMessage
|
||||
{
|
||||
public ulong Hash;
|
||||
public FastBufferWriter Data;
|
||||
public FastBufferWriter SendData;
|
||||
|
||||
private FastBufferReader m_ReceiveData;
|
||||
|
||||
public unsafe void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
writer.WriteValueSafe(Hash);
|
||||
writer.WriteBytesSafe(Data.GetUnsafePtr(), Data.Length);
|
||||
writer.WriteBytesSafe(SendData.GetUnsafePtr(), SendData.Length);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var message = new NamedMessage();
|
||||
reader.ReadValueSafe(out message.Hash);
|
||||
reader.ReadValueSafe(out Hash);
|
||||
m_ReceiveData = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
((NetworkManager)context.SystemOwner).CustomMessagingManager.InvokeNamedMessage(message.Hash, context.SenderId, reader, context.SerializedHeaderSize);
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
((NetworkManager)context.SystemOwner).CustomMessagingManager.InvokeNamedMessage(Hash, context.SenderId, m_ReceiveData, context.SerializedHeaderSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,18 @@ namespace Unity.Netcode
|
||||
public ulong ClientId;
|
||||
public NetworkBehaviour NetworkBehaviour;
|
||||
|
||||
private FastBufferReader m_ReceivedNetworkVariableData;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize(NetworkObjectId) +
|
||||
FastBufferWriter.GetWriteSize(NetworkBehaviourIndex)))
|
||||
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize(NetworkObjectId) + FastBufferWriter.GetWriteSize(NetworkBehaviourIndex)))
|
||||
{
|
||||
throw new OverflowException(
|
||||
$"Not enough space in the buffer to write {nameof(NetworkVariableDeltaMessage)}");
|
||||
throw new OverflowException($"Not enough space in the buffer to write {nameof(NetworkVariableDeltaMessage)}");
|
||||
}
|
||||
|
||||
writer.WriteValue(NetworkObjectId);
|
||||
writer.WriteValue(NetworkBehaviourIndex);
|
||||
|
||||
for (int k = 0; k < NetworkBehaviour.NetworkVariableFields.Count; k++)
|
||||
{
|
||||
if (!DeliveryMappedNetworkVariableIndex.Contains(k))
|
||||
@@ -36,7 +38,7 @@ namespace Unity.Netcode
|
||||
// This var does not belong to the currently iterating delivery group.
|
||||
if (NetworkBehaviour.NetworkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
{
|
||||
writer.WriteValueSafe((short)0);
|
||||
writer.WriteValueSafe((ushort)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,7 +71,12 @@ namespace Unity.Netcode
|
||||
var tmpWriter = new FastBufferWriter(MessagingSystem.NON_FRAGMENTED_MESSAGE_MAX_SIZE, Allocator.Temp, short.MaxValue);
|
||||
NetworkBehaviour.NetworkVariableFields[k].WriteDelta(tmpWriter);
|
||||
|
||||
writer.WriteValueSafe((ushort)tmpWriter.Length);
|
||||
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize<ushort>() + tmpWriter.Length))
|
||||
{
|
||||
throw new OverflowException($"Not enough space in the buffer to write {nameof(NetworkVariableDeltaMessage)}");
|
||||
}
|
||||
|
||||
writer.WriteValue((ushort)tmpWriter.Length);
|
||||
tmpWriter.CopyTo(writer);
|
||||
}
|
||||
else
|
||||
@@ -93,24 +100,25 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(NetworkObjectId) + FastBufferWriter.GetWriteSize(NetworkBehaviourIndex)))
|
||||
{
|
||||
throw new OverflowException($"Not enough data in the buffer to read {nameof(NetworkVariableDeltaMessage)}");
|
||||
}
|
||||
|
||||
reader.ReadValue(out NetworkObjectId);
|
||||
reader.ReadValue(out NetworkBehaviourIndex);
|
||||
|
||||
m_ReceivedNetworkVariableData = reader;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
|
||||
var message = new NetworkVariableDeltaMessage();
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(message.NetworkObjectId) +
|
||||
FastBufferWriter.GetWriteSize(message.NetworkBehaviourIndex)))
|
||||
{
|
||||
throw new OverflowException(
|
||||
$"Not enough data in the buffer to read {nameof(NetworkVariableDeltaMessage)}");
|
||||
}
|
||||
reader.ReadValue(out message.NetworkObjectId);
|
||||
reader.ReadValue(out message.NetworkBehaviourIndex);
|
||||
message.Handle(context.SenderId, reader, context, networkManager);
|
||||
}
|
||||
|
||||
public void Handle(ulong senderId, FastBufferReader reader, in NetworkContext context, NetworkManager networkManager)
|
||||
{
|
||||
if (networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out NetworkObject networkObject))
|
||||
{
|
||||
NetworkBehaviour behaviour = networkObject.GetNetworkBehaviourAtOrderIndex(NetworkBehaviourIndex);
|
||||
@@ -130,7 +138,7 @@ namespace Unity.Netcode
|
||||
|
||||
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
{
|
||||
reader.ReadValueSafe(out varSize);
|
||||
m_ReceivedNetworkVariableData.ReadValueSafe(out varSize);
|
||||
|
||||
if (varSize == 0)
|
||||
{
|
||||
@@ -139,7 +147,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.ReadValueSafe(out bool deltaExists);
|
||||
m_ReceivedNetworkVariableData.ReadValueSafe(out bool deltaExists);
|
||||
if (!deltaExists)
|
||||
{
|
||||
continue;
|
||||
@@ -157,7 +165,7 @@ namespace Unity.Netcode
|
||||
NetworkLog.LogError($"[{behaviour.NetworkVariableFields[i].GetType().Name}]");
|
||||
}
|
||||
|
||||
reader.Seek(reader.Position + varSize);
|
||||
m_ReceivedNetworkVariableData.Seek(m_ReceivedNetworkVariableData.Position + varSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -176,39 +184,37 @@ namespace Unity.Netcode
|
||||
|
||||
return;
|
||||
}
|
||||
int readStartPos = reader.Position;
|
||||
int readStartPos = m_ReceivedNetworkVariableData.Position;
|
||||
|
||||
behaviour.NetworkVariableFields[i].ReadDelta(reader, networkManager.IsServer);
|
||||
behaviour.NetworkVariableFields[i].ReadDelta(m_ReceivedNetworkVariableData, networkManager.IsServer);
|
||||
|
||||
networkManager.NetworkMetrics.TrackNetworkVariableDeltaReceived(
|
||||
senderId,
|
||||
context.SenderId,
|
||||
networkObject,
|
||||
behaviour.NetworkVariableFields[i].Name,
|
||||
behaviour.__getTypeName(),
|
||||
reader.Length);
|
||||
context.MessageSize);
|
||||
|
||||
|
||||
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
|
||||
{
|
||||
if (reader.Position > (readStartPos + varSize))
|
||||
if (m_ReceivedNetworkVariableData.Position > (readStartPos + varSize))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
$"Var delta read too far. {reader.Position - (readStartPos + varSize)} bytes. => {nameof(NetworkObjectId)}: {NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {networkObject.GetNetworkBehaviourOrderIndex(behaviour)} - VariableIndex: {i}");
|
||||
NetworkLog.LogWarning($"Var delta read too far. {m_ReceivedNetworkVariableData.Position - (readStartPos + varSize)} bytes. => {nameof(NetworkObjectId)}: {NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {networkObject.GetNetworkBehaviourOrderIndex(behaviour)} - VariableIndex: {i}");
|
||||
}
|
||||
|
||||
reader.Seek(readStartPos + varSize);
|
||||
m_ReceivedNetworkVariableData.Seek(readStartPos + varSize);
|
||||
}
|
||||
else if (reader.Position < (readStartPos + varSize))
|
||||
else if (m_ReceivedNetworkVariableData.Position < (readStartPos + varSize))
|
||||
{
|
||||
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
|
||||
{
|
||||
NetworkLog.LogWarning(
|
||||
$"Var delta read too little. {(readStartPos + varSize) - reader.Position} bytes. => {nameof(NetworkObjectId)}: {NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {networkObject.GetNetworkBehaviourOrderIndex(behaviour)} - VariableIndex: {i}");
|
||||
NetworkLog.LogWarning($"Var delta read too little. {(readStartPos + varSize) - m_ReceivedNetworkVariableData.Position} bytes. => {nameof(NetworkObjectId)}: {NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {networkObject.GetNetworkBehaviourOrderIndex(behaviour)} - VariableIndex: {i}");
|
||||
}
|
||||
|
||||
reader.Seek(readStartPos + varSize);
|
||||
m_ReceivedNetworkVariableData.Seek(readStartPos + varSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,7 +222,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
else
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(NetworkObjectId, reader, context);
|
||||
networkManager.SpawnManager.TriggerOnSpawn(NetworkObjectId, m_ReceivedNetworkVariableData, ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,42 +26,41 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsClient)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var message = new ParentSyncMessage();
|
||||
reader.ReadValueSafe(out message.NetworkObjectId);
|
||||
reader.ReadValueSafe(out message.IsReparented);
|
||||
if (message.IsReparented)
|
||||
reader.ReadValueSafe(out NetworkObjectId);
|
||||
reader.ReadValueSafe(out IsReparented);
|
||||
if (IsReparented)
|
||||
{
|
||||
reader.ReadValueSafe(out message.IsLatestParentSet);
|
||||
if (message.IsLatestParentSet)
|
||||
reader.ReadValueSafe(out IsLatestParentSet);
|
||||
if (IsLatestParentSet)
|
||||
{
|
||||
reader.ReadValueSafe(out ulong latestParent);
|
||||
message.LatestParent = latestParent;
|
||||
LatestParent = latestParent;
|
||||
}
|
||||
}
|
||||
|
||||
message.Handle(reader, context, networkManager);
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(NetworkObjectId, reader, ref context);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(FastBufferReader reader, in NetworkContext context, NetworkManager networkManager)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
if (networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
|
||||
{
|
||||
var networkObject = networkManager.SpawnManager.SpawnedObjects[NetworkObjectId];
|
||||
networkObject.SetNetworkParenting(IsReparented, LatestParent);
|
||||
networkObject.ApplyNetworkParenting();
|
||||
}
|
||||
else
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(NetworkObjectId, reader, context);
|
||||
}
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
var networkObject = networkManager.SpawnManager.SpawnedObjects[NetworkObjectId];
|
||||
networkObject.SetNetworkParenting(IsReparented, LatestParent);
|
||||
networkObject.ApplyNetworkParenting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.Netcode
|
||||
{
|
||||
internal struct RpcMessage : INetworkMessage
|
||||
{
|
||||
public enum RpcType : byte
|
||||
{
|
||||
Server,
|
||||
Client
|
||||
}
|
||||
|
||||
public struct HeaderData
|
||||
{
|
||||
public RpcType Type;
|
||||
public ulong NetworkObjectId;
|
||||
public ushort NetworkBehaviourId;
|
||||
public uint NetworkMethodId;
|
||||
}
|
||||
|
||||
public HeaderData Header;
|
||||
public FastBufferWriter RpcData;
|
||||
|
||||
|
||||
public unsafe void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize(Header) + RpcData.Length))
|
||||
{
|
||||
throw new OverflowException("Not enough space in the buffer to store RPC data.");
|
||||
}
|
||||
writer.WriteValue(Header);
|
||||
writer.WriteBytes(RpcData.GetUnsafePtr(), RpcData.Length);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
{
|
||||
var message = new RpcMessage();
|
||||
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(message.Header)))
|
||||
{
|
||||
throw new OverflowException("Not enough space in the buffer to read RPC data.");
|
||||
}
|
||||
reader.ReadValue(out message.Header);
|
||||
message.Handle(reader, context, (NetworkManager)context.SystemOwner, context.SenderId, true);
|
||||
}
|
||||
|
||||
public void Handle(FastBufferReader reader, in NetworkContext context, NetworkManager networkManager, ulong senderId, bool canDefer)
|
||||
{
|
||||
if (NetworkManager.__rpc_func_table.ContainsKey(Header.NetworkMethodId))
|
||||
{
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(Header.NetworkObjectId))
|
||||
{
|
||||
if (canDefer)
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(Header.NetworkObjectId, reader, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkLog.LogError($"Tried to invoke an RPC on a non-existent {nameof(NetworkObject)} with {nameof(canDefer)}=false");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var networkObject = networkManager.SpawnManager.SpawnedObjects[Header.NetworkObjectId];
|
||||
|
||||
var networkBehaviour = networkObject.GetNetworkBehaviourAtOrderIndex(Header.NetworkBehaviourId);
|
||||
if (networkBehaviour == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rpcParams = new __RpcParams();
|
||||
switch (Header.Type)
|
||||
{
|
||||
case RpcType.Server:
|
||||
rpcParams.Server = new ServerRpcParams
|
||||
{
|
||||
Receive = new ServerRpcReceiveParams
|
||||
{
|
||||
SenderClientId = senderId
|
||||
}
|
||||
};
|
||||
break;
|
||||
case RpcType.Client:
|
||||
rpcParams.Client = new ClientRpcParams
|
||||
{
|
||||
Receive = new ClientRpcReceiveParams
|
||||
{
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
NetworkManager.__rpc_func_table[Header.NetworkMethodId](networkBehaviour, reader, rpcParams);
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (NetworkManager.__rpc_name_table.TryGetValue(Header.NetworkMethodId, out var rpcMethodName))
|
||||
{
|
||||
networkManager.NetworkMetrics.TrackRpcReceived(
|
||||
senderId,
|
||||
networkObject,
|
||||
rpcMethodName,
|
||||
networkBehaviour.__getTypeName(),
|
||||
reader.Length);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
157
Runtime/Messaging/Messages/RpcMessages.cs
Normal file
157
Runtime/Messaging/Messages/RpcMessages.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace Unity.Netcode
|
||||
{
|
||||
internal static class RpcMessageHelpers
|
||||
{
|
||||
public static unsafe void Serialize(ref FastBufferWriter writer, ref RpcMetadata metadata, ref FastBufferWriter payload)
|
||||
{
|
||||
if (!writer.TryBeginWrite(FastBufferWriter.GetWriteSize<RpcMetadata>() + payload.Length))
|
||||
{
|
||||
throw new OverflowException("Not enough space in the buffer to store RPC data.");
|
||||
}
|
||||
|
||||
writer.WriteValue(metadata);
|
||||
writer.WriteBytes(payload.GetUnsafePtr(), payload.Length);
|
||||
}
|
||||
|
||||
public static unsafe bool Deserialize(ref FastBufferReader reader, ref NetworkContext context, ref RpcMetadata metadata, ref FastBufferReader payload)
|
||||
{
|
||||
int metadataSize = FastBufferWriter.GetWriteSize<RpcMetadata>();
|
||||
if (!reader.TryBeginRead(metadataSize))
|
||||
{
|
||||
throw new InvalidOperationException("Not enough data in the buffer to read RPC meta.");
|
||||
}
|
||||
|
||||
reader.ReadValue(out metadata);
|
||||
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(metadata.NetworkObjectId))
|
||||
{
|
||||
networkManager.SpawnManager.TriggerOnSpawn(metadata.NetworkObjectId, reader, ref context);
|
||||
return false;
|
||||
}
|
||||
|
||||
var networkObject = networkManager.SpawnManager.SpawnedObjects[metadata.NetworkObjectId];
|
||||
var networkBehaviour = networkManager.SpawnManager.SpawnedObjects[metadata.NetworkObjectId].GetNetworkBehaviourAtOrderIndex(metadata.NetworkBehaviourId);
|
||||
if (networkBehaviour == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NetworkManager.__rpc_func_table.ContainsKey(metadata.NetworkRpcMethodId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
payload = new FastBufferReader(reader.GetUnsafePtr() + metadataSize, Allocator.None, reader.Length - metadataSize);
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
if (NetworkManager.__rpc_name_table.TryGetValue(metadata.NetworkRpcMethodId, out var rpcMethodName))
|
||||
{
|
||||
networkManager.NetworkMetrics.TrackRpcReceived(
|
||||
context.SenderId,
|
||||
networkObject,
|
||||
rpcMethodName,
|
||||
networkBehaviour.__getTypeName(),
|
||||
reader.Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Handle(ref NetworkContext context, ref RpcMetadata metadata, ref FastBufferReader payload, ref __RpcParams rpcParams)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(metadata.NetworkObjectId, out var networkObject))
|
||||
{
|
||||
throw new InvalidOperationException($"An RPC called on a {nameof(NetworkObject)} that is not in the spawned objects list. Please make sure the {nameof(NetworkObject)} is spawned before calling RPCs.");
|
||||
}
|
||||
var networkBehaviour = networkObject.GetNetworkBehaviourAtOrderIndex(metadata.NetworkBehaviourId);
|
||||
|
||||
try
|
||||
{
|
||||
NetworkManager.__rpc_func_table[metadata.NetworkRpcMethodId](networkBehaviour, payload, rpcParams);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(new Exception("Unhandled RPC exception!", ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal struct RpcMetadata
|
||||
{
|
||||
public ulong NetworkObjectId;
|
||||
public ushort NetworkBehaviourId;
|
||||
public uint NetworkRpcMethodId;
|
||||
}
|
||||
|
||||
internal struct ServerRpcMessage : INetworkMessage
|
||||
{
|
||||
public RpcMetadata Metadata;
|
||||
|
||||
public FastBufferWriter WriteBuffer;
|
||||
public FastBufferReader ReadBuffer;
|
||||
|
||||
public unsafe void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
RpcMessageHelpers.Serialize(ref writer, ref Metadata, ref WriteBuffer);
|
||||
}
|
||||
|
||||
public unsafe bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return RpcMessageHelpers.Deserialize(ref reader, ref context, ref Metadata, ref ReadBuffer);
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var rpcParams = new __RpcParams
|
||||
{
|
||||
Server = new ServerRpcParams
|
||||
{
|
||||
Receive = new ServerRpcReceiveParams
|
||||
{
|
||||
SenderClientId = context.SenderId
|
||||
}
|
||||
}
|
||||
};
|
||||
RpcMessageHelpers.Handle(ref context, ref Metadata, ref ReadBuffer, ref rpcParams);
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ClientRpcMessage : INetworkMessage
|
||||
{
|
||||
public RpcMetadata Metadata;
|
||||
|
||||
public FastBufferWriter WriteBuffer;
|
||||
public FastBufferReader ReadBuffer;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
RpcMessageHelpers.Serialize(ref writer, ref Metadata, ref WriteBuffer);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
return RpcMessageHelpers.Deserialize(ref reader, ref context, ref Metadata, ref ReadBuffer);
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var rpcParams = new __RpcParams
|
||||
{
|
||||
Client = new ClientRpcParams
|
||||
{
|
||||
Receive = new ClientRpcReceiveParams
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
RpcMessageHelpers.Handle(ref context, ref Metadata, ref ReadBuffer, ref rpcParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,22 @@ namespace Unity.Netcode
|
||||
{
|
||||
public SceneEventData EventData;
|
||||
|
||||
private FastBufferReader m_ReceivedData;
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
EventData.Serialize(writer);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
((NetworkManager)context.SystemOwner).SceneManager.HandleSceneEvent(context.SenderId, reader);
|
||||
m_ReceivedData = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
((NetworkManager)context.SystemOwner).SceneManager.HandleSceneEvent(context.SenderId, m_ReceivedData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,21 +17,25 @@ namespace Unity.Netcode
|
||||
BytePacker.WriteValuePacked(writer, Message);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (networkManager.IsServer && networkManager.NetworkConfig.EnableNetworkLogs)
|
||||
{
|
||||
var message = new ServerLogMessage();
|
||||
reader.ReadValueSafe(out message.LogType);
|
||||
ByteUnpacker.ReadValuePacked(reader, out message.Message);
|
||||
message.Handle(context.SenderId, networkManager, reader.Length);
|
||||
reader.ReadValueSafe(out LogType);
|
||||
ByteUnpacker.ReadValuePacked(reader, out Message);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Handle(ulong senderId, NetworkManager networkManager, int messageSize)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
networkManager.NetworkMetrics.TrackServerLogReceived(senderId, (uint)LogType, messageSize);
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
var senderId = context.SenderId;
|
||||
|
||||
networkManager.NetworkMetrics.TrackServerLogReceived(senderId, (uint)LogType, context.MessageSize);
|
||||
|
||||
switch (LogType)
|
||||
{
|
||||
|
||||
@@ -76,9 +76,6 @@ namespace Unity.Netcode
|
||||
Despawns.Length * sizeof(DespawnData)
|
||||
))
|
||||
{
|
||||
Entries.Dispose();
|
||||
Spawns.Dispose();
|
||||
Despawns.Dispose();
|
||||
throw new OverflowException($"Not enough space to serialize {nameof(SnapshotDataMessage)}");
|
||||
}
|
||||
writer.WriteValue(CurrentTick);
|
||||
@@ -96,76 +93,67 @@ namespace Unity.Netcode
|
||||
|
||||
writer.WriteValue((ushort)Despawns.Length);
|
||||
writer.WriteBytes((byte*)Despawns.GetUnsafePtr(), Despawns.Length * sizeof(DespawnData));
|
||||
|
||||
Entries.Dispose();
|
||||
Spawns.Dispose();
|
||||
Despawns.Dispose();
|
||||
}
|
||||
|
||||
public static unsafe void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public unsafe bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var message = new SnapshotDataMessage();
|
||||
if (!reader.TryBeginRead(
|
||||
FastBufferWriter.GetWriteSize(message.CurrentTick) +
|
||||
FastBufferWriter.GetWriteSize(message.Sequence) +
|
||||
FastBufferWriter.GetWriteSize(message.Range)
|
||||
FastBufferWriter.GetWriteSize(CurrentTick) +
|
||||
FastBufferWriter.GetWriteSize(Sequence) +
|
||||
FastBufferWriter.GetWriteSize(Range)
|
||||
))
|
||||
{
|
||||
throw new OverflowException($"Not enough space to deserialize {nameof(SnapshotDataMessage)}");
|
||||
}
|
||||
reader.ReadValue(out message.CurrentTick);
|
||||
reader.ReadValue(out message.Sequence);
|
||||
reader.ReadValue(out CurrentTick);
|
||||
reader.ReadValue(out Sequence);
|
||||
|
||||
reader.ReadValue(out message.Range);
|
||||
message.ReceiveMainBuffer = new NativeArray<byte>(message.Range, Allocator.Temp);
|
||||
reader.ReadBytesSafe((byte*)message.ReceiveMainBuffer.GetUnsafePtr(), message.Range);
|
||||
reader.ReadValueSafe(out message.Ack);
|
||||
reader.ReadValue(out Range);
|
||||
ReceiveMainBuffer = new NativeArray<byte>(Range, Allocator.Temp);
|
||||
reader.ReadBytesSafe((byte*)ReceiveMainBuffer.GetUnsafePtr(), Range);
|
||||
reader.ReadValueSafe(out Ack);
|
||||
|
||||
reader.ReadValueSafe(out ushort length);
|
||||
message.Entries = new NativeList<EntryData>(length, Allocator.Temp);
|
||||
message.Entries.Length = length;
|
||||
reader.ReadBytesSafe((byte*)message.Entries.GetUnsafePtr(), message.Entries.Length * sizeof(EntryData));
|
||||
Entries = new NativeList<EntryData>(length, Allocator.Temp) { Length = length };
|
||||
reader.ReadBytesSafe((byte*)Entries.GetUnsafePtr(), Entries.Length * sizeof(EntryData));
|
||||
|
||||
reader.ReadValueSafe(out length);
|
||||
message.Spawns = new NativeList<SpawnData>(length, Allocator.Temp);
|
||||
message.Spawns.Length = length;
|
||||
reader.ReadBytesSafe((byte*)message.Spawns.GetUnsafePtr(), message.Spawns.Length * sizeof(SpawnData));
|
||||
Spawns = new NativeList<SpawnData>(length, Allocator.Temp) { Length = length };
|
||||
reader.ReadBytesSafe((byte*)Spawns.GetUnsafePtr(), Spawns.Length * sizeof(SpawnData));
|
||||
|
||||
reader.ReadValueSafe(out length);
|
||||
message.Despawns = new NativeList<DespawnData>(length, Allocator.Temp);
|
||||
message.Despawns.Length = length;
|
||||
reader.ReadBytesSafe((byte*)message.Despawns.GetUnsafePtr(), message.Despawns.Length * sizeof(DespawnData));
|
||||
Despawns = new NativeList<DespawnData>(length, Allocator.Temp) { Length = length };
|
||||
reader.ReadBytesSafe((byte*)Despawns.GetUnsafePtr(), Despawns.Length * sizeof(DespawnData));
|
||||
|
||||
using (message.ReceiveMainBuffer)
|
||||
using (message.Entries)
|
||||
using (message.Spawns)
|
||||
using (message.Despawns)
|
||||
{
|
||||
message.Handle(context.SenderId, context.SystemOwner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ulong senderId, object systemOwner)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
if (systemOwner is NetworkManager)
|
||||
using (ReceiveMainBuffer)
|
||||
using (Entries)
|
||||
using (Spawns)
|
||||
using (Despawns)
|
||||
{
|
||||
var networkManager = (NetworkManager)systemOwner;
|
||||
|
||||
// todo: temporary hack around bug
|
||||
if (!networkManager.IsServer)
|
||||
var systemOwner = context.SystemOwner;
|
||||
var senderId = context.SenderId;
|
||||
if (systemOwner is NetworkManager networkManager)
|
||||
{
|
||||
senderId = networkManager.ServerClientId;
|
||||
}
|
||||
// todo: temporary hack around bug
|
||||
if (!networkManager.IsServer)
|
||||
{
|
||||
senderId = networkManager.ServerClientId;
|
||||
}
|
||||
|
||||
var snapshotSystem = networkManager.SnapshotSystem;
|
||||
snapshotSystem.HandleSnapshot(senderId, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ownerData = (Tuple<SnapshotSystem, ulong>)systemOwner;
|
||||
var snapshotSystem = ownerData.Item1;
|
||||
snapshotSystem.HandleSnapshot(ownerData.Item2, this);
|
||||
return;
|
||||
var snapshotSystem = networkManager.SnapshotSystem;
|
||||
snapshotSystem.HandleSnapshot(senderId, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ownerData = (Tuple<SnapshotSystem, ulong>)systemOwner;
|
||||
var snapshotSystem = ownerData.Item1;
|
||||
snapshotSystem.HandleSnapshot(ownerData.Item2, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,21 +9,22 @@ namespace Unity.Netcode
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
if (!networkManager.IsClient)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
reader.ReadValueSafe(out TimeSyncMessage message);
|
||||
message.Handle(context.SenderId, networkManager);
|
||||
reader.ReadValueSafe(out this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ulong senderId, NetworkManager networkManager)
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
var networkManager = (NetworkManager)context.SystemOwner;
|
||||
var time = new NetworkTime(networkManager.NetworkTickSystem.TickRate, Tick);
|
||||
networkManager.NetworkTimeSystem.Sync(time.Time, networkManager.NetworkConfig.NetworkTransport.GetCurrentRtt(senderId) / 1000d);
|
||||
networkManager.NetworkTimeSystem.Sync(time.Time, networkManager.NetworkConfig.NetworkTransport.GetCurrentRtt(context.SenderId) / 1000d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,23 @@ namespace Unity.Netcode
|
||||
{
|
||||
internal struct UnnamedMessage : INetworkMessage
|
||||
{
|
||||
public FastBufferWriter Data;
|
||||
public FastBufferWriter SendData;
|
||||
private FastBufferReader m_ReceivedData;
|
||||
|
||||
public unsafe void Serialize(FastBufferWriter writer)
|
||||
{
|
||||
writer.WriteBytesSafe(Data.GetUnsafePtr(), Data.Length);
|
||||
writer.WriteBytesSafe(SendData.GetUnsafePtr(), SendData.Length);
|
||||
}
|
||||
|
||||
public static void Receive(FastBufferReader reader, in NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
((NetworkManager)context.SystemOwner).CustomMessagingManager.InvokeUnnamedMessage(context.SenderId, reader, context.SerializedHeaderSize);
|
||||
m_ReceivedData = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
((NetworkManager)context.SystemOwner).CustomMessagingManager.InvokeUnnamedMessage(context.SenderId, m_ReceivedData, context.SerializedHeaderSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
internal delegate void MessageHandler(FastBufferReader reader, in NetworkContext context);
|
||||
internal delegate void MessageHandler(FastBufferReader reader, ref NetworkContext context, MessagingSystem system);
|
||||
|
||||
private NativeList<ReceiveQueueItem> m_IncomingMessageQueue = new NativeList<ReceiveQueueItem>(16, Allocator.Persistent);
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Unity.Netcode
|
||||
for (var queueIndex = 0; queueIndex < m_IncomingMessageQueue.Length; ++queueIndex)
|
||||
{
|
||||
// Avoid copies...
|
||||
ref var item = ref m_IncomingMessageQueue.GetUnsafeList()->ElementAt(queueIndex);
|
||||
ref var item = ref m_IncomingMessageQueue.ElementAt(queueIndex);
|
||||
item.Reader.Dispose();
|
||||
}
|
||||
|
||||
@@ -236,6 +236,7 @@ namespace Unity.Netcode
|
||||
Timestamp = timestamp,
|
||||
Header = header,
|
||||
SerializedHeaderSize = serializedHeaderSize,
|
||||
MessageSize = header.MessageSize,
|
||||
};
|
||||
|
||||
var type = m_ReverseTypeMap[header.MessageType];
|
||||
@@ -260,7 +261,7 @@ namespace Unity.Netcode
|
||||
// for some dynamic-length value.
|
||||
try
|
||||
{
|
||||
handler.Invoke(reader, context);
|
||||
handler.Invoke(reader, ref context, this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -278,7 +279,7 @@ namespace Unity.Netcode
|
||||
for (var index = 0; index < m_IncomingMessageQueue.Length; ++index)
|
||||
{
|
||||
// Avoid copies...
|
||||
ref var item = ref m_IncomingMessageQueue.GetUnsafeList()->ElementAt(index);
|
||||
ref var item = ref m_IncomingMessageQueue.ElementAt(index);
|
||||
HandleMessage(item.Header, item.Reader, item.SenderId, item.Timestamp, item.MessageHeaderSerializedSize);
|
||||
if (m_Disposed)
|
||||
{
|
||||
@@ -313,12 +314,31 @@ namespace Unity.Netcode
|
||||
var queue = m_SendQueues[clientId];
|
||||
for (var i = 0; i < queue.Length; ++i)
|
||||
{
|
||||
queue.GetUnsafeList()->ElementAt(i).Writer.Dispose();
|
||||
queue.ElementAt(i).Writer.Dispose();
|
||||
}
|
||||
|
||||
queue.Dispose();
|
||||
}
|
||||
|
||||
public static void ReceiveMessage<T>(FastBufferReader reader, ref NetworkContext context, MessagingSystem system) where T : INetworkMessage, new()
|
||||
{
|
||||
var message = new T();
|
||||
if (message.Deserialize(reader, ref context))
|
||||
{
|
||||
for (var hookIdx = 0; hookIdx < system.m_Hooks.Count; ++hookIdx)
|
||||
{
|
||||
system.m_Hooks[hookIdx].OnBeforeHandleMessage(ref message, ref context);
|
||||
}
|
||||
|
||||
message.Handle(ref context);
|
||||
|
||||
for (var hookIdx = 0; hookIdx < system.m_Hooks.Count; ++hookIdx)
|
||||
{
|
||||
system.m_Hooks[hookIdx].OnAfterHandleMessage(ref message, ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanSend(ulong clientId, Type messageType, NetworkDelivery delivery)
|
||||
{
|
||||
for (var hookIdx = 0; hookIdx < m_Hooks.Count; ++hookIdx)
|
||||
@@ -332,7 +352,7 @@ namespace Unity.Netcode
|
||||
return true;
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<TMessageType, TClientIdListType>(in TMessageType message, NetworkDelivery delivery, in TClientIdListType clientIds)
|
||||
internal int SendMessage<TMessageType, TClientIdListType>(ref TMessageType message, NetworkDelivery delivery, in TClientIdListType clientIds)
|
||||
where TMessageType : INetworkMessage
|
||||
where TClientIdListType : IReadOnlyList<ulong>
|
||||
{
|
||||
@@ -347,11 +367,17 @@ namespace Unity.Netcode
|
||||
|
||||
message.Serialize(tmpSerializer);
|
||||
|
||||
return SendPreSerializedMessage(tmpSerializer, maxSize, ref message, delivery, clientIds);
|
||||
}
|
||||
|
||||
internal unsafe int SendPreSerializedMessage<TMessageType>(in FastBufferWriter tmpSerializer, int maxSize, ref TMessageType message, NetworkDelivery delivery, in IReadOnlyList<ulong> clientIds)
|
||||
where TMessageType : INetworkMessage
|
||||
{
|
||||
using var headerSerializer = new FastBufferWriter(FastBufferWriter.GetWriteSize<MessageHeader>(), Allocator.Temp);
|
||||
|
||||
var header = new MessageHeader
|
||||
{
|
||||
MessageSize = (ushort)tmpSerializer.Length,
|
||||
MessageSize = (uint)tmpSerializer.Length,
|
||||
MessageType = m_MessageTypes[typeof(TMessageType)],
|
||||
};
|
||||
BytePacker.WriteValueBitPacked(headerSerializer, header.MessageType);
|
||||
@@ -368,7 +394,7 @@ namespace Unity.Netcode
|
||||
|
||||
for (var hookIdx = 0; hookIdx < m_Hooks.Count; ++hookIdx)
|
||||
{
|
||||
m_Hooks[hookIdx].OnBeforeSendMessage(clientId, typeof(TMessageType), delivery);
|
||||
m_Hooks[hookIdx].OnBeforeSendMessage(clientId, ref message, delivery);
|
||||
}
|
||||
|
||||
var sendQueueItem = m_SendQueues[clientId];
|
||||
@@ -376,22 +402,22 @@ namespace Unity.Netcode
|
||||
{
|
||||
sendQueueItem.Add(new SendQueueItem(delivery, NON_FRAGMENTED_MESSAGE_MAX_SIZE, Allocator.TempJob,
|
||||
maxSize));
|
||||
sendQueueItem.GetUnsafeList()->ElementAt(0).Writer.Seek(sizeof(BatchHeader));
|
||||
sendQueueItem.ElementAt(0).Writer.Seek(sizeof(BatchHeader));
|
||||
}
|
||||
else
|
||||
{
|
||||
ref var lastQueueItem = ref sendQueueItem.GetUnsafeList()->ElementAt(sendQueueItem.Length - 1);
|
||||
ref var lastQueueItem = ref sendQueueItem.ElementAt(sendQueueItem.Length - 1);
|
||||
if (lastQueueItem.NetworkDelivery != delivery ||
|
||||
lastQueueItem.Writer.MaxCapacity - lastQueueItem.Writer.Position
|
||||
< tmpSerializer.Length + headerSerializer.Length)
|
||||
{
|
||||
sendQueueItem.Add(new SendQueueItem(delivery, NON_FRAGMENTED_MESSAGE_MAX_SIZE, Allocator.TempJob,
|
||||
maxSize));
|
||||
sendQueueItem.GetUnsafeList()->ElementAt(sendQueueItem.Length - 1).Writer.Seek(sizeof(BatchHeader));
|
||||
sendQueueItem.ElementAt(sendQueueItem.Length - 1).Writer.Seek(sizeof(BatchHeader));
|
||||
}
|
||||
}
|
||||
|
||||
ref var writeQueueItem = ref sendQueueItem.GetUnsafeList()->ElementAt(sendQueueItem.Length - 1);
|
||||
ref var writeQueueItem = ref sendQueueItem.ElementAt(sendQueueItem.Length - 1);
|
||||
writeQueueItem.Writer.TryBeginWrite(tmpSerializer.Length + headerSerializer.Length);
|
||||
|
||||
writeQueueItem.Writer.WriteBytes(headerSerializer.GetUnsafePtr(), headerSerializer.Length);
|
||||
@@ -399,13 +425,20 @@ namespace Unity.Netcode
|
||||
writeQueueItem.BatchHeader.BatchSize++;
|
||||
for (var hookIdx = 0; hookIdx < m_Hooks.Count; ++hookIdx)
|
||||
{
|
||||
m_Hooks[hookIdx].OnAfterSendMessage(clientId, typeof(TMessageType), delivery, tmpSerializer.Length + headerSerializer.Length);
|
||||
m_Hooks[hookIdx].OnAfterSendMessage(clientId, ref message, delivery, tmpSerializer.Length + headerSerializer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
return tmpSerializer.Length + headerSerializer.Length;
|
||||
}
|
||||
|
||||
internal unsafe int SendPreSerializedMessage<TMessageType>(in FastBufferWriter tmpSerializer, int maxSize, ref TMessageType message, NetworkDelivery delivery, ulong clientId)
|
||||
where TMessageType : INetworkMessage
|
||||
{
|
||||
ulong* clientIds = stackalloc ulong[] { clientId };
|
||||
return SendPreSerializedMessage(tmpSerializer, maxSize, ref message, delivery, new PointerListWrapper<ulong>(clientIds, 1));
|
||||
}
|
||||
|
||||
private struct PointerListWrapper<T> : IReadOnlyList<T>
|
||||
where T : unmanaged
|
||||
{
|
||||
@@ -441,24 +474,24 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<T>(in T message, NetworkDelivery delivery,
|
||||
internal unsafe int SendMessage<T>(ref T message, NetworkDelivery delivery,
|
||||
ulong* clientIds, int numClientIds)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
return SendMessage(message, delivery, new PointerListWrapper<ulong>(clientIds, numClientIds));
|
||||
return SendMessage(ref message, delivery, new PointerListWrapper<ulong>(clientIds, numClientIds));
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<T>(in T message, NetworkDelivery delivery, ulong clientId)
|
||||
internal unsafe int SendMessage<T>(ref T message, NetworkDelivery delivery, ulong clientId)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
ulong* clientIds = stackalloc ulong[] { clientId };
|
||||
return SendMessage(message, delivery, new PointerListWrapper<ulong>(clientIds, 1));
|
||||
return SendMessage(ref message, delivery, new PointerListWrapper<ulong>(clientIds, 1));
|
||||
}
|
||||
|
||||
internal unsafe int SendMessage<T>(in T message, NetworkDelivery delivery, in NativeArray<ulong> clientIds)
|
||||
internal unsafe int SendMessage<T>(ref T message, NetworkDelivery delivery, in NativeArray<ulong> clientIds)
|
||||
where T : INetworkMessage
|
||||
{
|
||||
return SendMessage(message, delivery, new PointerListWrapper<ulong>((ulong*)clientIds.GetUnsafePtr(), clientIds.Length));
|
||||
return SendMessage(ref message, delivery, new PointerListWrapper<ulong>((ulong*)clientIds.GetUnsafePtr(), clientIds.Length));
|
||||
}
|
||||
|
||||
internal unsafe void ProcessSendQueues()
|
||||
@@ -469,7 +502,7 @@ namespace Unity.Netcode
|
||||
var sendQueueItem = kvp.Value;
|
||||
for (var i = 0; i < sendQueueItem.Length; ++i)
|
||||
{
|
||||
ref var queueItem = ref sendQueueItem.GetUnsafeList()->ElementAt(i);
|
||||
ref var queueItem = ref sendQueueItem.ElementAt(i);
|
||||
if (queueItem.BatchHeader.BatchSize == 0)
|
||||
{
|
||||
queueItem.Writer.Dispose();
|
||||
|
||||
@@ -30,5 +30,10 @@ namespace Unity.Netcode
|
||||
/// The actual serialized size of the header when packed into the buffer
|
||||
/// </summary>
|
||||
public int SerializedHeaderSize;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the message in the buffer, header excluded
|
||||
/// </summary>
|
||||
public uint MessageSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,12 @@ namespace Unity.Netcode
|
||||
|
||||
void TrackSceneEventReceived(ulong senderClientId, uint sceneEventType, string sceneName, long bytesCount);
|
||||
|
||||
void TrackPacketSent(uint packetCount);
|
||||
|
||||
void TrackPacketReceived(uint packetCount);
|
||||
|
||||
void TrackRttToServer(int rtt);
|
||||
|
||||
void DispatchFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,13 @@ namespace Unity.Netcode
|
||||
m_NetworkManager = networkManager;
|
||||
}
|
||||
|
||||
|
||||
public void OnBeforeSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery)
|
||||
public void OnBeforeSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery, int messageSizeBytes)
|
||||
public void OnAfterSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage
|
||||
{
|
||||
m_NetworkManager.NetworkMetrics.TrackNetworkMessageSent(clientId, messageType.Name, messageSizeBytes);
|
||||
m_NetworkManager.NetworkMetrics.TrackNetworkMessageSent(clientId, typeof(T).Name, messageSizeBytes);
|
||||
}
|
||||
|
||||
public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes)
|
||||
@@ -57,5 +56,15 @@ namespace Unity.Netcode
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnBeforeHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage
|
||||
{
|
||||
// TODO: Per-message metrics recording moved here
|
||||
}
|
||||
|
||||
public void OnAfterHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage
|
||||
{
|
||||
// TODO: Per-message metrics recording moved here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using Unity.Multiplayer.Tools;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using Unity.Multiplayer.Tools.NetStats;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode
|
||||
@@ -14,6 +15,8 @@ namespace Unity.Netcode
|
||||
|
||||
static Dictionary<uint, string> s_SceneEventTypeNames;
|
||||
|
||||
static ProfilerMarker s_FrameDispatch = new ProfilerMarker($"{nameof(NetworkMetrics)}.DispatchFrame");
|
||||
|
||||
static NetworkMetrics()
|
||||
{
|
||||
s_SceneEventTypeNames = new Dictionary<uint, string>();
|
||||
@@ -63,6 +66,21 @@ namespace Unity.Netcode
|
||||
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_4
|
||||
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,
|
||||
};
|
||||
#endif
|
||||
|
||||
private ulong m_NumberOfMetricsThisFrame;
|
||||
|
||||
public NetworkMetrics()
|
||||
@@ -79,6 +97,10 @@ namespace Unity.Netcode
|
||||
.WithMetricEvents(m_RpcSentEvent, m_RpcReceivedEvent)
|
||||
.WithMetricEvents(m_ServerLogSentEvent, m_ServerLogReceivedEvent)
|
||||
.WithMetricEvents(m_SceneEventSentEvent, m_SceneEventReceivedEvent)
|
||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_4
|
||||
.WithCounters(m_PacketSentCounter, m_PacketReceivedCounter)
|
||||
.WithGauges(m_RttToServerGauge)
|
||||
#endif
|
||||
.Build();
|
||||
|
||||
Dispatcher.RegisterObserver(NetcodeObserver.Observer);
|
||||
@@ -404,9 +426,49 @@ namespace Unity.Netcode
|
||||
IncrementMetricCount();
|
||||
}
|
||||
|
||||
public void TrackPacketSent(uint packetCount)
|
||||
{
|
||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_4
|
||||
if (!CanSendMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_PacketSentCounter.Increment(packetCount);
|
||||
IncrementMetricCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void TrackPacketReceived(uint packetCount)
|
||||
{
|
||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_4
|
||||
if (!CanSendMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_PacketReceivedCounter.Increment(packetCount);
|
||||
IncrementMetricCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void TrackRttToServer(int rtt)
|
||||
{
|
||||
#if MULTIPLAYER_TOOLS_1_0_0_PRE_4
|
||||
if (!CanSendMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_RttToServerGauge.Set(rtt);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void DispatchFrame()
|
||||
{
|
||||
s_FrameDispatch.Begin();
|
||||
Dispatcher.Dispatch();
|
||||
s_FrameDispatch.End();
|
||||
m_NumberOfMetricsThisFrame = 0;
|
||||
}
|
||||
|
||||
@@ -421,7 +483,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
}
|
||||
|
||||
internal class NetcodeObserver
|
||||
internal class NetcodeObserver
|
||||
{
|
||||
public static IMetricObserver Observer { get; } = MetricObserverFactory.Construct();
|
||||
}
|
||||
|
||||
@@ -137,6 +137,18 @@ namespace Unity.Netcode
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackPacketSent(uint packetCount)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackPacketReceived(uint packetCount)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackRttToServer(int rtt)
|
||||
{
|
||||
}
|
||||
|
||||
public void DispatchFrame()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -90,18 +90,18 @@ namespace Unity.Netcode
|
||||
{
|
||||
case NetworkListEvent<T>.EventType.Add:
|
||||
{
|
||||
writer.WriteValueSafe(m_DirtyEvents[i].Value);
|
||||
NetworkVariable<T>.Write(writer, m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Insert:
|
||||
{
|
||||
writer.WriteValueSafe(m_DirtyEvents[i].Index);
|
||||
writer.WriteValueSafe(m_DirtyEvents[i].Value);
|
||||
NetworkVariable<T>.Write(writer, m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Remove:
|
||||
{
|
||||
writer.WriteValueSafe(m_DirtyEvents[i].Value);
|
||||
NetworkVariable<T>.Write(writer, m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.RemoveAt:
|
||||
@@ -112,7 +112,7 @@ namespace Unity.Netcode
|
||||
case NetworkListEvent<T>.EventType.Value:
|
||||
{
|
||||
writer.WriteValueSafe(m_DirtyEvents[i].Index);
|
||||
writer.WriteValueSafe(m_DirtyEvents[i].Value);
|
||||
NetworkVariable<T>.Write(writer, m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Clear:
|
||||
@@ -130,7 +130,7 @@ namespace Unity.Netcode
|
||||
writer.WriteValueSafe((ushort)m_List.Length);
|
||||
for (int i = 0; i < m_List.Length; i++)
|
||||
{
|
||||
writer.WriteValueSafe(m_List[i]);
|
||||
NetworkVariable<T>.Write(writer, m_List[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Unity.Netcode
|
||||
reader.ReadValueSafe(out ushort count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
reader.ReadValueSafe(out T value);
|
||||
NetworkVariable<T>.Read(reader, out T value);
|
||||
m_List.Add(value);
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
case NetworkListEvent<T>.EventType.Add:
|
||||
{
|
||||
reader.ReadValueSafe(out T value);
|
||||
NetworkVariable<T>.Read(reader, out T value);
|
||||
m_List.Add(value);
|
||||
|
||||
if (OnListChanged != null)
|
||||
@@ -184,7 +184,7 @@ namespace Unity.Netcode
|
||||
case NetworkListEvent<T>.EventType.Insert:
|
||||
{
|
||||
reader.ReadValueSafe(out int index);
|
||||
reader.ReadValueSafe(out T value);
|
||||
NetworkVariable<T>.Read(reader, out T value);
|
||||
m_List.InsertRangeWithBeginEnd(index, index + 1);
|
||||
m_List[index] = value;
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace Unity.Netcode
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Remove:
|
||||
{
|
||||
reader.ReadValueSafe(out T value);
|
||||
NetworkVariable<T>.Read(reader, out T value);
|
||||
int index = m_List.IndexOf(value);
|
||||
if (index == -1)
|
||||
{
|
||||
@@ -271,7 +271,7 @@ namespace Unity.Netcode
|
||||
case NetworkListEvent<T>.EventType.Value:
|
||||
{
|
||||
reader.ReadValueSafe(out int index);
|
||||
reader.ReadValueSafe(out T value);
|
||||
NetworkVariable<T>.Read(reader, out T value);
|
||||
if (index >= m_List.Length)
|
||||
{
|
||||
throw new Exception("Shouldn't be here, index is higher than list length");
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Unity.Netcode
|
||||
public class NetworkVariable<T> : NetworkVariableBase where T : unmanaged
|
||||
{
|
||||
// Functions that know how to serialize INetworkSerializable
|
||||
internal static void WriteNetworkSerializable<TForMethod>(FastBufferWriter writer, ref TForMethod value)
|
||||
internal static void WriteNetworkSerializable<TForMethod>(FastBufferWriter writer, in TForMethod value)
|
||||
where TForMethod : INetworkSerializable, new()
|
||||
{
|
||||
writer.WriteNetworkSerializable(value);
|
||||
@@ -22,7 +22,7 @@ namespace Unity.Netcode
|
||||
}
|
||||
|
||||
// Functions that serialize other types
|
||||
private static void WriteValue<TForMethod>(FastBufferWriter writer, ref TForMethod value) where TForMethod : unmanaged
|
||||
private static void WriteValue<TForMethod>(FastBufferWriter writer, in TForMethod value) where TForMethod : unmanaged
|
||||
{
|
||||
writer.WriteValueSafe(value);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace Unity.Netcode
|
||||
reader.ReadValueSafe(out value);
|
||||
}
|
||||
|
||||
internal delegate void WriteDelegate<TForMethod>(FastBufferWriter writer, ref TForMethod value);
|
||||
internal delegate void WriteDelegate<TForMethod>(FastBufferWriter writer, in TForMethod value);
|
||||
|
||||
internal delegate void ReadDelegate<TForMethod>(FastBufferReader reader, out TForMethod value);
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Unity.Netcode
|
||||
/// <inheritdoc />
|
||||
public override void WriteField(FastBufferWriter writer)
|
||||
{
|
||||
Write(writer, ref m_InternalValue);
|
||||
Write(writer, m_InternalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Unity.Netcode
|
||||
/// <summary>
|
||||
/// The delivery type (QoS) to send data with
|
||||
/// </summary>
|
||||
internal const NetworkDelivery Delivery = NetworkDelivery.ReliableSequenced;
|
||||
internal const NetworkDelivery Delivery = NetworkDelivery.ReliableFragmentedSequenced;
|
||||
|
||||
private protected NetworkBehaviour m_NetworkBehaviour;
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@ namespace Unity.Netcode
|
||||
return marker;
|
||||
}
|
||||
|
||||
public void OnBeforeSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery)
|
||||
public void OnBeforeSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage
|
||||
{
|
||||
GetSenderProfilerMarker(messageType).Begin();
|
||||
GetSenderProfilerMarker(typeof(T)).Begin();
|
||||
}
|
||||
|
||||
public void OnAfterSendMessage(ulong clientId, Type messageType, NetworkDelivery delivery, int messageSizeBytes)
|
||||
public void OnAfterSendMessage<T>(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage
|
||||
{
|
||||
GetSenderProfilerMarker(messageType).End();
|
||||
GetSenderProfilerMarker(typeof(T)).End();
|
||||
}
|
||||
|
||||
public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes)
|
||||
@@ -86,5 +86,15 @@ namespace Unity.Netcode
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnBeforeHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage
|
||||
{
|
||||
// nop
|
||||
}
|
||||
|
||||
public void OnAfterHandleMessage<T>(ref T message, ref NetworkContext context) where T : INetworkMessage
|
||||
{
|
||||
// nop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
Runtime/SceneManagement/ISceneManagerHandler.cs
Normal file
28
Runtime/SceneManagement/ISceneManagerHandler.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Unity.Netcode
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to override the LoadSceneAsync and UnloadSceneAsync methods called
|
||||
/// within the NetworkSceneManager.
|
||||
/// </summary>
|
||||
internal interface ISceneManagerHandler
|
||||
{
|
||||
// Generic action to call when a scene is finished loading/unloading
|
||||
struct SceneEventAction
|
||||
{
|
||||
internal uint SceneEventId;
|
||||
internal Action<uint> EventAction;
|
||||
internal void Invoke()
|
||||
{
|
||||
EventAction.Invoke(SceneEventId);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncOperation LoadSceneAsync(string sceneName, LoadSceneMode loadSceneMode, SceneEventAction sceneEventAction);
|
||||
|
||||
AsyncOperation UnloadSceneAsync(Scene scene, SceneEventAction sceneEventAction);
|
||||
}
|
||||
}
|
||||
11
Runtime/SceneManagement/ISceneManagerHandler.cs.meta
Normal file
11
Runtime/SceneManagement/ISceneManagerHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de907a9fb8151e240800dbcc97f8e745
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -139,13 +139,7 @@ namespace Unity.Netcode
|
||||
/// Used to detect if a scene event is underway
|
||||
/// Only 1 scene event can occur on the server at a time for now.
|
||||
/// </summary>
|
||||
private static bool s_IsSceneEventActive = false;
|
||||
|
||||
// TODO: Remove `m_IsRunningUnitTest` entirely after we switch to multi-process testing
|
||||
// In MultiInstance tests, we cannot allow clients to load additional scenes as they're sharing the same scene space / Unity instance.
|
||||
#if UNITY_INCLUDE_TESTS
|
||||
private readonly bool m_IsRunningUnitTest = SceneManager.GetActiveScene().name.StartsWith("InitTestScene");
|
||||
#endif
|
||||
private bool m_IsSceneEventActive = false;
|
||||
|
||||
/// <summary>
|
||||
/// The delegate callback definition for scene event notifications.<br/>
|
||||
@@ -324,6 +318,31 @@ namespace Unity.Netcode
|
||||
/// </summary>
|
||||
public VerifySceneBeforeLoadingDelegateHandler VerifySceneBeforeLoading;
|
||||
|
||||
/// <summary>
|
||||
/// Proof of concept: Interface version that allows for the decoupling from
|
||||
/// the SceneManager's Load and Unload methods for testing purposes (potentially other future usage)
|
||||
/// </summary>
|
||||
private class DefaultSceneManagerHandler : ISceneManagerHandler
|
||||
{
|
||||
public AsyncOperation LoadSceneAsync(string sceneName, LoadSceneMode loadSceneMode, ISceneManagerHandler.SceneEventAction sceneEventAction)
|
||||
{
|
||||
var operation = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
|
||||
operation.completed += new Action<AsyncOperation>(asyncOp2 => { sceneEventAction.Invoke(); });
|
||||
return operation;
|
||||
}
|
||||
|
||||
public AsyncOperation UnloadSceneAsync(Scene scene, ISceneManagerHandler.SceneEventAction sceneEventAction)
|
||||
{
|
||||
var operation = SceneManager.UnloadSceneAsync(scene);
|
||||
operation.completed += new Action<AsyncOperation>(asyncOp2 => { sceneEventAction.Invoke(); });
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
internal ISceneManagerHandler SceneManagerHandler = new DefaultSceneManagerHandler();
|
||||
/// End of Proof of Concept
|
||||
|
||||
|
||||
internal readonly Dictionary<Guid, SceneEventProgress> SceneEventProgressTracking = new Dictionary<Guid, SceneEventProgress>();
|
||||
|
||||
/// <summary>
|
||||
@@ -723,10 +742,9 @@ namespace Unity.Netcode
|
||||
{
|
||||
EventData = SceneEventDataStore[sceneEventId]
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, k_DeliveryType, targetClientIds);
|
||||
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, targetClientIds);
|
||||
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(
|
||||
targetClientIds, (uint)SceneEventDataStore[sceneEventId].SceneEventType, SceneNameFromHash(SceneEventDataStore[sceneEventId].SceneHash), size);
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(targetClientIds, (uint)SceneEventDataStore[sceneEventId].SceneEventType, SceneNameFromHash(SceneEventDataStore[sceneEventId].SceneHash), size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -789,7 +807,7 @@ namespace Unity.Netcode
|
||||
private SceneEventProgress ValidateSceneEvent(string sceneName, bool isUnloading = false)
|
||||
{
|
||||
// Return scene event already in progress if one is already in progress
|
||||
if (s_IsSceneEventActive)
|
||||
if (m_IsSceneEventActive)
|
||||
{
|
||||
return new SceneEventProgress(null, SceneEventProgressStatus.SceneEventInProgress);
|
||||
}
|
||||
@@ -818,7 +836,7 @@ namespace Unity.Netcode
|
||||
IsSpawnedObjectsPendingInDontDestroyOnLoad = true;
|
||||
}
|
||||
|
||||
s_IsSceneEventActive = true;
|
||||
m_IsSceneEventActive = true;
|
||||
|
||||
// Set our callback delegate handler for completion
|
||||
sceneEventProgress.OnComplete = OnSceneEventProgressCompleted;
|
||||
@@ -845,12 +863,12 @@ namespace Unity.Netcode
|
||||
{
|
||||
EventData = sceneEventData
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, k_DeliveryType, m_NetworkManager.ConnectedClientsIds);
|
||||
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, m_NetworkManager.ConnectedClientsIds);
|
||||
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(
|
||||
m_NetworkManager.ConnectedClientsIds,
|
||||
(uint)sceneEventProgress.SceneEventType,
|
||||
SceneNameFromHash(sceneEventProgress.SceneHash),
|
||||
SceneNameFromHash(sceneEventProgress.SceneHash),
|
||||
size);
|
||||
|
||||
// Send a local notification to the server that all clients are done loading or unloading
|
||||
@@ -917,8 +935,9 @@ namespace Unity.Netcode
|
||||
|
||||
ScenesLoaded.Remove(scene.handle);
|
||||
|
||||
AsyncOperation sceneUnload = SceneManager.UnloadSceneAsync(scene);
|
||||
sceneUnload.completed += (AsyncOperation asyncOp2) => { OnSceneUnloaded(sceneEventData.SceneEventId); };
|
||||
var sceneUnload = SceneManagerHandler.UnloadSceneAsync(scene,
|
||||
new ISceneManagerHandler.SceneEventAction() { SceneEventId = sceneEventData.SceneEventId, EventAction = OnSceneUnloaded });
|
||||
|
||||
sceneEventProgress.SetSceneLoadOperation(sceneUnload);
|
||||
|
||||
// Notify local server that a scene is going to be unloaded
|
||||
@@ -948,8 +967,10 @@ namespace Unity.Netcode
|
||||
|
||||
if (!ServerSceneHandleToClientSceneHandle.ContainsKey(sceneEventData.SceneHandle))
|
||||
{
|
||||
throw new Exception($"Client failed to unload scene {sceneName} " +
|
||||
$"because we are missing the client scene handle due to the server scene handle {sceneEventData.SceneHandle} not being found!");
|
||||
Debug.Log($"Client failed to unload scene {sceneName} " +
|
||||
$"because we are missing the client scene handle due to the server scene handle {sceneEventData.SceneHandle} not being found.");
|
||||
EndSceneEvent(sceneEventId);
|
||||
return;
|
||||
}
|
||||
|
||||
var sceneHandle = ServerSceneHandleToClientSceneHandle[sceneEventData.SceneHandle];
|
||||
@@ -960,22 +981,11 @@ namespace Unity.Netcode
|
||||
throw new Exception($"Client failed to unload scene {sceneName} " +
|
||||
$"because the client scene handle {sceneHandle} was not found in ScenesLoaded!");
|
||||
}
|
||||
s_IsSceneEventActive = true;
|
||||
var sceneUnload = (AsyncOperation)null;
|
||||
#if UNITY_INCLUDE_TESTS
|
||||
if (m_IsRunningUnitTest)
|
||||
{
|
||||
sceneUnload = new AsyncOperation();
|
||||
}
|
||||
else
|
||||
{
|
||||
sceneUnload = SceneManager.UnloadSceneAsync(ScenesLoaded[sceneHandle]);
|
||||
sceneUnload.completed += asyncOp2 => OnSceneUnloaded(sceneEventId);
|
||||
}
|
||||
#else
|
||||
sceneUnload = SceneManager.UnloadSceneAsync(ScenesLoaded[sceneHandle]);
|
||||
sceneUnload.completed += asyncOp2 => OnSceneUnloaded(sceneEventId);
|
||||
#endif
|
||||
m_IsSceneEventActive = true;
|
||||
|
||||
var sceneUnload = SceneManagerHandler.UnloadSceneAsync(ScenesLoaded[sceneHandle],
|
||||
new ISceneManagerHandler.SceneEventAction() { SceneEventId = sceneEventData.SceneEventId, EventAction = OnSceneUnloaded });
|
||||
|
||||
ScenesLoaded.Remove(sceneHandle);
|
||||
|
||||
// Remove our server to scene handle lookup
|
||||
@@ -992,13 +1002,6 @@ namespace Unity.Netcode
|
||||
});
|
||||
|
||||
OnUnload?.Invoke(m_NetworkManager.LocalClientId, sceneName, sceneUnload);
|
||||
|
||||
#if UNITY_INCLUDE_TESTS
|
||||
if (m_IsRunningUnitTest)
|
||||
{
|
||||
OnSceneUnloaded(sceneEventId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1045,7 +1048,12 @@ namespace Unity.Netcode
|
||||
|
||||
EndSceneEvent(sceneEventId);
|
||||
// This scene event is now considered "complete"
|
||||
s_IsSceneEventActive = false;
|
||||
m_IsSceneEventActive = false;
|
||||
}
|
||||
|
||||
private void EmptySceneUnloadedOperation(uint sceneEventId)
|
||||
{
|
||||
// Do nothing (this is a stub call since it is only used to flush all currently loaded scenes)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1053,17 +1061,21 @@ namespace Unity.Netcode
|
||||
/// Since we assume a single mode loaded scene will be considered the "currently active scene",
|
||||
/// we only unload any additively loaded scenes.
|
||||
/// </summary>
|
||||
internal void UnloadAdditivelyLoadedScenes()
|
||||
internal void UnloadAdditivelyLoadedScenes(uint sceneEventId)
|
||||
{
|
||||
// Unload all additive scenes while making sure we don't try to unload the base scene ( loaded in single mode ).
|
||||
var currentActiveScene = SceneManager.GetActiveScene();
|
||||
foreach (var keyHandleEntry in ScenesLoaded)
|
||||
{
|
||||
if (currentActiveScene.name != keyHandleEntry.Value.name)
|
||||
// Validate the scene as well as ignore the DDOL (which will have a negative buildIndex)
|
||||
if (currentActiveScene.name != keyHandleEntry.Value.name && keyHandleEntry.Value.buildIndex >= 0)
|
||||
{
|
||||
var sceneUnload = SceneManagerHandler.UnloadSceneAsync(keyHandleEntry.Value,
|
||||
new ISceneManagerHandler.SceneEventAction() { SceneEventId = sceneEventId, EventAction = EmptySceneUnloadedOperation });
|
||||
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
{
|
||||
AsyncOperation = SceneManager.UnloadSceneAsync(keyHandleEntry.Value),
|
||||
AsyncOperation = sceneUnload,
|
||||
SceneEventType = SceneEventType.Unload,
|
||||
SceneName = keyHandleEntry.Value.name,
|
||||
LoadSceneMode = LoadSceneMode.Additive, // The only scenes unloaded are scenes that were additively loaded
|
||||
@@ -1103,8 +1115,8 @@ namespace Unity.Netcode
|
||||
sceneEventData.LoadSceneMode = loadSceneMode;
|
||||
|
||||
// This both checks to make sure the scene is valid and if not resets the active scene event
|
||||
s_IsSceneEventActive = ValidateSceneBeforeLoading(sceneEventData.SceneHash, loadSceneMode);
|
||||
if (!s_IsSceneEventActive)
|
||||
m_IsSceneEventActive = ValidateSceneBeforeLoading(sceneEventData.SceneHash, loadSceneMode);
|
||||
if (!m_IsSceneEventActive)
|
||||
{
|
||||
EndSceneEvent(sceneEventData.SceneEventId);
|
||||
return SceneEventProgressStatus.SceneFailedVerification;
|
||||
@@ -1119,12 +1131,13 @@ namespace Unity.Netcode
|
||||
MoveObjectsToDontDestroyOnLoad();
|
||||
|
||||
// Now Unload all currently additively loaded scenes
|
||||
UnloadAdditivelyLoadedScenes();
|
||||
UnloadAdditivelyLoadedScenes(sceneEventData.SceneEventId);
|
||||
}
|
||||
|
||||
// Now start loading the scene
|
||||
AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
|
||||
sceneLoad.completed += (AsyncOperation asyncOp2) => { OnSceneLoaded(sceneEventData.SceneEventId, sceneName); };
|
||||
var sceneLoad = SceneManagerHandler.LoadSceneAsync(sceneName, loadSceneMode,
|
||||
new ISceneManagerHandler.SceneEventAction() { SceneEventId = sceneEventData.SceneEventId, EventAction = OnSceneLoaded });
|
||||
|
||||
sceneEventProgress.SetSceneLoadOperation(sceneLoad);
|
||||
|
||||
// Notify the local server that a scene loading event has begun
|
||||
@@ -1160,44 +1173,13 @@ namespace Unity.Netcode
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_INCLUDE_TESTS
|
||||
if (m_IsRunningUnitTest)
|
||||
{
|
||||
// Send the loading message
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
{
|
||||
AsyncOperation = new AsyncOperation(),
|
||||
SceneEventType = sceneEventData.SceneEventType,
|
||||
LoadSceneMode = sceneEventData.LoadSceneMode,
|
||||
SceneName = sceneName,
|
||||
ClientId = m_NetworkManager.LocalClientId
|
||||
});
|
||||
|
||||
// Only for testing
|
||||
OnLoad?.Invoke(m_NetworkManager.ServerClientId, sceneName, sceneEventData.LoadSceneMode, new AsyncOperation());
|
||||
|
||||
// Unit tests must mirror the server's scenes loaded dictionary, otherwise this portion will fail
|
||||
if (ScenesLoaded.ContainsKey(sceneEventData.SceneHandle))
|
||||
{
|
||||
OnClientLoadedScene(sceneEventId, ScenesLoaded[sceneEventData.SceneHandle]);
|
||||
}
|
||||
else
|
||||
{
|
||||
EndSceneEvent(sceneEventId);
|
||||
throw new Exception($"Could not find the scene handle {sceneEventData.SceneHandle} for scene {sceneName} " +
|
||||
$"during unit test. Did you forget to register this in the unit test?");
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sceneEventData.LoadSceneMode == LoadSceneMode.Single)
|
||||
{
|
||||
// Move ALL NetworkObjects to the temp scene
|
||||
MoveObjectsToDontDestroyOnLoad();
|
||||
|
||||
// Now Unload all currently additively loaded scenes
|
||||
UnloadAdditivelyLoadedScenes();
|
||||
UnloadAdditivelyLoadedScenes(sceneEventData.SceneEventId);
|
||||
}
|
||||
|
||||
// The Condition: While a scene is asynchronously loaded in single loading scene mode, if any new NetworkObjects are spawned
|
||||
@@ -1205,13 +1187,14 @@ namespace Unity.Netcode
|
||||
// When it is set: Just before starting the asynchronous loading call
|
||||
// When it is unset: After the scene has loaded, the PopulateScenePlacedObjects is called, and all NetworkObjects in the do
|
||||
// not destroy temporary scene are moved into the active scene
|
||||
// TODO: When Snapshot scene spawning is enabled this needs to be removed.
|
||||
if (sceneEventData.LoadSceneMode == LoadSceneMode.Single)
|
||||
{
|
||||
IsSpawnedObjectsPendingInDontDestroyOnLoad = true;
|
||||
}
|
||||
|
||||
var sceneLoad = SceneManager.LoadSceneAsync(sceneName, sceneEventData.LoadSceneMode);
|
||||
sceneLoad.completed += asyncOp2 => OnSceneLoaded(sceneEventId, sceneName);
|
||||
var sceneLoad = SceneManagerHandler.LoadSceneAsync(sceneName, sceneEventData.LoadSceneMode,
|
||||
new ISceneManagerHandler.SceneEventAction() { SceneEventId = sceneEventId, EventAction = OnSceneLoaded });
|
||||
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
{
|
||||
@@ -1230,10 +1213,10 @@ namespace Unity.Netcode
|
||||
/// Client and Server:
|
||||
/// Generic on scene loaded callback method to be called upon a scene loading
|
||||
/// </summary>
|
||||
private void OnSceneLoaded(uint sceneEventId, string sceneName)
|
||||
private void OnSceneLoaded(uint sceneEventId)
|
||||
{
|
||||
var sceneEventData = SceneEventDataStore[sceneEventId];
|
||||
var nextScene = GetAndAddNewlyLoadedSceneByName(sceneName);
|
||||
var nextScene = GetAndAddNewlyLoadedSceneByName(SceneNameFromHash(sceneEventData.SceneHash));
|
||||
if (!nextScene.isLoaded || !nextScene.IsValid())
|
||||
{
|
||||
throw new Exception($"Failed to find valid scene internal Unity.Netcode for {nameof(GameObject)}s error!");
|
||||
@@ -1314,12 +1297,12 @@ namespace Unity.Netcode
|
||||
{
|
||||
EventData = sceneEventData
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, k_DeliveryType, clientId);
|
||||
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, clientId);
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEventData.SceneEventType, scene.name, size);
|
||||
}
|
||||
}
|
||||
|
||||
s_IsSceneEventActive = false;
|
||||
m_IsSceneEventActive = false;
|
||||
//First, notify local server that the scene was loaded
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
{
|
||||
@@ -1351,7 +1334,7 @@ namespace Unity.Netcode
|
||||
|
||||
sceneEventData.SceneEventType = SceneEventType.LoadComplete;
|
||||
SendSceneEventData(sceneEventId, new ulong[] { m_NetworkManager.ServerClientId });
|
||||
s_IsSceneEventActive = false;
|
||||
m_IsSceneEventActive = false;
|
||||
|
||||
// Notify local client that the scene was loaded
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
@@ -1421,9 +1404,8 @@ namespace Unity.Netcode
|
||||
{
|
||||
EventData = sceneEventData
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, k_DeliveryType, clientId);
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(
|
||||
clientId, (uint)sceneEventData.SceneEventType, "", size);
|
||||
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, clientId);
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEventData.SceneEventType, "", size);
|
||||
|
||||
// Notify the local server that the client has been sent the synchronize event
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
@@ -1474,6 +1456,10 @@ namespace Unity.Netcode
|
||||
ScenePlacedObjects.Clear();
|
||||
}
|
||||
|
||||
// Store the sceneHandle and hash
|
||||
sceneEventData.ClientSceneHandle = sceneHandle;
|
||||
sceneEventData.ClientSceneHash = sceneHash;
|
||||
|
||||
var shouldPassThrough = false;
|
||||
var sceneLoad = (AsyncOperation)null;
|
||||
|
||||
@@ -1485,38 +1471,28 @@ namespace Unity.Netcode
|
||||
shouldPassThrough = true;
|
||||
}
|
||||
|
||||
#if UNITY_INCLUDE_TESTS
|
||||
if (m_IsRunningUnitTest)
|
||||
{
|
||||
// In unit tests, we don't allow clients to load additional scenes since
|
||||
// MultiInstance unit tests share the same scene space.
|
||||
shouldPassThrough = true;
|
||||
sceneLoad = new AsyncOperation();
|
||||
}
|
||||
#endif
|
||||
if (!shouldPassThrough)
|
||||
{
|
||||
// If not, then load the scene
|
||||
sceneLoad = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
|
||||
sceneLoad.completed += asyncOp2 => ClientLoadedSynchronization(sceneEventId, sceneHash, sceneHandle);
|
||||
sceneLoad = SceneManagerHandler.LoadSceneAsync(sceneName, loadSceneMode,
|
||||
new ISceneManagerHandler.SceneEventAction() { SceneEventId = sceneEventId, EventAction = ClientLoadedSynchronization });
|
||||
|
||||
// Notify local client that a scene load has begun
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
{
|
||||
AsyncOperation = sceneLoad,
|
||||
SceneEventType = SceneEventType.Load,
|
||||
LoadSceneMode = loadSceneMode,
|
||||
SceneName = sceneName,
|
||||
ClientId = m_NetworkManager.LocalClientId,
|
||||
});
|
||||
|
||||
OnLoad?.Invoke(m_NetworkManager.LocalClientId, sceneName, loadSceneMode, sceneLoad);
|
||||
}
|
||||
|
||||
// Notify local client that a scene load has begun
|
||||
OnSceneEvent?.Invoke(new SceneEvent()
|
||||
{
|
||||
AsyncOperation = sceneLoad,
|
||||
SceneEventType = SceneEventType.Load,
|
||||
LoadSceneMode = loadSceneMode,
|
||||
SceneName = sceneName,
|
||||
ClientId = m_NetworkManager.LocalClientId,
|
||||
});
|
||||
|
||||
OnLoad?.Invoke(m_NetworkManager.LocalClientId, sceneName, loadSceneMode, sceneLoad);
|
||||
|
||||
if (shouldPassThrough)
|
||||
else
|
||||
{
|
||||
// If so, then pass through
|
||||
ClientLoadedSynchronization(sceneEventId, sceneHash, sceneHandle);
|
||||
ClientLoadedSynchronization(sceneEventId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1525,10 +1501,10 @@ namespace Unity.Netcode
|
||||
/// This handles all of the in-scene and dynamically spawned NetworkObject synchronization
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Netcode scene index that was loaded</param>
|
||||
private void ClientLoadedSynchronization(uint sceneEventId, uint sceneHash, int sceneHandle)
|
||||
private void ClientLoadedSynchronization(uint sceneEventId)
|
||||
{
|
||||
var sceneEventData = SceneEventDataStore[sceneEventId];
|
||||
var sceneName = SceneNameFromHash(sceneHash);
|
||||
var sceneName = SceneNameFromHash(sceneEventData.ClientSceneHash);
|
||||
var nextScene = GetAndAddNewlyLoadedSceneByName(sceneName);
|
||||
|
||||
if (!nextScene.isLoaded || !nextScene.IsValid())
|
||||
@@ -1536,7 +1512,7 @@ namespace Unity.Netcode
|
||||
throw new Exception($"Failed to find valid scene internal Unity.Netcode for {nameof(GameObject)}s error!");
|
||||
}
|
||||
|
||||
var loadSceneMode = (sceneHash == sceneEventData.SceneHash ? sceneEventData.LoadSceneMode : LoadSceneMode.Additive);
|
||||
var loadSceneMode = (sceneEventData.ClientSceneHash == sceneEventData.SceneHash ? sceneEventData.LoadSceneMode : LoadSceneMode.Additive);
|
||||
|
||||
// For now, during a synchronization event, we will make the first scene the "base/master" scene that denotes a "complete scene switch"
|
||||
if (loadSceneMode == LoadSceneMode.Single)
|
||||
@@ -1544,9 +1520,9 @@ namespace Unity.Netcode
|
||||
SceneManager.SetActiveScene(nextScene);
|
||||
}
|
||||
|
||||
if (!ServerSceneHandleToClientSceneHandle.ContainsKey(sceneHandle))
|
||||
if (!ServerSceneHandleToClientSceneHandle.ContainsKey(sceneEventData.ClientSceneHandle))
|
||||
{
|
||||
ServerSceneHandleToClientSceneHandle.Add(sceneHandle, nextScene.handle);
|
||||
ServerSceneHandleToClientSceneHandle.Add(sceneEventData.ClientSceneHandle, nextScene.handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1561,14 +1537,14 @@ namespace Unity.Netcode
|
||||
var responseSceneEventData = BeginSceneEvent();
|
||||
responseSceneEventData.LoadSceneMode = loadSceneMode;
|
||||
responseSceneEventData.SceneEventType = SceneEventType.LoadComplete;
|
||||
responseSceneEventData.SceneHash = sceneHash;
|
||||
responseSceneEventData.SceneHash = sceneEventData.ClientSceneHash;
|
||||
|
||||
|
||||
var message = new SceneEventMessage
|
||||
{
|
||||
EventData = responseSceneEventData
|
||||
};
|
||||
var size = m_NetworkManager.SendMessage(message, k_DeliveryType, m_NetworkManager.ServerClientId);
|
||||
var size = m_NetworkManager.SendMessage(ref message, k_DeliveryType, m_NetworkManager.ServerClientId);
|
||||
|
||||
m_NetworkManager.NetworkMetrics.TrackSceneEventSent(m_NetworkManager.ServerClientId, (uint)responseSceneEventData.SceneEventType, sceneName, size);
|
||||
|
||||
@@ -1824,6 +1800,11 @@ namespace Unity.Netcode
|
||||
var objectsToKeep = new HashSet<NetworkObject>(m_NetworkManager.SpawnManager.SpawnedObjectsList);
|
||||
foreach (var sobj in objectsToKeep)
|
||||
{
|
||||
if (sobj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sobj.DestroyWithScene || sobj.gameObject.scene == DontDestroyOnLoadScene)
|
||||
{
|
||||
// Only move dynamically spawned network objects with no parent as child objects will follow
|
||||
@@ -1864,7 +1845,7 @@ namespace Unity.Netcode
|
||||
// at the end of scene loading we use this list to soft synchronize all in-scene placed NetworkObjects
|
||||
foreach (var networkObjectInstance in networkObjects)
|
||||
{
|
||||
// We check to make sure the NetworkManager instance is the same one to be "MultiInstanceHelpers" compatible and filter the list on a per scene basis (additive scenes)
|
||||
// We check to make sure the NetworkManager instance is the same one to be "NetcodeIntegrationTestHelpers" compatible and filter the list on a per scene basis (additive scenes)
|
||||
if (networkObjectInstance.IsSceneObject == null && networkObjectInstance.NetworkManager == m_NetworkManager && networkObjectInstance.gameObject.scene == sceneToFilterBy &&
|
||||
networkObjectInstance.gameObject.scene.handle == sceneToFilterBy.handle)
|
||||
{
|
||||
@@ -1899,6 +1880,10 @@ namespace Unity.Netcode
|
||||
|
||||
foreach (var sobj in objectsToKeep)
|
||||
{
|
||||
if (sobj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// If it is in the DDOL then
|
||||
if (sobj.gameObject.scene == DontDestroyOnLoadScene)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using Unity.Collections;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
|
||||
namespace Unity.Netcode
|
||||
{
|
||||
/// <summary>
|
||||
@@ -100,6 +99,10 @@ namespace Unity.Netcode
|
||||
internal uint SceneHash;
|
||||
internal int SceneHandle;
|
||||
|
||||
// Used by the client during synchronization
|
||||
internal uint ClientSceneHash;
|
||||
internal int ClientSceneHandle;
|
||||
|
||||
/// Only used for <see cref="SceneEventType.Synchronize"/> scene events, this assures permissions when writing
|
||||
/// NetworkVariable information. If that process changes, then we need to update this
|
||||
internal ulong TargetClientId;
|
||||
@@ -230,7 +233,14 @@ namespace Unity.Netcode
|
||||
|
||||
internal void AddSpawnedNetworkObjects()
|
||||
{
|
||||
m_NetworkObjectsSync = m_NetworkManager.SpawnManager.SpawnedObjectsList.ToList();
|
||||
m_NetworkObjectsSync.Clear();
|
||||
foreach (var sobj in m_NetworkManager.SpawnManager.SpawnedObjectsList)
|
||||
{
|
||||
if (sobj.Observers.Contains(TargetClientId))
|
||||
{
|
||||
m_NetworkObjectsSync.Add(sobj);
|
||||
}
|
||||
}
|
||||
m_NetworkObjectsSync.Sort(SortNetworkObjects);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Unity.Netcode
|
||||
|
||||
/// <summary>
|
||||
/// Create a FastBufferReader from a NativeArray.
|
||||
///
|
||||
///
|
||||
/// A new buffer will be created using the given allocator and the value will be copied in.
|
||||
/// FastBufferReader will then own the data.
|
||||
///
|
||||
@@ -93,12 +93,12 @@ namespace Unity.Netcode
|
||||
/// <param name="offset"></param>
|
||||
public unsafe FastBufferReader(NativeArray<byte> buffer, Allocator allocator, int length = -1, int offset = 0)
|
||||
{
|
||||
Handle = CreateHandle((byte*)buffer.GetUnsafePtr(), Math.Max(1, length == -1 ? buffer.Length : length), offset, allocator);
|
||||
Handle = CreateHandle((byte*)buffer.GetUnsafePtr(), length == -1 ? buffer.Length : length, offset, allocator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a FastBufferReader from an ArraySegment.
|
||||
///
|
||||
///
|
||||
/// A new buffer will be created using the given allocator and the value will be copied in.
|
||||
/// FastBufferReader will then own the data.
|
||||
///
|
||||
@@ -117,13 +117,13 @@ namespace Unity.Netcode
|
||||
}
|
||||
fixed (byte* data = buffer.Array)
|
||||
{
|
||||
Handle = CreateHandle(data, Math.Max(1, length == -1 ? buffer.Count : length), offset, allocator);
|
||||
Handle = CreateHandle(data, length == -1 ? buffer.Count : length, offset, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a FastBufferReader from an existing byte array.
|
||||
///
|
||||
///
|
||||
/// A new buffer will be created using the given allocator and the value will be copied in.
|
||||
/// FastBufferReader will then own the data.
|
||||
///
|
||||
@@ -142,13 +142,13 @@ namespace Unity.Netcode
|
||||
}
|
||||
fixed (byte* data = buffer)
|
||||
{
|
||||
Handle = CreateHandle(data, Math.Max(1, length == -1 ? buffer.Length : length), offset, allocator);
|
||||
Handle = CreateHandle(data, length == -1 ? buffer.Length : length, offset, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a FastBufferReader from an existing byte buffer.
|
||||
///
|
||||
///
|
||||
/// A new buffer will be created using the given allocator and the value will be copied in.
|
||||
/// FastBufferReader will then own the data.
|
||||
///
|
||||
@@ -165,12 +165,12 @@ namespace Unity.Netcode
|
||||
/// <param name="offset">The offset of the buffer to start copying from</param>
|
||||
public unsafe FastBufferReader(byte* buffer, Allocator allocator, int length, int offset = 0)
|
||||
{
|
||||
Handle = CreateHandle(buffer, Math.Max(1, length), offset, allocator);
|
||||
Handle = CreateHandle(buffer, length, offset, allocator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a FastBufferReader from a FastBufferWriter.
|
||||
///
|
||||
///
|
||||
/// A new buffer will be created using the given allocator and the value will be copied in.
|
||||
/// FastBufferReader will then own the data.
|
||||
///
|
||||
@@ -187,7 +187,7 @@ namespace Unity.Netcode
|
||||
/// <param name="offset">The offset of the buffer to start copying from</param>
|
||||
public unsafe FastBufferReader(FastBufferWriter writer, Allocator allocator, int length = -1, int offset = 0)
|
||||
{
|
||||
Handle = CreateHandle(writer.GetUnsafePtr(), Math.Max(1, length == -1 ? writer.Length : length), offset, allocator);
|
||||
Handle = CreateHandle(writer.GetUnsafePtr(), length == -1 ? writer.Length : length, offset, allocator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,7 +250,7 @@ namespace Unity.Netcode
|
||||
/// When you know you will be reading multiple fields back-to-back and you know the total size,
|
||||
/// you can call TryBeginRead() once on the total size, and then follow it with calls to
|
||||
/// ReadValue() instead of ReadValueSafe() for faster serialization.
|
||||
///
|
||||
///
|
||||
/// Unsafe read operations will throw OverflowException in editor and development builds if you
|
||||
/// go past the point you've marked using TryBeginRead(). In release builds, OverflowException will not be thrown
|
||||
/// for performance reasons, since the point of using TryBeginRead is to avoid bounds checking in the following
|
||||
@@ -284,7 +284,7 @@ namespace Unity.Netcode
|
||||
/// When you know you will be reading multiple fields back-to-back and you know the total size,
|
||||
/// you can call TryBeginRead() once on the total size, and then follow it with calls to
|
||||
/// ReadValue() instead of ReadValueSafe() for faster serialization.
|
||||
///
|
||||
///
|
||||
/// Unsafe read operations will throw OverflowException in editor and development builds if you
|
||||
/// go past the point you've marked using TryBeginRead(). In release builds, OverflowException will not be thrown
|
||||
/// for performance reasons, since the point of using TryBeginRead is to avoid bounds checking in the following
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Unity.Netcode
|
||||
/// There is a one second maximum lifetime of triggers to avoid memory leaks. After one second has passed
|
||||
/// without the requested object ID being spawned, the triggers for it are automatically deleted.
|
||||
/// </summary>
|
||||
internal unsafe void TriggerOnSpawn(ulong networkObjectId, FastBufferReader reader, in NetworkContext context)
|
||||
internal unsafe void TriggerOnSpawn(ulong networkObjectId, FastBufferReader reader, ref NetworkContext context)
|
||||
{
|
||||
if (!m_Triggers.ContainsKey(networkObjectId))
|
||||
{
|
||||
@@ -212,7 +212,7 @@ namespace Unity.Netcode
|
||||
NetworkObjectId = networkObject.NetworkObjectId,
|
||||
OwnerClientId = networkObject.OwnerClientId
|
||||
};
|
||||
var size = NetworkManager.SendMessage(message, NetworkDelivery.ReliableSequenced, NetworkManager.ConnectedClientsIds);
|
||||
var size = NetworkManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, NetworkManager.ConnectedClientsIds);
|
||||
|
||||
foreach (var client in NetworkManager.ConnectedClients)
|
||||
{
|
||||
@@ -280,13 +280,17 @@ namespace Unity.Netcode
|
||||
|
||||
networkObject.OwnerClientId = clientId;
|
||||
|
||||
if (TryGetNetworkClient(clientId, out NetworkClient newNetworkClient))
|
||||
{
|
||||
newNetworkClient.OwnedObjects.Add(networkObject);
|
||||
}
|
||||
|
||||
var message = new ChangeOwnershipMessage
|
||||
{
|
||||
NetworkObjectId = networkObject.NetworkObjectId,
|
||||
OwnerClientId = networkObject.OwnerClientId
|
||||
};
|
||||
var size = NetworkManager.SendMessage(message, NetworkDelivery.ReliableSequenced, NetworkManager.ConnectedClientsIds);
|
||||
var size = NetworkManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, NetworkManager.ConnectedClientsIds);
|
||||
|
||||
foreach (var client in NetworkManager.ConnectedClients)
|
||||
{
|
||||
@@ -422,6 +426,15 @@ namespace Unity.Netcode
|
||||
throw new SpawnStateException("Object is already spawned");
|
||||
}
|
||||
|
||||
if (!sceneObject)
|
||||
{
|
||||
var networkObjectChildren = networkObject.GetComponentsInChildren<NetworkObject>();
|
||||
if (networkObjectChildren.Length > 1)
|
||||
{
|
||||
Debug.LogError("Spawning NetworkObjects with nested NetworkObjects is only supported for scene objects. Child NetworkObjects will not be spawned over the network!");
|
||||
}
|
||||
}
|
||||
|
||||
SpawnNetworkObjectLocallyCommon(networkObject, networkId, sceneObject, playerObject, ownerClientId, destroyWithScene);
|
||||
}
|
||||
|
||||
@@ -525,6 +538,13 @@ namespace Unity.Netcode
|
||||
triggerInfo.TriggerData.Dispose();
|
||||
m_Triggers.Remove(networkId);
|
||||
}
|
||||
|
||||
// propagate the IsSceneObject setting to child NetworkObjects
|
||||
var children = networkObject.GetComponentsInChildren<NetworkObject>();
|
||||
foreach (var childObject in children)
|
||||
{
|
||||
childObject.IsSceneObject = sceneObject;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SendSpawnCallForObject(ulong clientId, NetworkObject networkObject)
|
||||
@@ -543,7 +563,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
ObjectInfo = networkObject.GetMessageSceneObject(clientId)
|
||||
};
|
||||
var size = NetworkManager.SendMessage(message, NetworkDelivery.ReliableFragmentedSequenced, clientId);
|
||||
var size = NetworkManager.SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, clientId);
|
||||
NetworkManager.NetworkMetrics.TrackObjectSpawnSent(clientId, networkObject, size);
|
||||
|
||||
networkObject.MarkVariablesDirty();
|
||||
@@ -678,6 +698,7 @@ namespace Unity.Netcode
|
||||
internal void ServerSpawnSceneObjectsOnStartSweep()
|
||||
{
|
||||
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>();
|
||||
var networkObjectsToSpawn = new List<NetworkObject>();
|
||||
|
||||
for (int i = 0; i < networkObjects.Length; i++)
|
||||
{
|
||||
@@ -685,10 +706,15 @@ namespace Unity.Netcode
|
||||
{
|
||||
if (networkObjects[i].IsSceneObject == null)
|
||||
{
|
||||
SpawnNetworkObjectLocally(networkObjects[i], GetNetworkObjectId(), true, false, null, true);
|
||||
networkObjectsToSpawn.Add(networkObjects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var networkObject in networkObjectsToSpawn)
|
||||
{
|
||||
SpawnNetworkObjectLocally(networkObject, GetNetworkObjectId(), true, false, null, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObject)
|
||||
@@ -783,7 +809,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
NetworkObjectId = networkObject.NetworkObjectId
|
||||
};
|
||||
var size = NetworkManager.SendMessage(message, NetworkDelivery.ReliableSequenced, m_TargetClientIds);
|
||||
var size = NetworkManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, m_TargetClientIds);
|
||||
foreach (var targetClientId in m_TargetClientIds)
|
||||
{
|
||||
NetworkManager.NetworkMetrics.TrackObjectDestroySent(targetClientId, networkObject, size);
|
||||
@@ -822,7 +848,7 @@ namespace Unity.Netcode
|
||||
{
|
||||
foreach (var sobj in SpawnedObjectsList)
|
||||
{
|
||||
if (sobj.CheckObjectVisibility == null || NetworkManager.IsServer)
|
||||
if (sobj.CheckObjectVisibility == null)
|
||||
{
|
||||
if (!sobj.Observers.Contains(clientId))
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace Unity.Netcode
|
||||
/// <value><c>true</c> if is supported; otherwise, <c>false</c>.</value>
|
||||
public virtual bool IsSupported => true;
|
||||
|
||||
internal INetworkMetrics NetworkMetrics;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for transport network events
|
||||
/// </summary>
|
||||
@@ -95,6 +97,14 @@ namespace Unity.Netcode
|
||||
/// <summary>
|
||||
/// Initializes the transport
|
||||
/// </summary>
|
||||
public abstract void Initialize();
|
||||
/// /// <param name="networkManager">optionally pass in NetworkManager</param>
|
||||
public abstract void Initialize(NetworkManager networkManager = null);
|
||||
}
|
||||
|
||||
#if UNITY_INCLUDE_TESTS
|
||||
public abstract class TestingNetworkTransport : NetworkTransport
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#if UNITY_UNET_PRESENT
|
||||
using System;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
@@ -50,3 +51,4 @@ namespace Unity.Netcode.Transports.UNET
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#if UNITY_UNET_PRESENT
|
||||
#pragma warning disable 618 // disable is obsolete
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
using System;
|
||||
@@ -41,6 +42,8 @@ namespace Unity.Netcode.Transports.UNET
|
||||
|
||||
public override ulong ServerClientId => GetNetcodeClientId(0, 0, true);
|
||||
|
||||
internal NetworkManager NetworkManager;
|
||||
|
||||
protected void LateUpdate()
|
||||
{
|
||||
if (UnityEngine.Networking.NetworkTransport.IsStarted && MessageSendMode == SendMode.Queued)
|
||||
@@ -48,7 +51,7 @@ namespace Unity.Netcode.Transports.UNET
|
||||
#if UNITY_WEBGL
|
||||
Debug.LogError("Cannot use queued sending mode for WebGL");
|
||||
#else
|
||||
if (NetworkManager.Singleton.IsServer)
|
||||
if (NetworkManager != null && NetworkManager.IsServer)
|
||||
{
|
||||
foreach (var targetClient in NetworkManager.Singleton.ConnectedClientsList)
|
||||
{
|
||||
@@ -230,8 +233,10 @@ namespace Unity.Netcode.Transports.UNET
|
||||
UnityEngine.Networking.NetworkTransport.Shutdown();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
public override void Initialize(NetworkManager networkManager = null)
|
||||
{
|
||||
NetworkManager = networkManager;
|
||||
|
||||
m_MessageBuffer = new byte[MessageBufferSize];
|
||||
|
||||
UnityEngine.Networking.NetworkTransport.Init();
|
||||
@@ -279,3 +284,4 @@ namespace Unity.Netcode.Transports.UNET
|
||||
}
|
||||
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
|
||||
#pragma warning restore 618 // restore is obsolete
|
||||
#endif
|
||||
|
||||
@@ -6,21 +6,28 @@
|
||||
"Unity.Multiplayer.NetStats",
|
||||
"Unity.Multiplayer.NetStatsReporting",
|
||||
"Unity.Multiplayer.NetworkSolutionInterface",
|
||||
"Unity.Multiplayer.Tools.MetricTypes",
|
||||
"Unity.Multiplayer.Tools.NetStats",
|
||||
"Unity.Multiplayer.Tools.NetStatsReporting",
|
||||
"Unity.Multiplayer.Tools.NetworkSolutionInterface",
|
||||
"Unity.Collections"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.multiplayer.tools",
|
||||
"expression": "",
|
||||
"define": "MULTIPLAYER_TOOLS"
|
||||
},
|
||||
{
|
||||
"name": "Unity",
|
||||
"expression": "(0,2022.2.0a5)",
|
||||
"define": "UNITY_UNET_PRESENT"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.multiplayer.tools",
|
||||
"expression": "1.0.0-pre.4",
|
||||
"define": "MULTIPLAYER_TOOLS_1_0_0_PRE_4"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user