Skip to content

Commit 8df4e98

Browse files
authored
chore: Merge release/1.4.0 back to develop (#2527)
1 parent 9e45386 commit 8df4e98

File tree

8 files changed

+148
-15
lines changed

8 files changed

+148
-15
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ Additional documentation and release notes are available at [Multiplayer Documen
2020

2121
## Changed
2222

23-
## [1.4.0]
23+
24+
## [1.4.0] - 2023-04-10
2425

2526
### Added
2627

2728
- Added a way to access the GlobalObjectIdHash via PrefabIdHash for use in the Connection Approval Callback. (#2437)
29+
- Added `OnServerStarted` and `OnServerStopped` events that will trigger only on the server (or host player) to notify that the server just started or is no longer active (#2420)
30+
- Added `OnClientStarted` and `OnClientStopped` events that will trigger only on the client (or host player) to notify that the client just started or is no longer active (#2420)
2831
- Added `NetworkTransform.UseHalfFloatPrecision` property that, when enabled, will use half float values for position, rotation, and scale. This yields a 50% bandwidth savings a the cost of precision. (#2388)
2932
- Added `NetworkTransform.UseQuaternionSynchronization` property that, when enabled, will synchronize the entire quaternion. (#2388)
3033
- Added `NetworkTransform.UseQuaternionCompression` property that, when enabled, will use a smallest three implementation reducing a full quaternion synchronization update to the size of an unsigned integer. (#2388)
@@ -41,22 +44,23 @@ Additional documentation and release notes are available at [Multiplayer Documen
4144
- Added `NetworkSceneManager.ActiveSceneSynchronizationEnabled` property, disabled by default, that enables client synchronization of server-side active scene changes. (#2383)
4245
- Added `NetworkObject.ActiveSceneSynchronization`, disabled by default, that will automatically migrate a `NetworkObject` to a newly assigned active scene. (#2383)
4346
- Added `NetworkObject.SceneMigrationSynchronization`, enabled by default, that will synchronize client(s) when a `NetworkObject` is migrated into a new scene on the server side via `SceneManager.MoveGameObjectToScene`. (#2383)
44-
- Added `OnServerStarted` and `OnServerStopped` events that will trigger only on the server (or host player) to notify that the server just started or is no longer active (#2420)
45-
- Added `OnClientStarted` and `OnClientStopped` events that will trigger only on the client (or host player) to notify that the client just started or is no longer active (#2420)
4647

4748
### Changed
4849

50+
- Made sure the `CheckObjectVisibility` delegate is checked and applied, upon `NetworkShow` attempt. Found while supporting (#2454), although this is not a fix for this (already fixed) issue. (#2463)
4951
- Changed `NetworkTransform` authority handles delta checks on each new network tick and no longer consumes processing cycles checking for deltas for all frames in-between ticks. (#2388)
5052
- Changed the `NetworkTransformState` structure is now public and now has public methods that provide access to key properties of the `NetworkTransformState` structure. (#2388)
5153
- Changed `NetworkTransform` interpolation adjusts its interpolation "ticks ago" to be 2 ticks latent if it is owner authoritative and the instance is not the server or 1 tick latent if the instance is the server and/or is server authoritative. (#2388)
5254
- Updated `NetworkSceneManager` to migrate dynamically spawned `NetworkObject`s with `DestroyWithScene` set to false into the active scene if their current scene is unloaded. (#2383)
5355
- Updated the server to synchronize its local `NetworkSceneManager.ClientSynchronizationMode` during the initial client synchronization. (#2383)
54-
- Made sure the `CheckObjectVisibility` delegate is checked and applied, upon `NetworkShow` attempt. Found while supporting (#2454), although this is not a fix for this (already fixed) issue. (#2463)
5556

5657
### Fixed
5758

59+
- Fixed issue where during client synchronization the synchronizing client could receive a ObjectSceneChanged message before the client-side NetworkObject instance had been instantiated and spawned. (#2502)
60+
- Fixed issue where `NetworkAnimator` was building client RPC parameters to exclude the host from sending itself messages but was not including it in the ClientRpc parameters. (#2492)
5861
- Fixed issue where `NetworkAnimator` was not properly detecting and synchronizing cross fade initiated transitions. (#2481)
5962
- Fixed issue where `NetworkAnimator` was not properly synchronizing animation state updates. (#2481)
63+
- Fixed float NetworkVariables not being rendered properly in the inspector of NetworkObjects. (#2441)
6064
- Fixed an issue where Named Message Handlers could remove themselves causing an exception when the metrics tried to access the name of the message.(#2426)
6165
- Fixed registry of public `NetworkVariable`s in derived `NetworkBehaviour`s (#2423)
6266
- Fixed issue where runtime association of `Animator` properties to `AnimationCurve`s would cause `NetworkAnimator` to attempt to update those changes. (#2416)
@@ -65,7 +69,6 @@ Additional documentation and release notes are available at [Multiplayer Documen
6569
- Fixed issue where `NetworkTransform` was not setting the teleport flag when the `NetworkTransform.InLocalSpace` value changed. This issue only impacted `NetworkTransform` when interpolation was enabled. (#2388)
6670
- Fixed issue when the `NetworkSceneManager.ClientSynchronizationMode` is `LoadSceneMode.Additive` and the server changes the currently active scene prior to a client connecting then upon a client connecting and being synchronized the NetworkSceneManager would clear its internal ScenePlacedObjects list that could already be populated. (#2383)
6771
- Fixed issue where a client would load duplicate scenes of already preloaded scenes during the initial client synchronization and `NetworkSceneManager.ClientSynchronizationMode` was set to `LoadSceneMode.Additive`. (#2383)
68-
- Fixed float NetworkVariables not being rendered properly in the inspector of NetworkObjects. (#2441)
6972

7073
## [1.3.1] - 2023-03-27
7174

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ internal void CheckForAnimatorChanges()
920920
m_ClientSendList.AddRange(NetworkManager.ConnectedClientsIds);
921921
m_ClientSendList.Remove(NetworkManager.LocalClientId);
922922
m_ClientRpcParams.Send.TargetClientIds = m_ClientSendList;
923-
SendAnimStateClientRpc(m_AnimationMessage);
923+
SendAnimStateClientRpc(m_AnimationMessage, m_ClientRpcParams);
924924
}
925925
}
926926
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2003,7 +2003,7 @@ private void ApplyTeleportingState(NetworkTransformState newState)
20032003

20042004
if (Interpolate)
20052005
{
2006-
UpdatePositionInterpolator(currentPosition, sentTime);
2006+
UpdatePositionInterpolator(currentPosition, sentTime, true);
20072007
}
20082008

20092009
}

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,11 @@ private void HandleClientSceneEvent(uint sceneEventId)
20582058
ClientId = NetworkManager.LocalClientId, // Client sent this to the server
20592059
});
20602060

2061+
// Process any SceneEventType.ObjectSceneChanged messages that
2062+
// were deferred while synchronizing and migrate the associated
2063+
// NetworkObjects to their newly assigned scenes.
2064+
sceneEventData.ProcessDeferredObjectSceneChangedEvents();
2065+
20612066
// Only if PostSynchronizationSceneUnloading is set and we are running in client synchronization
20622067
// mode additive do we unload any remaining scene that was not synchronized (otherwise any loaded
20632068
// scene not synchronized by the server will remain loaded)
@@ -2412,6 +2417,7 @@ internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject)
24122417
}
24132418

24142419
// Don't notify if a scene event is in progress
2420+
// Note: This does not apply to SceneEventType.Synchronize since synchronization isn't a global connected client event.
24152421
foreach (var sceneEventEntry in SceneEventProgressTracking)
24162422
{
24172423
if (!sceneEventEntry.Value.HasTimedOut() && sceneEventEntry.Value.Status == SceneEventProgressStatus.Started)
@@ -2430,8 +2436,10 @@ internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject)
24302436

24312437
/// <summary>
24322438
/// Invoked by clients when processing a <see cref="SceneEventType.ObjectSceneChanged"/> event
2439+
/// or invoked by <see cref="SceneEventData.ProcessDeferredObjectSceneChangedEvents"/> when a client finishes
2440+
/// synchronization.
24332441
/// </summary>
2434-
private void MigrateNetworkObjectsIntoScenes()
2442+
internal void MigrateNetworkObjectsIntoScenes()
24352443
{
24362444
try
24372445
{
@@ -2476,5 +2484,13 @@ internal void CheckForAndSendNetworkObjectSceneChanged()
24762484
SendSceneEventData(sceneEvent.SceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != NetworkManager.ServerClientId).ToArray());
24772485
EndSceneEvent(sceneEvent.SceneEventId);
24782486
}
2487+
2488+
// Used to handle client-side scene migration messages received while
2489+
// a client is synchronizing
2490+
internal struct DeferredObjectsMovedEvent
2491+
{
2492+
internal Dictionary<int, List<ulong>> ObjectsMigratedTable;
2493+
}
2494+
internal List<DeferredObjectsMovedEvent> DeferredObjectsMovedEvents = new List<DeferredObjectsMovedEvent>();
24792495
}
24802496
}

com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,15 @@ internal void Deserialize(FastBufferReader reader)
575575

576576
if (SceneEventType == SceneEventType.ObjectSceneChanged)
577577
{
578-
DeserializeObjectsMovedIntoNewScene(reader);
578+
// Defer these scene event types if a client hasn't finished synchronizing
579+
if (!m_NetworkManager.IsConnectedClient)
580+
{
581+
DeferObjectsMovedIntoNewScene(reader);
582+
}
583+
else
584+
{
585+
DeserializeObjectsMovedIntoNewScene(reader);
586+
}
579587
return;
580588
}
581589

@@ -1036,14 +1044,94 @@ private void DeserializeObjectsMovedIntoNewScene(FastBufferReader reader)
10361044
reader.ReadValueSafe(out networkObjectId);
10371045
if (!spawnManager.SpawnedObjects.ContainsKey(networkObjectId))
10381046
{
1039-
throw new Exception($"[Object Scene Migration] Trying to synchronize NetworkObjectId ({networkObjectId}) but it no longer exists!");
1047+
NetworkLog.LogError($"[Object Scene Migration] Trying to synchronize NetworkObjectId ({networkObjectId}) but it was not spawned or no longer exists!!");
1048+
continue;
10401049
}
1050+
// Add NetworkObject scene migration to ObjectsMigratedIntoNewScene dictionary that is processed
1051+
//
10411052
sceneManager.ObjectsMigratedIntoNewScene[sceneHandle].Add(spawnManager.SpawnedObjects[networkObjectId]);
10421053
}
10431054
}
10441055
}
10451056

10461057

1058+
/// <summary>
1059+
/// While a client is synchronizing ObjectSceneChanged messages could be received.
1060+
/// This defers any ObjectSceneChanged message processing to occur after the client
1061+
/// has completed synchronization to assure the associated NetworkObjects being
1062+
/// migrated to a new scene are instantiated and spawned.
1063+
/// </summary>
1064+
private void DeferObjectsMovedIntoNewScene(FastBufferReader reader)
1065+
{
1066+
var sceneManager = m_NetworkManager.SceneManager;
1067+
var spawnManager = m_NetworkManager.SpawnManager;
1068+
var numberOfScenes = 0;
1069+
var sceneHandle = 0;
1070+
var objectCount = 0;
1071+
var networkObjectId = (ulong)0;
1072+
1073+
var deferredObjectsMovedEvent = new NetworkSceneManager.DeferredObjectsMovedEvent()
1074+
{
1075+
ObjectsMigratedTable = new Dictionary<int, List<ulong>>()
1076+
};
1077+
1078+
reader.ReadValueSafe(out numberOfScenes);
1079+
for (int i = 0; i < numberOfScenes; i++)
1080+
{
1081+
reader.ReadValueSafe(out sceneHandle);
1082+
deferredObjectsMovedEvent.ObjectsMigratedTable.Add(sceneHandle, new List<ulong>());
1083+
reader.ReadValueSafe(out objectCount);
1084+
for (int j = 0; j < objectCount; j++)
1085+
{
1086+
reader.ReadValueSafe(out networkObjectId);
1087+
deferredObjectsMovedEvent.ObjectsMigratedTable[sceneHandle].Add(networkObjectId);
1088+
}
1089+
}
1090+
sceneManager.DeferredObjectsMovedEvents.Add(deferredObjectsMovedEvent);
1091+
}
1092+
1093+
internal void ProcessDeferredObjectSceneChangedEvents()
1094+
{
1095+
var sceneManager = m_NetworkManager.SceneManager;
1096+
var spawnManager = m_NetworkManager.SpawnManager;
1097+
if (sceneManager.DeferredObjectsMovedEvents.Count == 0)
1098+
{
1099+
return;
1100+
}
1101+
foreach (var objectsMovedEvent in sceneManager.DeferredObjectsMovedEvents)
1102+
{
1103+
foreach (var keyEntry in objectsMovedEvent.ObjectsMigratedTable)
1104+
{
1105+
if (!sceneManager.ObjectsMigratedIntoNewScene.ContainsKey(keyEntry.Key))
1106+
{
1107+
sceneManager.ObjectsMigratedIntoNewScene.Add(keyEntry.Key, new List<NetworkObject>());
1108+
}
1109+
foreach (var objectId in keyEntry.Value)
1110+
{
1111+
if (!spawnManager.SpawnedObjects.ContainsKey(objectId))
1112+
{
1113+
NetworkLog.LogWarning($"[Deferred][Object Scene Migration] Trying to synchronize NetworkObjectId ({objectId}) but it was not spawned or no longer exists!");
1114+
continue;
1115+
}
1116+
var networkObject = spawnManager.SpawnedObjects[objectId];
1117+
if (!sceneManager.ObjectsMigratedIntoNewScene[keyEntry.Key].Contains(networkObject))
1118+
{
1119+
sceneManager.ObjectsMigratedIntoNewScene[keyEntry.Key].Add(networkObject);
1120+
}
1121+
}
1122+
}
1123+
objectsMovedEvent.ObjectsMigratedTable.Clear();
1124+
}
1125+
1126+
sceneManager.DeferredObjectsMovedEvents.Clear();
1127+
1128+
// If there are any pending objects to migrate, then migrate them
1129+
if (sceneManager.ObjectsMigratedIntoNewScene.Count > 0)
1130+
{
1131+
sceneManager.MigrateNetworkObjectsIntoScenes();
1132+
}
1133+
}
1134+
10471135
/// <summary>
10481136
/// Used to release the pooled network buffer
10491137
/// </summary>

com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -930,8 +930,9 @@ public void TeleportTest([Values] Interpolation interpolation, [Values] Precisio
930930
var success = WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed && m_NonAuthoritativeTransform.StateUpdated);
931931
Assert.True(success, $"[Teleport] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed}) or state to be updated ({m_NonAuthoritativeTransform.StateUpdated})!");
932932

933-
success = WaitForConditionOrTimeOutWithTimeTravel(() => TeleportPositionMatches(nonAuthPosition));
934-
Assert.True(success, $"[Timed-Out][Teleport] Timed out waiting for NonAuthoritative position ({m_NonAuthoritativeTransform.GetSpaceRelativePosition()}) to teleport to position {teleportDestination}!");
933+
SimulateOneFrame();
934+
Assert.True(TeleportPositionMatches(nonAuthPosition), $"NonAuthoritative position ({m_NonAuthoritativeTransform.GetSpaceRelativePosition()}) is not the same as the destination position {teleportDestination}!");
935+
935936
var targetDistance = 0.0f;
936937
if (!Approximately(m_DetectedPotentialInterpolatedTeleport, 0.0f))
937938
{

com.unity.netcode.gameobjects/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "com.unity.netcode.gameobjects",
33
"displayName": "Netcode for GameObjects",
44
"description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.",
5-
"version": "1.3.1",
5+
"version": "1.4.0",
66
"unity": "2020.3",
77
"dependencies": {
88
"com.unity.nuget.mono-cecil": "1.10.1",

testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkObjectSceneMigrationTests.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ private bool VerifySpawnedObjectsMigrated()
157157
return true;
158158
}
159159

160+
private const int k_MaxObjectsToSpawn = 9;
160161
/// <summary>
161162
/// Integration test to verify that migrating NetworkObjects
162163
/// into different scenes (in the same frame) is synchronized
@@ -167,7 +168,7 @@ private bool VerifySpawnedObjectsMigrated()
167168
public IEnumerator MigrateIntoNewSceneTest()
168169
{
169170
// Spawn 9 NetworkObject instances
170-
for (int i = 0; i < 9; i++)
171+
for (int i = 0; i < k_MaxObjectsToSpawn; i++)
171172
{
172173
var serverInstance = Object.Instantiate(m_TestPrefab);
173174
var serverNetworkObject = serverInstance.GetComponent<NetworkObject>();
@@ -204,12 +205,36 @@ public IEnumerator MigrateIntoNewSceneTest()
204205
yield return WaitForConditionOrTimeOut(VerifySpawnedObjectsMigrated);
205206
AssertOnTimeout($"Timed out waiting for all clients to migrate all NetworkObjects into the appropriate scenes!");
206207

207-
// Verify that a late joining client synchronizes properly
208+
// Register for the server-side client synchronization so we can send an object scene migration event at the same time
209+
// the new client begins to synchronize
210+
m_ServerNetworkManager.SceneManager.OnSynchronize += SceneManager_OnSynchronize;
211+
212+
// Verify that a late joining client synchronizes properly even while new scene migrations occur
213+
// during its synchronization
208214
yield return CreateAndStartNewClient();
209215
yield return WaitForConditionOrTimeOut(VerifySpawnedObjectsMigrated);
216+
210217
AssertOnTimeout($"[Late Joined Client] Timed out waiting for all clients to migrate all NetworkObjects into the appropriate scenes!");
211218
}
212219

220+
/// <summary>
221+
/// Migrate objects into other scenes when a client begins synchronization
222+
/// </summary>
223+
/// <param name="clientId"></param>
224+
private void SceneManager_OnSynchronize(ulong clientId)
225+
{
226+
var objectCount = k_MaxObjectsToSpawn - 1;
227+
228+
// Migrate the NetworkObjects into different scenes than they originally were migrated into
229+
foreach (var scene in m_ScenesLoaded)
230+
{
231+
SceneManager.MoveGameObjectToScene(m_ServerSpawnedPrefabInstances[objectCount].gameObject, scene);
232+
SceneManager.MoveGameObjectToScene(m_ServerSpawnedPrefabInstances[objectCount - 1].gameObject, scene);
233+
SceneManager.MoveGameObjectToScene(m_ServerSpawnedPrefabInstances[objectCount - 2].gameObject, scene);
234+
objectCount -= 3;
235+
}
236+
}
237+
213238
/// <summary>
214239
/// Integration test to verify changing the currently active scene
215240
/// will migrate NetworkObjects with ActiveSceneSynchronization set

0 commit comments

Comments
 (0)