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:
Unity Technologies
2022-03-02 00:00:00 +00:00
parent 4818405514
commit 5b4aaa8b59
205 changed files with 6971 additions and 2722 deletions

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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
}
}
}
}

View 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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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)
{

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}