Netcode for Entities 1.6.1 released

:package: Netcode for Entities 1.6.1 is now live! :package:

Hey everyone! We’re back with another batch of updates for Netcode for Entities, and we’re excited to share what the team has been working on. Here’s a quick rundown of the latest features, improvements, and fixes.

First, we’ve made improvements in prediction control with the introduction of two new systems: BeginPredictedSimulationCommandBufferSystem and EndPredictedSimulationCommandBufferSystem. These provide better control over commands within the PredictedSimulationSystemGroup, making prediction workflows more reliable and robust.
Our experimental Host Migration feature has also seen some additional updates on top of the ones introduced in version 1.5.1. We’re continuing to refine this feature to make it better and easier to use for your projects.

Another update involves Ghost Relevancy and Importance Scaling. By combining these two features, we’ve introduced a new fast-path relevancy calculation that ensures efficient bandwidth usage. This should make managing complex multiplayer environments more efficient.

We’ve also added flexibility to Snapshot History Size. With new compiler defines, you can now define smaller GhostSystemConstants.SnapshotHistorySize values, which is perfect for memory-constrained servers. This flexibility is especially useful when scaling up your multiplayer games.

In terms of fixes and improvements, we’ve addressed several areas. Prediction stability has been enhanced, improving ghost spawning and rollback behavior. We’ve also added WebGL support, enabling self-hosting servers for browser-based multiplayer games. Additionally, we’ve resolved serialization issues with buffers and ghost fields, ensuring data integrity.

We’ve introduced analytics into our Tools to better understand which tools are most popular and how they’re being used.
This information will help us make informed decisions about prioritizing improvements and support for our Netcode tools.

We’re excited to bring you these updates and can’t wait to see how they help with your projects :grin:. Let us know if you have any questions or feedback!

Happy Netcoding!


Fixed
  • Behaviour Breaking Change: Incorrect state serialized inside the SnapshotDataBuffer for predicted spawned ghost on the client when spawned inside the prediction loop. The PredictedGhostSpawnSystem is now updated also as part of the prediction loop (inside the PredictedSpawningSystemGroup) to ensure that any predicted spawned ghosts on the client are correctly initialized at the tick they are spawned, and not with partial tick state.
  • Issue where predicted spawned ghosts re-simulated from the wrong tick when configured to rollback to their spawnTick and are spawned inside the prediction loop. They are now restored using the corrected full tick state, rather than the erroneous partial tick state.
  • Enable creating and initializing server drivers when using WebGL to enable self-hosting cases using relay. Many methods were under conditional compilation flags and removed from the WebGL build and not usable outside the editor.
  • All the unmanaged systems present in the FixedStepSimulationSystemGroup that have a direct or indirect update dependency to the PhysicsSystemGroup are now correctly moved to the PredictedFixedStepSimulationSystemGroup. This is a Behaviour Change in respect the previous versions, where all the unmanaged systems continued to stay inside the fixed update group, regardless of the dependency of update order.
  • An issue with Mutiplayer PlayModeTool window, throwing exceptions when docked after a domain reload. The issue was due to because of an access to EditorPrefs and Application.productName while restoring the window state.
  • Issue where, during host migration, ghosts could be migrated with a 0 id and type. Causing various issues when instantiated on the new host.
  • Crash which could happen after host migrations when the server is deploying the host migration data.
  • Issue with prespawn prefab entity list initialization after a host migration, the ordering of the prespawn ghosts could be shifted by one because of the internal PrespawnSceneList entity prefab creation. This would result in invalid ghost type X (expected X+1) off by one style errors.
  • The prediction loop will no longer rollback too many times when one ghost is switched from predicted to interpolated, and later switched back to predicted, when that ghost is the only predicted ghost.
  • If you update multiple packages, create a new section with a new header for the other package.
  • The client packet dump was not being written to the EnablePacketLogging.NetDebugPacketCache field, thus were not usable by users and other netcode call-sites (like the NetworkStreamReceiveSystem).
  • SnapshotHistorySize values below 32 uncovered an issue where a ghost chunk being written would write over its snapshot history entries for currently-in-flight snapshots, leading to a cycle of never being able to fetch a valid baseline, in perpetuity. The fix for this requires us to stall the send of this ghost chunk if the in-flight queue is full, until the in-flight snapshots are assumed to have either arrived or been lost/dropped.
  • Buffer serialization errors caused by incorrect pointer stepping when ghost fields are not present (i.e. surrounding GhostComponentSerializer.State.HasGhostFields).
  • Buffer serialization errors caused by missing change mask invalidation when SendToOwnerType or GhostSendType conditionally prevented sending of the buffer.
  • Readded UsePreSerialization to the GhostAuthoringComponent inspector that was accidentally removed.
Changed
  • Behaviour Breaking Change: Predicted spawned ghosts for partial ticks skip restoring the state from the backup (and instead continue prediction from their spawn state) when the last backup state tick is identical to the spawn tick, as no data has changed.
  • Behaviour Breaking Change: Reduced the complexity (and performance overhead) of the GhostCount.GhostCountOnServer calculations internally. Note that this value is (and always has been) an approximation.
  • IsReconnected split into NetworkStreamIsReconnected for reconnected connections and IsMigrated for re-spawned ghosts (Host Migration).
  • Moved host migration related types into a Unity.Netcode.HostMigration namespace, renamed the HostMigration class to HostMigrationUtility so it works in the new namespace.
  • Prespawn ghost IDs will now be preserved between host migrations
  • Client connection NetworkIDs are now preserved between host migrations.
Added
  • Two new entity command buffer systems that run at the beginning and end of the PredictedSimulationSystemGroup respectively: BeginPredictedSimulationCommandBufferSystem and EndPredictedSimulationCommandBufferSystem.
  • A new internal PredictedSpawningSystemGroup, running after the EndPredictedSimulationCommandBufferSystem, created to guarantee that when a new snapshot is received from server, all new ghosts are spawned and ready to receive new data.
  • New documentation regarding the NetworkDriverStore architecture, setup and how to use it in conjunction with Unity.Relay.
  • Experimental host migration feature added, enabled with the ENABLE_HOST_MIGRATION define but otherwise hidden.
  • With ENABLE_HOST_MIGRATION defined, when a client reconnects to a server after disconnecting the connection entity on both sides will receive a NetworkStreamIsReconnected component. An internal unique ID is added to connections to track this behaviour.
  • The ability to define a smaller GhostSystemConstants.SnapshotHistorySize value via compiler define NETCODE_SNAPSHOT_HISTORY_SIZE_6 or NETCODE_SNAPSHOT_HISTORY_SIZE_16. These values are well suited for larger scale use-cases where server memory is constrained, and snapshot sends of individual ghosts are relatively infrequent.
  • Support for combining Ghost Relevancy with Ghost Importance Scaling via new PrioChunks.isRelevant field, enabling a fast-path for relevancy calculations.
  • Analytics to netcode tools to better understand their usage.
Obsolete
  • Prefer BatchScaleImportanceDelegate to ScaleImportanceFunction as the latter significantly reduces the total number of function pointer calls.
8 Likes

Sounds great! I’m particularly excited to try getting WebGL to work.

For 1.6.2, can a long-standing request please be made: change GhostPredictionDisableSimulateSystem to be public instead of internal. We had a subtle bug for a long time where a system placed at the start of the PredictedSimulationSystemGroup was actually placed before GhostPredictionDisableSimulateSystem, so ghosts requiring to be simulated weren’t always tagged as such.

1 Like

In my opinion it’s terrible practice for unity or any developer to make any system non public. So please fix this, and the rest of them…

6 Likes

we can make stuff public (but I counter the fact making system internal is bad practice). sure system should be targeted (sometime) but it is mostly a bad design of us letting you to have to target a specific system exactly before in many cases.

also everything public cause other pain point: make it harder for us changing internals without impacting projects.

In this specific case, instead of the GhostPredictionDisableSimulateSystem being public maybe would have been better have group that run at the beginning of prediction where you can inject into and be sure is run before everything else.

however, being the change so simple let’s do that, among some other critical ones (that was already in the our radar)

3 Likes

1.6.2 is now live, fixing a couple of regressions.

4 Likes