Skip to content

Commit 70c9ce6

Browse files
author
Unity Technologies
committed
## [1.9.0] - 2025-09-15 ### Added * `GenerateTestsForBurstCompatibility` test coverage - and `ToString` overloads - of `ToFixedString` methods. * **Behaviour Breaking Change:** `GhostSendSystemData.PercentReservedForDespawnMessages` denoting the percentage of the snapshot capacity reserved for ghost despawn messages, with a default value of 33% (i.e. one third of the snapshot). This replaces the internal const of 100 ghosts. * A clickable link directing users where to disable Batched Tick Warnings. * New + and - buttons for automatic thin client creation in the PlayMode Tools window. * Bounds checks to `NetworkDriverStore` and `NetworkDriverStore.Concurrent` driver accessors. ### Changed * Marginally reduced the bandwidth consumption of the `GID` and `SpawnTick` values of ghosts within snapshots, on average. * **API Breaking Change:** The `PrefabDebugName.Name` has now been fully deprecated, reducing archetype chunk sizes, increasing per-chunk entity capacity for ghost instances. * Best practice on GhostOwnerIsLocal usage. Server-only world behaviour is now undefined and might be changed in future versions. GhostOwnerIsLocal should only be used in client logic. To find owned ghosts in prediction logic, please make sure to strip your input components so they only appear on predicted ghosts. * Best practice on NetcodeServerRateManage.WillUpdate. Should now use NetworkTime.NumPredictedTicksExpected server side. * Significant internal refactoring for upcoming Single World Host feature. * The importance visualizer setting name for "Per Entity Spatial Chunk Structure" has been changed to "Per Chunk". This does not change the behavior, the name is only changed to more accurately reflect the underlying data that is being visualized. * Made `NetworkDriverStore` methods readonly, where possible. ### Fixed * The analyzer to warn about using the `Simulate` component while ignoring enabled state has been fixed to correctly warn when using SystemAPI.Query().WithAll<Simulate>()` and similar calls. * Issue where the ghost data writes could fail while gathering the host migration data (now it will always grow correctly). * `Allocator.Persistent` memory leaks caused by `ImportanceDrawerSystem.cs`. * `ClampPartialTicksThreshold` now displays correctly in the `NetCodeConfig`. * **Behaviour Breaking Change:** Ghost despawn messages are now added to the snapshot in a round-robin priority order, where up to 2 despawn messages can be "in-flight" for a single ghost at once. Old behaviour was to send up to 100 ghostIds per snapshot, where each despawn was sent up to 5 times in a row before the next 100 could be added. Delta-compression has also been significantly improved. This new approach significantly improves despawn throughput, while also significantly reducing despawn bandwidth consumption. * **Behaviour Breaking Change:** The minimum `DefaultSnapshotPacketSize` is now 100 bytes, up from 1 byte. * Incorrectness in ghost despawn message handling, leading to missed despawns, and rare snapshot errors. * Hardened snapshot receive logic to expect exact `dataStream.GetBitsRead()` correctness, and used it to fix a (harmless) incorrectness when a chunk attempts to write its first ghost into the snapshot, but fails due to exceeding the stream capacity. * Potential dependency error with importance visualization. * Broken table on PlayMode Tool documentation page.
1 parent 44fa025 commit 70c9ce6

File tree

112 files changed

+3072
-1063
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+3072
-1063
lines changed

.attestation.p7m

1 Byte
Binary file not shown.

.signature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"timestamp":1755424786,"signature":"YBUJl53Rqd2W72Ig5cNuc0OGlYbt0OSu1fYJDfhZMZBw4u/ra85wkXgy3CJ+V/Pa+m8/3Txtqv5SyJGwnXMjYQ/vM8k7pfEvmQ5bWt6N5frIncPvKThwJ+20d0rxR5MSKqYI91fy2vp3mEi1/smKMlP5dTDj0rfuV6HwSjuAJFGfl4ecKnVazFG06ZQq5nwsEnVkLew1qJT/xva6s6mY1oxI9bHZ8myTJeMLI9OeONKkHroscl7S4ZLMi3EVI6RZTmjyAISdVp1werb3K4+qNMCkjoB/sNKvRW2bI2UU/NaxhnHdQIHkURJaLa23J1QiGJGGP0dt/yz65r4GwQd/8VkpioXWKhI3hNtYVvyiBdBLl+X7R0aRNRaOKEoWzIB9Lg8wFMueiYK5m31PZcKX21pT218IPxjDmYfZ8+75uQHjtvmtU8Yh/nwFO/ysgN35P17OcH3Li/kuJ5wvl5LJUPrvyImbPhvuhYsXPl39nBd8rLsL6zAVTlPW1pD9dndv","publicKey":"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"}
1+
{"timestamp":1758701568,"signature":"r75hTMuvHqwfIgsR6Nuxe/ZwV2ymJiAc+Wu3wQKpUX5M2BqlRhBa4Q3VTp2SXEC/wG6v4Yv+b2F8iri3X7pses5M7Ybyut6SA5NQ4HAV1ItHnl4aH/xzJ9jAfkkoWTqFgmPSwyllSBB18zQtNmyDxqcc0GucaL+bNEoQj9Cauvg1tDFyhN2z4p1KnxHmsBIu3wEp/Xpeqw7+2Mb7Rgu7CQzCOlNl5a99UnflVWvauK26xmE9a+CW2fZI6/p+KusjueAKT0II7EjtqB7ArA7mTDcwt/DwEmxMzyRxEjyiHb65dmQbsZCzy+1TiSFqpH7Ug511YW0+zC5rxCAqaAcy+rmIo8C+vj6AV9VYqamdmli0iVCKmhVDIwayVdJdoeZ73qgofVqig7weJojm33HNK56qVfUL48fRifoCKuP/Pm6XdCGwwlFTFWJ3fpPI0loEHVgRBlRb/cPADt7hF2Cj32nb+cqI0+kxItRLNocj56oo7hXFI/cHw+S+I8twnnss","publicKey":"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"}

CHANGELOG.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,41 @@
22
uid: changelog
33
---
44

5+
## [1.9.0] - 2025-09-15
6+
7+
### Added
8+
9+
* `GenerateTestsForBurstCompatibility` test coverage - and `ToString` overloads - of `ToFixedString` methods.
10+
* **Behaviour Breaking Change:** `GhostSendSystemData.PercentReservedForDespawnMessages` denoting the percentage of the snapshot capacity reserved for ghost despawn messages, with a default value of 33% (i.e. one third of the snapshot). This replaces the internal const of 100 ghosts.
11+
* A clickable link directing users where to disable Batched Tick Warnings.
12+
* New + and - buttons for automatic thin client creation in the PlayMode Tools window.
13+
* Bounds checks to `NetworkDriverStore` and `NetworkDriverStore.Concurrent` driver accessors.
14+
15+
### Changed
16+
17+
* Marginally reduced the bandwidth consumption of the `GID` and `SpawnTick` values of ghosts within snapshots, on average.
18+
* **API Breaking Change:** The `PrefabDebugName.Name` has now been fully deprecated, reducing archetype chunk sizes, increasing per-chunk entity capacity for ghost instances.
19+
* Best practice on GhostOwnerIsLocal usage. Server-only world behaviour is now undefined and might be changed in future versions. GhostOwnerIsLocal should only be used in client logic. To find owned ghosts in prediction logic, please make sure to strip your input components so they only appear on predicted ghosts.
20+
* Best practice on NetcodeServerRateManage.WillUpdate. Should now use NetworkTime.NumPredictedTicksExpected server side.
21+
* Significant internal refactoring for upcoming Single World Host feature.
22+
* The importance visualizer setting name for "Per Entity Spatial Chunk Structure" has been changed to "Per Chunk". This does not change the behavior, the name is only changed to more accurately reflect the underlying data that is being visualized.
23+
* Made `NetworkDriverStore` methods readonly, where possible.
24+
25+
### Fixed
26+
27+
* The analyzer to warn about using the `Simulate` component while ignoring enabled state has been fixed to correctly warn when using SystemAPI.Query().WithAll<Simulate>()` and similar calls.
28+
* Issue where the ghost data writes could fail while gathering the host migration data (now it will always grow correctly).
29+
* `Allocator.Persistent` memory leaks caused by `ImportanceDrawerSystem.cs`.
30+
* `ClampPartialTicksThreshold` now displays correctly in the `NetCodeConfig`.
31+
* **Behaviour Breaking Change:** Ghost despawn messages are now added to the snapshot in a round-robin priority order, where up to 2 despawn messages can be "in-flight" for a single ghost at once. Old behaviour was to send up to 100 ghostIds per snapshot, where each despawn was sent up to 5 times in a row before the next 100 could be added. Delta-compression has also been significantly improved. This new approach significantly improves despawn throughput, while also significantly reducing despawn bandwidth consumption.
32+
* **Behaviour Breaking Change:** The minimum `DefaultSnapshotPacketSize` is now 100 bytes, up from 1 byte.
33+
* Incorrectness in ghost despawn message handling, leading to missed despawns, and rare snapshot errors.
34+
* Hardened snapshot receive logic to expect exact `dataStream.GetBitsRead()` correctness, and used it to fix a (harmless) incorrectness when a chunk attempts to write its first ghost into the snapshot, but fails due to exceeding the stream capacity.
35+
* Potential dependency error with importance visualization.
36+
* Broken table on PlayMode Tool documentation page.
37+
38+
39+
540
## [1.8.0] - 2025-08-17
641

742
### Added
@@ -968,7 +1003,6 @@ All the information in regards the current simulated tick MUST be retrieved from
9681003
* Package Dependencies
9691004
* `com.unity.entities` to version `0.51.1`
9701005

971-
9721006
## [0.51.0] - 2022-05-04
9731007

9741008
### Changed

Documentation~/client-server-worlds.md

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,83 @@
22

33
Understand the client and server networking model that the Netcode for Entities package uses.
44

5-
Netcode for Entities separates client and server logic into two worlds, referred to as the client world and the server world respectively. The concept of [worlds](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/concepts-worlds.html) is inherited from Unity's Entity Component System (ECS), and refers to a collection of [entities](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/concepts-entities.html) and [systems](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/concepts-systems.html) arranged into [system groups](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/systems-update-order.html).
5+
Netcode for Entities uses a client-server model and has a separation between client and server logic that is split into multiple worlds (the client world and server world <!-- or host world (Experimental) TODO -->). The concept of [worlds](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/concepts-worlds.html) is inherited from Unity's Entity Component System (ECS), and refers to a collection of [entities](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/concepts-entities.html) and [systems](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/concepts-systems.html) arranged into [system groups](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/manual/systems-update-order.html).
66

77
In addition to the standard client and server worlds, Netcode for Entities also supports [thin clients](thin-clients.md) which you can use to test your game during development.
88

9+
## Terminology
10+
11+
The words client and server can mean different things depending on the context. They can refer to the role a world is taking, or they can refer to the device a game is executing on.
12+
13+
- From a hosting perspective, server refers to the hardware or virtual machine that is running the server world for client devices to connect to.
14+
- From a role perspective, server refers to the world that's running the authoritative simulation, and client refers to the world that's running the local simulation for a player.
15+
16+
A client device can have a server role, for example, which is referred to as a client-hosted server (or simply host).
17+
18+
<!--
19+
20+
TODO remove this comment once ready to be used by users
21+
22+
## Client, server, and host worlds
23+
24+
Netcode for Entities supports different configurations of worlds within the client-server model. A host world is a special type of server world that also runs client systems, allowing one of the players to act as a server. This is referred to as a client-hosted server.
25+
26+
[See Hosting vs Roles](hosting-vs-role.md) for the difference between the two.
27+
28+
| Configuration | Description |
29+
|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
30+
| Client-only world connecting to a server-only world. | You distribute client builds to your players and host a server build yourself in dedicated servers. |
31+
| Client-only world connecting to a client-hosted server world | You distribute client-server builds to your players and one of the players acts as a server.<br/>The host player has a client world connecting through IPC to a server world. |
32+
| Client-only world connecting to a client-hosted single-world server | You distribute client-server builds to your players, but instead of the host player creating two worlds, they create a single world acting as both a client and server world. This single-world host behaves as a server with client systems running on it as well. Visible ghosts are no longer predicted or interpolated, they are simply the authoritative ghosts being rendered. |
33+
34+
### Binary and single-world host modes
35+
36+
You can choose between the default binary host mode and single-world host mode using the NetcodeConfig's **Host World Mode Selection** dropdown.
37+
38+
> [!NOTE]
39+
> Because this is an experimental feature, you also need to add the NETCODE_EXPERIMENTAL_SINGLE_WORLD_HOST define in your project to enable single-world host mode.
40+
41+
Each mode has its own advantages and disadvantages, as described below.
42+
43+
TODO-next format the following in a table
44+
45+
Single-world host mode advantages:
46+
47+
- Performance: a binary world host has multiple extra steps to spend CPU time on. A server world's `SimulationGroup`, `GhostSendSystem`'s serialization, a client world's deserialization, rolling back to the last snapshot, replaying 1+ ticks, 1 partial tick, serializing and sending inputs to the local server world. Whereas a single-world host only has one world to execute locally, with one simulation tick and spends no time sending/receiving data for its own player.
48+
- Because there's no longer two worlds in the same process, static state is for only one world (a client world or a host world).
49+
50+
Binary host mode advantages:
51+
52+
- Client and server separation: `IsClient` and `IsServer` are always exclusive, making writing client and server code easier to think about. Client-only logic will behave the same whether executing on a client or on a client-hosted server.
53+
- Easier testing: when you test locally with a split client world connecting through IPC to a local server world, you are already testing a client connecting to a server. The chances of client-only issues when testing a second client connecting to your host are lessened (although not zero, you should still test with builds or [Multiplayer Play Mode](https://docs.unity3d.com/Packages/com.unity.multiplayer.playmode@latest) clones). For example, it can be easy to forget adding a `[GhostField]` attribute on your `Entity somePlayer` or `int myHealth` fields. With single-world host, you need to always test the behavior of client-only separately.
54+
- When using binary host mode, your game is closer to a dedicated server. It's easier to port to a dedicated server hosting model since your gameplay logic is already split between client and server worlds.
55+
56+
### Behavior differences and migration considerations
57+
58+
If you want to switch between binary host mode and single-world host mode mid-project, you need to be aware of the following differences in behavior between the two modes.
59+
60+
- Connection entity: a world where client systems execute (your host) can have multiple connections containing `NetworkId` and `NetworkStreamInGame`.
61+
- Single-world host has a fake connection entity, containing a singleton `LocalConnection` component, a `NetworkId` component, and no `NetworkStreamConnection` component.
62+
- Inputs: client systems have access to other player's inputs on a host. You need to filter appropriately using `GhostOwnerIsLocal`.
63+
- `GhostOwnerIsLocal` behaves differently between the two modes.
64+
- In a binary host mode setup, client worlds see `GhostOwnerIsLocal` active on locally owned ghosts (ghosts whose owner ID corresponds to the `LocalConnection`'s network ID). On a server world, the behaviour is undefined.
65+
- In a single-world setup, the host world sees `GhostOwnerIsLocal` active on its locally owned ghosts, just like for client worlds.
66+
- Make sure to strip your input components so they only appear on predicted ghosts if you want to run prediction code reading inputs server-side without having to rely on `GhostOwnerIsLocal`. Refer to `GhostComponent` for stripping configurations.
67+
- Client-only logic executes in the same world as server systems when using single-world host mode.
68+
- Relevancy and culling: as the single hosting world is the server role, it must have all server ghost entities loaded in memory to be able to properly perform server duties (for other connections). Therefore, host worlds cannot enable relevancy for the host connection (though relevancy can still be applied to other connections). Therefore, you need to manually disable rendering for far away ghosts in single-world host mode, you can't rely on relevancy.
69+
- Prediction switching isn't supported on hosts, so can't be used in single-world host mode.
70+
- When using single-world host mode, all ghosts are authoritative ghosts which means interpolation must be handled differently.
71+
- Instead of changing the authoritative value, it's recommended to just smooth the visual instead when interpolating. For example, use `LocalToWorld` for transforms.
72+
- Refer to the [Health sample](https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/NetcodeSamples/Assets/Samples/HelloNetcode/3_Advanced/01_HealthBars) for an example of an interpolated and replicated values (the player's health).
73+
- You can use a fast path for RPCs in single-world host mode. Custom serialization should take advantage of that fast path with `IsPassthroughRPC` and `GetPassthroughActionData`.
74+
- Partial Ticks: single-host world doesn't support partial ticks. You can instead interpolate your ghosts between full ticks on the host.
75+
- Testing with lag: to test with lag, you need to test with an external client connecting to your host. Because the host doesn't serialize/deserialize its own state in single-host world mode, there's no way to add artificial latency on your local objects.
76+
- Sending snapshots on catchup ticks: in a server-only world, the server can send snapshot packets for each individual catchup ticks if they all happen in the same frame. This isn't the case for single-world host, where the host only sends one snapshot per frame.
77+
78+
TODO-next see comment here https://github.cds.internal.unity3d.com/unity/dots/pull/14369/files/ee874d6192b2d76cf38a3aa733b54469b65b24fa#r831105 the above should be a table.
79+
80+
-->
81+
982
## Configuring system creation and updates
1083

1184
By default, systems are created and updated in the [`SimulationSystemGroup`](https://docs.unity3d.com/Packages/com.unity.entities@latest?subfolder=/api/Unity.Entities.SimulationSystemGroup.html) for both client and server worlds. If you want to override this behavior (for example, to have your system created and run only on the client world), there are two different methods available.
@@ -68,7 +141,7 @@ The default bootstrap creates the client and server worlds automatically at star
68141

69142
This automatic world creation is most useful when you're working in the Editor and enter Play mode with your game scene opened, because it allows immediate Editor iteration testing of your multiplayer game. However, in a standalone game where you typically want to use some sort of front-end menu, you might want to delay world creation, or choose which Netcode worlds to spawn.
70143

71-
For example, consider a "Hosting a client-hosted server" flow versus a "Connect as a client to a dedicated server via matchmaking" flow. In the first scenario, you want to add (and connect via IPC to) an in-process server world. In second scenario, you only want to create a client world. In these cases, you can choose to customize the bootstrapping flow.
144+
For example, consider a "Hosting a client-hosted server" flow versus a "Connect as a client to a dedicated server via matchmaking" flow. In the first scenario, you may want to add (and connect via IPC to) an in-process server world. In the second scenario, you only want to create a client world. In these cases, you can choose to customize the bootstrapping flow.
72145

73146
### Customize the bootstrapping flow
74147

0 commit comments

Comments
 (0)