Skip to content

Commit adcec18

Browse files
chore: migrate NetworkTransform away from using named messages over to NetworkTransformMessage [MTT-7535] (#2810)
* update Adding the NetworkTransformMessage Expanding INetworkMessgeILPP assembly processing to Unity.Netcode.Components.
1 parent 64ed674 commit adcec18

File tree

7 files changed

+171
-96
lines changed

7 files changed

+171
-96
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

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

1717
### Changed
1818

19+
- Changed `NetworkTransform` to now use `NetworkTransformMessage` as opposed to named messages for NetworkTransformState updates. (#2810)
1920
- Changed `CustomMessageManager` so it no longer attempts to register or "unregister" a null or empty string and will log an error if this condition occurs. (#2807)
2021

2122

com.unity.netcode.gameobjects/Components/Messages.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using Unity.Netcode.Components;
2+
using UnityEngine;
3+
4+
namespace Unity.Netcode
5+
{
6+
/// <summary>
7+
/// NetworkTransform State Update Message
8+
/// </summary>
9+
internal struct NetworkTransformMessage : INetworkMessage
10+
{
11+
public int Version => 0;
12+
public ulong NetworkObjectId;
13+
public int NetworkBehaviourId;
14+
public NetworkTransform.NetworkTransformState State;
15+
16+
private NetworkTransform m_ReceiverNetworkTransform;
17+
private FastBufferReader m_CurrentReader;
18+
19+
private unsafe void CopyPayload(ref FastBufferWriter writer)
20+
{
21+
writer.WriteBytesSafe(m_CurrentReader.GetUnsafePtrAtCurrentPosition(), m_CurrentReader.Length - m_CurrentReader.Position);
22+
}
23+
24+
public void Serialize(FastBufferWriter writer, int targetVersion)
25+
{
26+
if (m_CurrentReader.IsInitialized)
27+
{
28+
CopyPayload(ref writer);
29+
}
30+
else
31+
{
32+
BytePacker.WriteValueBitPacked(writer, NetworkObjectId);
33+
BytePacker.WriteValueBitPacked(writer, NetworkBehaviourId);
34+
writer.WriteNetworkSerializable(State);
35+
}
36+
}
37+
38+
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
39+
{
40+
var networkManager = context.SystemOwner as NetworkManager;
41+
if (networkManager == null)
42+
{
43+
Debug.LogError($"[{nameof(NetworkTransformMessage)}] System owner context was not of type {nameof(NetworkManager)}!");
44+
return false;
45+
}
46+
var currentPosition = reader.Position;
47+
ByteUnpacker.ReadValueBitPacked(reader, out NetworkObjectId);
48+
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
49+
{
50+
networkManager.DeferredMessageManager.DeferMessage(IDeferredNetworkMessageManager.TriggerType.OnSpawn, NetworkObjectId, reader, ref context);
51+
return false;
52+
}
53+
// Get the behaviour index
54+
ByteUnpacker.ReadValueBitPacked(reader, out NetworkBehaviourId);
55+
56+
// Deserialize the state
57+
reader.ReadNetworkSerializable(out State);
58+
59+
var networkObject = networkManager.SpawnManager.SpawnedObjects[NetworkObjectId];
60+
61+
// Get the target NetworkTransform
62+
m_ReceiverNetworkTransform = networkObject.ChildNetworkBehaviours[NetworkBehaviourId] as NetworkTransform;
63+
64+
var isServerAuthoritative = m_ReceiverNetworkTransform.IsServerAuthoritative();
65+
var ownerAuthoritativeServerSide = !isServerAuthoritative && networkManager.IsServer;
66+
if (ownerAuthoritativeServerSide)
67+
{
68+
var ownerClientId = networkObject.OwnerClientId;
69+
if (ownerClientId == NetworkManager.ServerClientId)
70+
{
71+
// Ownership must have changed, ignore any additional pending messages that might have
72+
// come from a previous owner client.
73+
return true;
74+
}
75+
76+
var networkDelivery = State.IsReliableStateUpdate() ? NetworkDelivery.ReliableSequenced : NetworkDelivery.UnreliableSequenced;
77+
78+
// Forward the state update if there are any remote clients to foward it to
79+
if (networkManager.ConnectionManager.ConnectedClientsList.Count > (networkManager.IsHost ? 2 : 1))
80+
{
81+
// This is only to copy the existing and already serialized struct for forwarding purposes only.
82+
// This will not include any changes made to this struct at this particular stage of processing the message.
83+
var currentMessage = this;
84+
// Create a new reader that replicates this message
85+
currentMessage.m_CurrentReader = new FastBufferReader(reader, Collections.Allocator.None);
86+
// Rewind the new reader to the beginning of the message's payload
87+
currentMessage.m_CurrentReader.Seek(currentPosition);
88+
// Forward the message to all connected clients that are observers of the associated NetworkObject
89+
var clientCount = networkManager.ConnectionManager.ConnectedClientsList.Count;
90+
for (int i = 0; i < clientCount; i++)
91+
{
92+
var clientId = networkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
93+
if (NetworkManager.ServerClientId == clientId || (!isServerAuthoritative && clientId == ownerClientId) || !networkObject.Observers.Contains(clientId))
94+
{
95+
continue;
96+
}
97+
networkManager.MessageManager.SendMessage(ref currentMessage, networkDelivery, clientId);
98+
}
99+
// Dispose of the reader used for forwarding
100+
currentMessage.m_CurrentReader.Dispose();
101+
}
102+
}
103+
return true;
104+
}
105+
106+
public void Handle(ref NetworkContext context)
107+
{
108+
if (m_ReceiverNetworkTransform == null)
109+
{
110+
Debug.LogError($"[{nameof(NetworkTransformMessage)}][Dropped] Reciever {nameof(NetworkTransform)} was not set!");
111+
return;
112+
}
113+
m_ReceiverNetworkTransform.TransformStateUpdate(ref State);
114+
}
115+
}
116+
}

com.unity.netcode.gameobjects/Components/Messages/NetworkTransformMessage.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.netcode.gameobjects/Components/NetworkTransform.cs

Lines changed: 33 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Runtime.CompilerServices;
4-
using Unity.Collections;
54
using Unity.Mathematics;
65
using UnityEngine;
76

@@ -1330,9 +1329,6 @@ internal NetworkTransformState LocalAuthoritativeNetworkState
13301329
private Quaternion m_CurrentRotation;
13311330
private Vector3 m_TargetRotation;
13321331

1333-
// Used to for each instance to uniquely identify the named message
1334-
private string m_MessageName;
1335-
13361332

13371333
[MethodImpl(MethodImplOptions.AggressiveInlining)]
13381334
internal void UpdatePositionInterpolator(Vector3 position, double time, bool resetInterpolator = false)
@@ -2753,21 +2749,12 @@ public override void OnNetworkSpawn()
27532749
// Started using this again to avoid the getter processing cost of NetworkBehaviour.NetworkManager
27542750
m_CachedNetworkManager = NetworkManager;
27552751

2756-
// Register a custom named message specifically for this instance
2757-
m_MessageName = $"NTU_{NetworkObjectId}_{NetworkBehaviourId}";
2758-
m_CachedNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(m_MessageName, TransformStateUpdate);
27592752
Initialize();
27602753
}
27612754

27622755
/// <inheritdoc/>
27632756
public override void OnNetworkDespawn()
27642757
{
2765-
// During destroy, use NetworkBehaviour.NetworkManager as opposed to m_CachedNetworkManager
2766-
if (!NetworkManager.ShutdownInProgress && NetworkManager.CustomMessagingManager != null && !string.IsNullOrEmpty(m_MessageName))
2767-
{
2768-
NetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(m_MessageName);
2769-
}
2770-
27712758
DeregisterForTickUpdate(this);
27722759

27732760
CanCommitToTransform = false;
@@ -3156,79 +3143,23 @@ public bool IsServerAuthoritative()
31563143
}
31573144

31583145
/// <summary>
3159-
/// Receives the <see cref="NetworkTransformState"/> named message updates
3146+
/// Invoked by <see cref="NetworkTransformMessage"/> to update the transform state
31603147
/// </summary>
3161-
/// <param name="senderId">authority of the transform</param>
3162-
/// <param name="messagePayload">serialzied <see cref="NetworkTransformState"/></param>
3163-
private void TransformStateUpdate(ulong senderId, FastBufferReader messagePayload)
3148+
/// <param name="networkTransformState"></param>
3149+
internal void TransformStateUpdate(ref NetworkTransformState networkTransformState)
31643150
{
3165-
var ownerAuthoritativeServerSide = !OnIsServerAuthoritative() && IsServer;
3166-
if (ownerAuthoritativeServerSide && OwnerClientId == NetworkManager.ServerClientId)
3167-
{
3168-
// Ownership must have changed, ignore any additional pending messages that might have
3169-
// come from a previous owner client.
3170-
return;
3171-
}
3172-
31733151
// Store the previous/old state
31743152
m_OldState = m_LocalAuthoritativeNetworkState;
31753153

3176-
// Save the current payload stream position
3177-
var currentPosition = messagePayload.Position;
3178-
3179-
// Deserialize the message (and determine network delivery)
3180-
messagePayload.ReadNetworkSerializableInPlace(ref m_LocalAuthoritativeNetworkState);
3181-
3182-
// Rewind back prior to serialization
3183-
messagePayload.Seek(currentPosition);
3154+
// Assign the new incoming state
3155+
m_LocalAuthoritativeNetworkState = networkTransformState;
31843156

3185-
// Get the network delivery method used to send this state update
3186-
var networkDelivery = m_LocalAuthoritativeNetworkState.ReliableSequenced ? NetworkDelivery.ReliableSequenced : NetworkDelivery.UnreliableSequenced;
3187-
3188-
// Forward owner authoritative messages before doing anything else
3189-
if (ownerAuthoritativeServerSide)
3190-
{
3191-
// Forward the state update if there are any remote clients to foward it to
3192-
if (m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count > (IsHost ? 2 : 1))
3193-
{
3194-
ForwardStateUpdateMessage(messagePayload, networkDelivery);
3195-
}
3196-
}
3197-
3198-
// Apply the message
3157+
// Apply the state update
31993158
OnNetworkStateChanged(m_OldState, m_LocalAuthoritativeNetworkState);
32003159
}
32013160

32023161
/// <summary>
3203-
/// Forwards owner authoritative state updates when received by the server
3204-
/// </summary>
3205-
/// <param name="messagePayload">the owner state message payload</param>
3206-
private unsafe void ForwardStateUpdateMessage(FastBufferReader messagePayload, NetworkDelivery networkDelivery)
3207-
{
3208-
var serverAuthoritative = OnIsServerAuthoritative();
3209-
var currentPosition = messagePayload.Position;
3210-
var messageSize = messagePayload.Length - currentPosition;
3211-
var writer = new FastBufferWriter(messageSize, Allocator.Temp);
3212-
using (writer)
3213-
{
3214-
writer.WriteBytesSafe(messagePayload.GetUnsafePtr(), messageSize, currentPosition);
3215-
3216-
var clientCount = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count;
3217-
for (int i = 0; i < clientCount; i++)
3218-
{
3219-
var clientId = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
3220-
if (NetworkManager.ServerClientId == clientId || (!serverAuthoritative && clientId == OwnerClientId))
3221-
{
3222-
continue;
3223-
}
3224-
m_CachedNetworkManager.CustomMessagingManager.SendNamedMessage(m_MessageName, clientId, writer, networkDelivery);
3225-
}
3226-
}
3227-
messagePayload.Seek(currentPosition);
3228-
}
3229-
3230-
/// <summary>
3231-
/// Sends <see cref="NetworkTransformState"/> named message updates by the authority of the transform
3162+
/// Invoked by the authoritative instance to sends a <see cref="NetworkTransformMessage"/> containing the <see cref="NetworkTransformState"/>
32323163
/// </summary>
32333164
private void UpdateTransformState()
32343165
{
@@ -3248,7 +3179,12 @@ private void UpdateTransformState()
32483179
}
32493180
var customMessageManager = m_CachedNetworkManager.CustomMessagingManager;
32503181

3251-
var writer = new FastBufferWriter(128, Allocator.Temp);
3182+
var networkTransformMessage = new NetworkTransformMessage()
3183+
{
3184+
NetworkObjectId = NetworkObjectId,
3185+
NetworkBehaviourId = NetworkBehaviourId,
3186+
State = m_LocalAuthoritativeNetworkState
3187+
};
32523188

32533189
// Determine what network delivery method to use:
32543190
// When to send reliable packets:
@@ -3259,32 +3195,32 @@ private void UpdateTransformState()
32593195
| m_LocalAuthoritativeNetworkState.UnreliableFrameSync | m_LocalAuthoritativeNetworkState.SynchronizeBaseHalfFloat
32603196
? NetworkDelivery.ReliableSequenced : NetworkDelivery.UnreliableSequenced;
32613197

3262-
using (writer)
3198+
// Server-host always sends updates to all clients (but itself)
3199+
if (IsServer)
32633200
{
3264-
writer.WriteNetworkSerializable(m_LocalAuthoritativeNetworkState);
3265-
// Server-host always sends updates to all clients (but itself)
3266-
if (IsServer)
3201+
var clientCount = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count;
3202+
for (int i = 0; i < clientCount; i++)
32673203
{
3268-
var clientCount = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList.Count;
3269-
for (int i = 0; i < clientCount; i++)
3204+
var clientId = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
3205+
if (NetworkManager.ServerClientId == clientId)
32703206
{
3271-
var clientId = m_CachedNetworkManager.ConnectionManager.ConnectedClientsList[i].ClientId;
3272-
if (NetworkManager.ServerClientId == clientId)
3273-
{
3274-
continue;
3275-
}
3276-
customMessageManager.SendNamedMessage(m_MessageName, clientId, writer, networkDelivery);
3207+
continue;
32773208
}
3209+
if (!NetworkObject.Observers.Contains(clientId))
3210+
{
3211+
continue;
3212+
}
3213+
NetworkManager.MessageManager.SendMessage(ref networkTransformMessage, networkDelivery, clientId);
32783214
}
3279-
else
3280-
{
3281-
// Clients (owner authoritative) send messages to the server-host
3282-
customMessageManager.SendNamedMessage(m_MessageName, NetworkManager.ServerClientId, writer, networkDelivery);
3283-
}
3215+
}
3216+
else
3217+
{
3218+
// Clients (owner authoritative) send messages to the server-host
3219+
NetworkManager.MessageManager.SendMessage(ref networkTransformMessage, networkDelivery, NetworkManager.ServerClientId);
32843220
}
32853221
}
32863222

3287-
3223+
#region Network Tick Registration and Handling
32883224
private static Dictionary<NetworkManager, NetworkTransformTickRegistration> s_NetworkTickRegistration = new Dictionary<NetworkManager, NetworkTransformTickRegistration>();
32893225

32903226
private static void RemoveTickUpdate(NetworkManager networkManager)
@@ -3394,6 +3330,8 @@ private static void DeregisterForTickUpdate(NetworkTransform networkTransform)
33943330
}
33953331
}
33963332
}
3333+
3334+
#endregion
33973335
}
33983336

33993337
internal interface INetworkTransformLogStateEntry

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal static class CodeGenHelpers
2121
public const string NetcodeModuleName = "Unity.Netcode.Runtime.dll";
2222

2323
public const string RuntimeAssemblyName = "Unity.Netcode.Runtime";
24+
public const string ComponentsAssemblyName = "Unity.Netcode.Components";
2425

2526
public static readonly string NetworkBehaviour_FullName = typeof(NetworkBehaviour).FullName;
2627
public static readonly string INetworkMessage_FullName = typeof(INetworkMessage).FullName;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal sealed class INetworkMessageILPP : ILPPInterface
1717
{
1818
public override ILPPInterface GetInstance() => this;
1919

20-
public override bool WillProcess(ICompiledAssembly compiledAssembly) => compiledAssembly.Name == CodeGenHelpers.RuntimeAssemblyName;
20+
public override bool WillProcess(ICompiledAssembly compiledAssembly) => compiledAssembly.Name == CodeGenHelpers.RuntimeAssemblyName || compiledAssembly.Name == CodeGenHelpers.ComponentsAssemblyName;
2121

2222
private readonly List<DiagnosticMessage> m_Diagnostics = new List<DiagnosticMessage>();
2323

0 commit comments

Comments
 (0)