Skip to content

Commit 13be3cc

Browse files
committed
Merge branch 'develop-2.0.0' into chore/simplify-accessors-network-object
2 parents ae5c41a + 8f99d40 commit 13be3cc

File tree

8 files changed

+153
-146
lines changed

8 files changed

+153
-146
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1313

1414
### Changed
1515

16+
- Improve performance of `NetworkObject`. (#3820)
1617
- If the Unity Transport Disconnect Timeout is set to 0 in the Editor, the timeout will be entirely disabled. (#3810)
1718

1819
### Deprecated
@@ -23,7 +24,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2324

2425
### Fixed
2526

26-
- Fixed issue where maxCapacity calculation overflows if a developer sets a very, very high (large) m_DisconnectTimeoutMS in the Editor for Unity Transport. (#3810)
27+
- Fixed an integer overflow that occurred when configuring a large disconnect timeout with Unity Transport. (#3810)
2728

2829
### Security
2930

com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ internal void ApprovedPlayerSpawn(ulong clientId, uint playerPrefabHash)
11191119

11201120
var message = new CreateObjectMessage
11211121
{
1122-
ObjectInfo = ConnectedClients[clientId].PlayerObject.GetMessageSceneObject(clientPair.Key),
1122+
ObjectInfo = ConnectedClients[clientId].PlayerObject.Serialize(clientPair.Key),
11231123
IncludesSerializedObject = true,
11241124
};
11251125

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

Lines changed: 82 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2889,87 +2889,91 @@ public NetworkBehaviour GetNetworkBehaviourAtOrderIndex(ushort index)
28892889
return ChildNetworkBehaviours[index];
28902890
}
28912891

2892-
internal struct SceneObject
2892+
/// <summary>
2893+
/// The serialized representation of a NetworkObject.
2894+
/// Used for synchronizing clients on NetworkObject spawn.
2895+
/// </summary>
2896+
internal struct SerializedObject
28932897
{
2894-
private ushort m_BitField;
28952898
public uint Hash;
28962899
public ulong NetworkObjectId;
28972900
public ulong OwnerClientId;
28982901
public ushort OwnershipFlags;
28992902

2900-
public bool IsPlayerObject
2901-
{
2902-
get => ByteUtility.GetBit(m_BitField, 0);
2903-
set => ByteUtility.SetBit(ref m_BitField, 0, value);
2904-
}
2905-
public bool HasParent
2906-
{
2907-
get => ByteUtility.GetBit(m_BitField, 1);
2908-
set => ByteUtility.SetBit(ref m_BitField, 1, value);
2909-
}
2910-
public bool IsSceneObject
2911-
{
2912-
get => ByteUtility.GetBit(m_BitField, 2);
2913-
set => ByteUtility.SetBit(ref m_BitField, 2, value);
2914-
}
2915-
public bool HasTransform
2916-
{
2917-
get => ByteUtility.GetBit(m_BitField, 3);
2918-
set => ByteUtility.SetBit(ref m_BitField, 3, value);
2919-
}
2903+
private const ushort k_IsPlayerObject = 0x001;
2904+
private const ushort k_HasParent = 0x002;
2905+
private const ushort k_IsSceneObject = 0x004;
2906+
private const ushort k_HasTransform = 0x008;
2907+
private const ushort k_IsLatestParentSet = 0x010;
2908+
private const ushort k_WorldPositionStays = 0x020;
2909+
private const ushort k_DestroyWithScene = 0x040;
2910+
private const ushort k_DontDestroyWithOwner = 0x080;
2911+
private const ushort k_HasOwnershipFlags = 0x100;
2912+
private const ushort k_SyncObservers = 0x200;
2913+
private const ushort k_SpawnWithObservers = 0x400;
2914+
private const ushort k_HasInstantiationData = 0x800;
29202915

2921-
public bool IsLatestParentSet
2922-
{
2923-
get => ByteUtility.GetBit(m_BitField, 4);
2924-
set => ByteUtility.SetBit(ref m_BitField, 4, value);
2925-
}
2916+
public bool IsPlayerObject;
2917+
public bool HasParent;
2918+
public bool IsSceneObject;
2919+
public bool HasTransform;
29262920

2927-
public bool WorldPositionStays
2928-
{
2929-
get => ByteUtility.GetBit(m_BitField, 5);
2930-
set => ByteUtility.SetBit(ref m_BitField, 5, value);
2931-
}
2921+
public bool IsLatestParentSet;
2922+
2923+
public bool WorldPositionStays;
29322924

29332925
/// <summary>
29342926
/// Even though the server sends notifications for NetworkObjects that get
29352927
/// destroyed when a scene is unloaded, we want to synchronize this so
29362928
/// the client side can use it as part of a filter for automatically migrating
29372929
/// to the current active scene when its scene is unloaded. (only for dynamically spawned)
29382930
/// </summary>
2939-
public bool DestroyWithScene
2940-
{
2941-
get => ByteUtility.GetBit(m_BitField, 6);
2942-
set => ByteUtility.SetBit(ref m_BitField, 6, value);
2943-
}
2931+
public bool DestroyWithScene;
29442932

2945-
public bool DontDestroyWithOwner
2946-
{
2947-
get => ByteUtility.GetBit(m_BitField, 7);
2948-
set => ByteUtility.SetBit(ref m_BitField, 7, value);
2949-
}
2933+
public bool DontDestroyWithOwner;
29502934

2951-
public bool HasOwnershipFlags
2952-
{
2953-
get => ByteUtility.GetBit(m_BitField, 8);
2954-
set => ByteUtility.SetBit(ref m_BitField, 8, value);
2955-
}
2935+
public bool HasOwnershipFlags;
29562936

2957-
public bool SyncObservers
2958-
{
2959-
get => ByteUtility.GetBit(m_BitField, 9);
2960-
set => ByteUtility.SetBit(ref m_BitField, 9, value);
2961-
}
2937+
public bool SyncObservers;
29622938

2963-
public bool SpawnWithObservers
2939+
public bool SpawnWithObservers;
2940+
2941+
public bool HasInstantiationData;
2942+
2943+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2944+
internal ushort GetBitsetRepresentation()
29642945
{
2965-
get => ByteUtility.GetBit(m_BitField, 10);
2966-
set => ByteUtility.SetBit(ref m_BitField, 10, value);
2946+
ushort bitset = 0;
2947+
if (IsPlayerObject) { bitset |= k_IsPlayerObject; };
2948+
if (HasParent) { bitset |= k_HasParent; };
2949+
if (IsSceneObject) { bitset |= k_IsSceneObject; };
2950+
if (HasTransform) { bitset |= k_HasTransform; };
2951+
if (IsLatestParentSet) { bitset |= k_IsLatestParentSet; };
2952+
if (WorldPositionStays) { bitset |= k_WorldPositionStays; };
2953+
if (DestroyWithScene) { bitset |= k_DestroyWithScene; };
2954+
if (DontDestroyWithOwner) { bitset |= k_DontDestroyWithOwner; };
2955+
if (HasOwnershipFlags) { bitset |= k_HasOwnershipFlags; };
2956+
if (SyncObservers) { bitset |= k_SyncObservers; };
2957+
if (SpawnWithObservers) { bitset |= k_SpawnWithObservers; };
2958+
if (HasInstantiationData) { bitset |= k_HasInstantiationData; };
2959+
return bitset;
29672960
}
29682961

2969-
public bool HasInstantiationData
2962+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2963+
internal void SetStateFromBitset(ushort bitset)
29702964
{
2971-
get => ByteUtility.GetBit(m_BitField, 11);
2972-
set => ByteUtility.SetBit(ref m_BitField, 11, value);
2965+
IsPlayerObject = (bitset & k_IsPlayerObject) != 0;
2966+
HasParent = (bitset & k_HasParent) != 0;
2967+
IsSceneObject = (bitset & k_IsSceneObject) != 0;
2968+
HasTransform = (bitset & k_HasTransform) != 0;
2969+
IsLatestParentSet = (bitset & k_IsLatestParentSet) != 0;
2970+
WorldPositionStays = (bitset & k_WorldPositionStays) != 0;
2971+
DestroyWithScene = (bitset & k_DestroyWithScene) != 0;
2972+
DontDestroyWithOwner = (bitset & k_DontDestroyWithOwner) != 0;
2973+
HasOwnershipFlags = (bitset & k_HasOwnershipFlags) != 0;
2974+
SyncObservers = (bitset & k_SyncObservers) != 0;
2975+
SpawnWithObservers = (bitset & k_SpawnWithObservers) != 0;
2976+
HasInstantiationData = (bitset & k_HasInstantiationData) != 0;
29732977
}
29742978

29752979
// When handling the initial synchronization of NetworkObjects,
@@ -3008,7 +3012,8 @@ public void Serialize(FastBufferWriter writer)
30083012
HasOwnershipFlags = true;
30093013
SpawnWithObservers = OwnerObject.SpawnWithObservers;
30103014
}
3011-
writer.WriteValueSafe(m_BitField);
3015+
3016+
writer.WriteValueSafe(GetBitsetRepresentation());
30123017
writer.WriteValueSafe(Hash);
30133018
BytePacker.WriteValueBitPacked(writer, NetworkObjectId);
30143019
BytePacker.WriteValueBitPacked(writer, OwnerClientId);
@@ -3088,7 +3093,8 @@ public void Serialize(FastBufferWriter writer)
30883093

30893094
public void Deserialize(FastBufferReader reader)
30903095
{
3091-
reader.ReadValueSafe(out m_BitField);
3096+
reader.ReadValueSafe(out ushort bitset);
3097+
SetStateFromBitset(bitset);
30923098
reader.ReadValueSafe(out Hash);
30933099
ByteUnpacker.ReadValueBitPacked(reader, out NetworkObjectId);
30943100
ByteUnpacker.ReadValueBitPacked(reader, out OwnerClientId);
@@ -3216,9 +3222,9 @@ internal void SynchronizeNetworkBehaviours<T>(ref BufferSerializer<T> serializer
32163222
}
32173223
}
32183224

3219-
internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager.ServerClientId, bool syncObservers = false)
3225+
internal SerializedObject Serialize(ulong targetClientId = NetworkManager.ServerClientId, bool syncObservers = false)
32203226
{
3221-
var obj = new SceneObject
3227+
var obj = new SerializedObject
32223228
{
32233229
HasParent = transform.parent != null,
32243230
WorldPositionStays = m_CachedWorldPositionStays,
@@ -3272,7 +3278,7 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
32723278
syncScaleLocalSpaceRelative = obj.HasParent;
32733279
}
32743280

3275-
obj.Transform = new SceneObject.TransformData
3281+
obj.Transform = new SerializedObject.TransformData
32763282
{
32773283
// If we are parented and we have the m_CachedWorldPositionStays disabled, then use local space
32783284
// values as opposed world space values.
@@ -3291,35 +3297,35 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
32913297
}
32923298

32933299
/// <summary>
3294-
/// Used to deserialize a serialized scene object which occurs
3300+
/// Used to deserialize a serialized <see cref="SerializedObject"/> which occurs
32953301
/// when the client is approved or during a scene transition
32963302
/// </summary>
3297-
/// <param name="sceneObject">Deserialized scene object data</param>
3303+
/// <param name="serializedObject">Deserialized scene object data</param>
32983304
/// <param name="reader">FastBufferReader for the NetworkVariable data</param>
32993305
/// <param name="networkManager">NetworkManager instance</param>
33003306
/// <param name="invokedByMessage">will be true if invoked by CreateObjectMessage</param>
33013307
/// <returns>The deserialized NetworkObject or null if deserialization failed</returns>
3302-
internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBufferReader reader, NetworkManager networkManager, bool invokedByMessage = false)
3308+
internal static NetworkObject Deserialize(in SerializedObject serializedObject, FastBufferReader reader, NetworkManager networkManager, bool invokedByMessage = false)
33033309
{
3304-
var endOfSynchronizationData = reader.Position + sceneObject.SynchronizationDataSize;
3310+
var endOfSynchronizationData = reader.Position + serializedObject.SynchronizationDataSize;
33053311

33063312
byte[] instantiationData = null;
3307-
if (sceneObject.HasInstantiationData)
3313+
if (serializedObject.HasInstantiationData)
33083314
{
33093315
reader.ReadValueSafe(out instantiationData);
33103316
}
33113317

33123318

33133319
// Attempt to create a local NetworkObject
3314-
var networkObject = networkManager.SpawnManager.CreateLocalNetworkObject(sceneObject, instantiationData);
3320+
var networkObject = networkManager.SpawnManager.CreateLocalNetworkObject(serializedObject, instantiationData);
33153321

33163322

33173323
if (networkObject == null)
33183324
{
33193325
// Log the error that the NetworkObject failed to construct
33203326
if (networkManager.LogLevel <= LogLevel.Normal)
33213327
{
3322-
NetworkLog.LogError($"Failed to spawn {nameof(NetworkObject)} for Hash {sceneObject.Hash}.");
3328+
NetworkLog.LogError($"Failed to spawn {nameof(NetworkObject)} for Hash {serializedObject.Hash}.");
33233329
}
33243330

33253331
try
@@ -3340,7 +3346,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33403346

33413347
// This will get set again when the NetworkObject is spawned locally, but we set it here ahead of spawning
33423348
// in order to be able to determine which NetworkVariables the client will be allowed to read.
3343-
networkObject.OwnerClientId = sceneObject.OwnerClientId;
3349+
networkObject.OwnerClientId = serializedObject.OwnerClientId;
33443350

33453351
// Special Case: Invoke NetworkBehaviour.OnPreSpawn methods here before SynchronizeNetworkBehaviours
33463352
networkObject.InvokeBehaviourNetworkPreSpawn();
@@ -3368,7 +3374,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33683374
// being told we do not have a parent, then we want to clear the latest parent so it is not automatically
33693375
// "re-parented" to the original parent. This can happen if not unloading the scene and the parenting of
33703376
// the in-scene placed Networkobject changes several times over different sessions.
3371-
if (sceneObject.IsSceneObject && !sceneObject.HasParent && networkObject.m_LatestParent.HasValue)
3377+
if (serializedObject.IsSceneObject && !serializedObject.HasParent && networkObject.m_LatestParent.HasValue)
33723378
{
33733379
networkObject.m_LatestParent = null;
33743380
}
@@ -3381,19 +3387,19 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33813387

33823388
// Invoke the non-authority local spawn method
33833389
// (It also invokes post spawn and handles processing derferred messages)
3384-
networkManager.SpawnManager.NonAuthorityLocalSpawn(networkObject, sceneObject, sceneObject.DestroyWithScene);
3390+
networkManager.SpawnManager.NonAuthorityLocalSpawn(networkObject, serializedObject, serializedObject.DestroyWithScene);
33853391

3386-
if (sceneObject.SyncObservers)
3392+
if (serializedObject.SyncObservers)
33873393
{
3388-
foreach (var observer in sceneObject.Observers)
3394+
foreach (var observer in serializedObject.Observers)
33893395
{
33903396
networkObject.Observers.Add(observer);
33913397
}
33923398
}
33933399

33943400
if (networkManager.DistributedAuthorityMode)
33953401
{
3396-
networkObject.SpawnWithObservers = sceneObject.SpawnWithObservers;
3402+
networkObject.SpawnWithObservers = serializedObject.SpawnWithObservers;
33973403
}
33983404

33993405
// If this was not invoked by a message handler, we are in distributed authority mode, and we are spawning with observers or

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ public void Serialize(FastBufferWriter writer, int targetVersion)
160160
{
161161
sobj.Observers.Add(OwnerClientId);
162162
// In distributed authority mode, we send the currently known observers of each NetworkObject to the client being synchronized.
163-
var sceneObject = sobj.GetMessageSceneObject(OwnerClientId, IsDistributedAuthority);
164-
sceneObject.Serialize(writer);
163+
var serializedObject = sobj.Serialize(OwnerClientId, IsDistributedAuthority);
164+
serializedObject.Serialize(writer);
165165
++sceneObjectCount;
166166
}
167167
}
@@ -342,9 +342,9 @@ public void Handle(ref NetworkContext context)
342342
// to create a list to hold the data. This is a breach of convention for performance reasons.
343343
for (ushort i = 0; i < sceneObjectCount; i++)
344344
{
345-
var sceneObject = new NetworkObject.SceneObject();
346-
sceneObject.Deserialize(m_ReceivedSceneObjectData);
347-
NetworkObject.AddSceneObject(sceneObject, m_ReceivedSceneObjectData, networkManager);
345+
var serializedObject = new NetworkObject.SerializedObject();
346+
serializedObject.Deserialize(m_ReceivedSceneObjectData);
347+
NetworkObject.Deserialize(serializedObject, m_ReceivedSceneObjectData, networkManager);
348348
}
349349

350350
if (networkManager.AutoSpawnPlayerPrefabClientSide)

0 commit comments

Comments
 (0)