Skip to content

Commit e3a614e

Browse files
Merge branch 'develop-2.0.0' into fix/server-sending-disconnectmessage-to-self
2 parents 0c67142 + 6153519 commit e3a614e

File tree

15 files changed

+275
-89
lines changed

15 files changed

+275
-89
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2626

2727
- Fixed issue where a warning message was being logged upon a client disconnecting from a server when the log level is set to developer. (#3786)
2828
- Fixed issue where the server or host would no longer have access to the transport id to client id table when processing a transport level client disconnect event. (#3786)
29+
- Fixed issue where invoking an RPC, on another `NetworkBehaviour` associated with the same `NetworkObject` that is ordered before the `NetworkBehaviour` invoking the RPC, during `OnNetworkSpawn` could throw an exception if scene management is disabled. (#3782)
2930
- Fixed issue where the `Axis to Synchronize` toggles didn't work with multi object editing in `NetworkTransform`. (#3781)
3031

3132

com.unity.netcode.gameobjects/Editor/CodeGen/NetworkBehaviourILPP.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,7 @@ private void CreateNetworkVariableTypeInitializers(AssemblyDefinition assembly,
595595
private const string k_NetworkManager_IsServer = nameof(NetworkManager.IsServer);
596596
private const string k_NetworkManager_IsClient = nameof(NetworkManager.IsClient);
597597
private const string k_NetworkManager_LogLevel = nameof(NetworkManager.LogLevel);
598-
599598
private const string k_NetworkBehaviour_rpc_func_table = nameof(NetworkBehaviour.__rpc_func_table);
600-
private const string k_NetworkBehaviour_rpc_name_table = nameof(NetworkBehaviour.__rpc_name_table);
601599
private const string k_NetworkBehaviour_rpc_exec_stage = nameof(NetworkBehaviour.__rpc_exec_stage);
602600
private const string k_NetworkBehaviour_NetworkVariableFields = nameof(NetworkBehaviour.NetworkVariableFields);
603601
private const string k_NetworkBehaviour_beginSendServerRpc = nameof(NetworkBehaviour.__beginSendServerRpc);

com.unity.netcode.gameobjects/Editor/CodeGen/RuntimeAccessModifiersILPP.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,12 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
151151
{
152152
fieldDefinition.IsFamilyOrAssembly = true;
153153
}
154-
154+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
155155
if (fieldDefinition.Name == nameof(NetworkBehaviour.__rpc_name_table))
156156
{
157157
fieldDefinition.IsFamilyOrAssembly = true;
158158
}
159+
#endif
159160
}
160161

161162
foreach (var methodDefinition in typeDefinition.Methods)

com.unity.netcode.gameobjects/Editor/CodeGen/Unity.Netcode.Editor.CodeGen.asmdef

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
"name": "com.unity.nuget.mono-cecil",
2525
"expression": "(0,1.11.4)",
2626
"define": "CECIL_CONSTRAINTS_ARE_TYPE_REFERENCES"
27+
},
28+
{
29+
"name": "com.unity.multiplayer.tools",
30+
"expression": "",
31+
"define": "MULTIPLAYER_TOOLS"
2732
}
2833
],
2934
"noEngineReferences": false

com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs

Lines changed: 128 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Runtime.CompilerServices;
34
using Unity.Collections;
45
using UnityEngine;
56

@@ -40,7 +41,7 @@ public abstract class NetworkBehaviour : MonoBehaviour
4041
internal static readonly Dictionary<Type, Dictionary<uint, RpcReceiveHandler>> __rpc_func_table = new Dictionary<Type, Dictionary<uint, RpcReceiveHandler>>();
4142
internal static readonly Dictionary<Type, Dictionary<uint, RpcInvokePermission>> __rpc_permission_table = new Dictionary<Type, Dictionary<uint, RpcInvokePermission>>();
4243

43-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
44+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
4445
// RuntimeAccessModifiersILPP will make this `public`
4546
internal static readonly Dictionary<Type, Dictionary<uint, string>> __rpc_name_table = new Dictionary<Type, Dictionary<uint, string>>();
4647
#endif
@@ -142,16 +143,9 @@ internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
142143
}
143144

144145
bufferWriter.Dispose();
145-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
146-
if (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName))
147-
{
148-
networkManager.NetworkMetrics.TrackRpcSent(
149-
NetworkManager.ServerClientId,
150-
m_NetworkObject,
151-
rpcMethodName,
152-
__getTypeName(),
153-
rpcWriteSize);
154-
}
146+
147+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
148+
TrackRpcMetricsSend(ref serverRpcMessage, rpcMethodId, rpcWriteSize);
155149
#endif
156150
}
157151

@@ -275,7 +269,11 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth
275269
}
276270

277271
bufferWriter.Dispose();
278-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
272+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
273+
if (!ValidateRpcMessageMetrics(GetType()))
274+
{
275+
return;
276+
}
279277
if (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName))
280278
{
281279
if (clientRpcParams.Send.TargetClientIds != null)
@@ -755,6 +753,11 @@ public virtual void OnNetworkPreDespawn() { }
755753

756754
internal virtual void InternalOnNetworkPreSpawn(ref NetworkManager networkManager) { }
757755

756+
/// <summary>
757+
/// Handles pre-spawn related initializations.
758+
/// Invokes any <see cref="InternalOnNetworkPreSpawn"/> subscriptions.
759+
/// Finally invokes <see cref="OnNetworkPreSpawn(ref NetworkManager)"/>.
760+
/// </summary>
758761
internal void NetworkPreSpawn(ref NetworkManager networkManager, NetworkObject networkObject)
759762
{
760763
m_NetworkObject = networkObject;
@@ -782,13 +785,28 @@ internal void NetworkPreSpawn(ref NetworkManager networkManager, NetworkObject n
782785
}
783786
}
784787

788+
/// <summary>
789+
/// Initializes the:
790+
/// - <see cref="IsSpawned"/> state.
791+
/// - <see cref="NetworkVariableBase"/> instances.
792+
/// - Spawned related properties are applied.
793+
/// !! Note !!:
794+
/// This also populates RPC related tables based on this <see cref="NetworkBehaviour"/>'s RPCs (if any).
795+
/// </summary>
785796
internal void InternalOnNetworkSpawn()
786797
{
787798
IsSpawned = true;
788-
// Initialize the NetworkVariables so they are accessible in OnNetworkSpawn;
799+
// Initialize the NetworkVariables and **RPC tables** so they are accessible in OnNetworkSpawn
789800
InitializeVariables();
801+
// Apply the spawned state/properties to this instance
790802
UpdateNetworkProperties();
803+
}
791804

805+
/// <summary>
806+
/// Handles invoking <see cref="OnNetworkSpawn"/>.
807+
/// </summary>
808+
internal void NetworkSpawn()
809+
{
792810
try
793811
{
794812
OnNetworkSpawn();
@@ -799,6 +817,9 @@ internal void InternalOnNetworkSpawn()
799817
}
800818
}
801819

820+
/// <summary>
821+
/// Handles invoking <see cref="OnNetworkPostSpawn"/>.
822+
/// </summary>
802823
internal void NetworkPostSpawn()
803824
{
804825
try
@@ -819,6 +840,9 @@ internal void NetworkPostSpawn()
819840
}
820841
}
821842

843+
/// <summary>
844+
/// Handles invoking <see cref="OnNetworkSessionSynchronized"/>.
845+
/// </summary>
822846
internal void NetworkSessionSynchronized()
823847
{
824848
try
@@ -832,6 +856,9 @@ internal void NetworkSessionSynchronized()
832856
}
833857
}
834858

859+
/// <summary>
860+
/// Handles invoking <see cref="OnInSceneObjectsSpawned"/>.
861+
/// </summary>
835862
internal void InSceneNetworkObjectsSpawned()
836863
{
837864
try
@@ -844,6 +871,9 @@ internal void InSceneNetworkObjectsSpawned()
844871
}
845872
}
846873

874+
/// <summary>
875+
/// Handles invoking <see cref="OnNetworkPreDespawn"/>.
876+
/// </summary>
847877
internal void InternalOnNetworkPreDespawn()
848878
{
849879
try
@@ -863,6 +893,9 @@ internal void InternalOnNetworkPreDespawn()
863893
}
864894
}
865895

896+
/// <summary>
897+
/// Handles invoking <see cref="OnNetworkDespawn"/>.
898+
/// </summary>
866899
internal void InternalOnNetworkDespawn()
867900
{
868901
IsSpawned = false;
@@ -965,13 +998,90 @@ internal virtual void __initializeRpcs()
965998
internal void __registerRpc(uint hash, RpcReceiveHandler handler, string rpcMethodName, RpcInvokePermission permission)
966999
#pragma warning restore IDE1006 // restore naming rule violation check
9671000
{
968-
__rpc_func_table[GetType()][hash] = handler;
969-
__rpc_permission_table[GetType()][hash] = permission;
970-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
971-
__rpc_name_table[GetType()][hash] = rpcMethodName;
1001+
var rpcType = GetType();
1002+
__rpc_func_table[rpcType][hash] = handler;
1003+
__rpc_permission_table[rpcType][hash] = permission;
1004+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
1005+
__rpc_name_table[rpcType][hash] = rpcMethodName;
9721006
#endif
9731007
}
9741008

1009+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
1010+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1011+
private bool ValidateRpcMessageMetrics(Type type)
1012+
{
1013+
if (m_NetworkManager == null)
1014+
{
1015+
Debug.LogError($"[{nameof(ValidateRpcMessageMetrics)}][{type.Name}] {nameof(NetworkBehaviour)} is attempting to invoking an RPC before {nameof(NetworkManager)} has been initialized!");
1016+
return false;
1017+
}
1018+
1019+
if (!__rpc_name_table.ContainsKey(type))
1020+
{
1021+
Debug.LogError($"[{nameof(ValidateRpcMessageMetrics)}][{type.Name}][{nameof(__rpc_name_table)}] RPC table initialization failure: Table does not contain an entry for {type.Name}!");
1022+
return false;
1023+
}
1024+
return true;
1025+
}
1026+
1027+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1028+
internal void TrackRpcMetricsSend(ref ServerRpcMessage message, uint rpcMethodId, int rpcWriteSize)
1029+
{
1030+
var type = GetType();
1031+
if (!ValidateRpcMessageMetrics(type))
1032+
{
1033+
return;
1034+
}
1035+
if (__rpc_name_table[type].TryGetValue(rpcMethodId, out var rpcMethodName))
1036+
{
1037+
m_NetworkManager.NetworkMetrics.TrackRpcSent(
1038+
NetworkManager.ServerClientId,
1039+
m_NetworkObject,
1040+
rpcMethodName,
1041+
__getTypeName(),
1042+
rpcWriteSize);
1043+
}
1044+
}
1045+
1046+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1047+
internal void TrackRpcMetricsSend(ulong clientId, ref RpcMessage message, int length)
1048+
{
1049+
var type = GetType();
1050+
if (!ValidateRpcMessageMetrics(type))
1051+
{
1052+
return;
1053+
}
1054+
if (__rpc_name_table[type].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
1055+
{
1056+
m_NetworkManager.NetworkMetrics.TrackRpcSent(
1057+
m_NetworkManager.LocalClientId,
1058+
NetworkObject,
1059+
rpcMethodName,
1060+
__getTypeName(),
1061+
length);
1062+
}
1063+
}
1064+
1065+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1066+
internal void TrackRpcMetricsReceive(ref RpcMetadata metadata, ref NetworkContext context, int length)
1067+
{
1068+
var type = GetType();
1069+
if (!ValidateRpcMessageMetrics(type))
1070+
{
1071+
return;
1072+
}
1073+
if (__rpc_name_table[type].TryGetValue(metadata.NetworkRpcMethodId, out var rpcMethodName))
1074+
{
1075+
m_NetworkManager.NetworkMetrics.TrackRpcReceived(
1076+
context.SenderId,
1077+
NetworkObject,
1078+
rpcMethodName,
1079+
__getTypeName(),
1080+
length);
1081+
}
1082+
}
1083+
#endif
1084+
9751085
#pragma warning disable IDE1006 // disable naming rule violation check
9761086
// RuntimeAccessModifiersILPP will make this `protected`
9771087
// Using this method here because ILPP doesn't seem to let us do visibility modification on properties.
@@ -1014,7 +1124,7 @@ internal void InitializeVariables()
10141124
{
10151125
__rpc_func_table[GetType()] = new Dictionary<uint, RpcReceiveHandler>();
10161126
__rpc_permission_table[GetType()] = new Dictionary<uint, RpcInvokePermission>();
1017-
#if UNITY_EDITOR || DEVELOPMENT_BUILD || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
1127+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
10181128
__rpc_name_table[GetType()] = new Dictionary<uint, string>();
10191129
#endif
10201130
__initializeRpcs();

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,8 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem
4949
// RuntimeAccessModifiersILPP will make this `public`
5050
internal static readonly Dictionary<uint, RpcReceiveHandler> __rpc_func_table = new Dictionary<uint, RpcReceiveHandler>();
5151

52-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
53-
// RuntimeAccessModifiersILPP will make this `public`
52+
// RuntimeAccessModifiersILPP will make this `public` (legacy table should be removed in v3.x.x)
5453
internal static readonly Dictionary<uint, string> __rpc_name_table = new Dictionary<uint, string>();
55-
#endif
5654

5755
#pragma warning restore IDE1006 // restore naming rule violation check
5856

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2556,6 +2556,12 @@ internal void InvokeBehaviourNetworkSpawn()
25562556
{
25572557
NetworkManager.SpawnManager.UpdateOwnershipTable(this, OwnerClientId);
25582558

2559+
// Always invoke all InternalOnNetworkSpawn methods on each child NetworkBehaviour
2560+
// ** before ** invoking OnNetworkSpawn.
2561+
// This assures all NetworkVariables and RPC related tables have been initialized
2562+
// prior to invoking OnNetworkSpawn so cross NetworkBehaviour:
2563+
// - accessing of NetworkVariables will work correctly.
2564+
// - invocation of RPCs will work properly (and not throw exception under certain scenarios)
25592565
foreach (var childBehaviour in ChildNetworkBehaviours)
25602566
{
25612567
if (!childBehaviour.gameObject.activeInHierarchy)
@@ -2565,6 +2571,17 @@ internal void InvokeBehaviourNetworkSpawn()
25652571
}
25662572
childBehaviour.InternalOnNetworkSpawn();
25672573
}
2574+
2575+
// After initialization, we can then invoke OnNetworkSpawn on each child NetworkBehaviour.
2576+
foreach (var childBehaviour in ChildNetworkBehaviours)
2577+
{
2578+
if (!childBehaviour.gameObject.activeInHierarchy)
2579+
{
2580+
Debug.LogWarning($"{GenerateDisabledNetworkBehaviourWarning(childBehaviour)}");
2581+
continue;
2582+
}
2583+
childBehaviour.NetworkSpawn();
2584+
}
25682585
}
25692586

25702587
internal void InvokeBehaviourNetworkPostSpawn()
@@ -2578,7 +2595,6 @@ internal void InvokeBehaviourNetworkPostSpawn()
25782595
}
25792596
}
25802597

2581-
25822598
internal void InternalNetworkSessionSynchronized()
25832599
{
25842600
for (int i = 0; i < ChildNetworkBehaviours.Count; i++)

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,8 @@ public static unsafe bool Deserialize(ref FastBufferReader reader, ref NetworkCo
4040
}
4141

4242
payload = new FastBufferReader(reader.GetUnsafePtrAtCurrentPosition(), Allocator.None, reader.Length - reader.Position);
43-
44-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
45-
if (NetworkBehaviour.__rpc_name_table[networkBehaviour.GetType()].TryGetValue(metadata.NetworkRpcMethodId, out var rpcMethodName))
46-
{
47-
networkManager.NetworkMetrics.TrackRpcReceived(
48-
context.SenderId,
49-
networkObject,
50-
rpcMethodName,
51-
networkBehaviour.__getTypeName(),
52-
reader.Length);
53-
}
43+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
44+
networkBehaviour.TrackRpcMetricsReceive(ref metadata, ref context, reader.Length);
5445
#endif
5546
return true;
5647
}

com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/BaseRpcTarget.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,10 @@ protected void CheckLockBeforeDispose()
5252

5353
private protected void SendMessageToClient(NetworkBehaviour behaviour, ulong clientId, ref RpcMessage message, NetworkDelivery delivery)
5454
{
55-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
56-
var size =
57-
#endif
58-
behaviour.NetworkManager.MessageManager.SendMessage(ref message, delivery, clientId);
59-
60-
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
61-
if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName))
62-
{
63-
behaviour.NetworkManager.NetworkMetrics.TrackRpcSent(
64-
clientId,
65-
behaviour.NetworkObject,
66-
rpcMethodName,
67-
behaviour.__getTypeName(),
68-
size);
69-
}
55+
var size = behaviour.NetworkManager.MessageManager.SendMessage(ref message, delivery, clientId);
56+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
57+
// Send to a specific client
58+
behaviour.TrackRpcMetricsSend(clientId, ref message, size);
7059
#endif
7160
}
7261
}

0 commit comments

Comments
 (0)