Skip to content

Commit 362f449

Browse files
author
Unity Technologies
committed
## [1.2.0-pre.12] - 2024-02-13 ### Added * Optimisations for the gather-ghost-chunk by batching function pointer calls and using a better hash map. * BatchScaleImportanceDelegate, a new version of the importance scaling function that work in batches. It is not required to set both the ScaleImportance and the BatchScaleImportance function pointers. If the BatchScaleImportance is set, it is the preferred. * TempStreamInitialSize, a new parameter in the GhostSendSystemData for tuning the initial size of the temporary buffer used by server to serialise ghosts. By default now the size is 8KB. * AlwaysRelevantQuery to specify general rules for relevancy without specifying it ghost by ghost. ### Changed * StreamCompressionDataModel is passed as in parameter to avoid many copy every time a WriteXXX or ReadXXX was called. * Updated Burst dependency to version 1.8.12 ### Fixed * UI issue disallowing the user from enabling the Network Emulator utility when upgrading with a now-deprecated EditorPref value. * an issue with pre-serialised ghosts, corrupting memory, crashing or copying wrong data into the snapshot buffer in certain conditions. * avoided GC allocation and the costly Marshal.GetDelegateFromFunctionPointer every time an FunctionPointer.Invoke is called. This is done by using directly unmanaged function pointers. All this, compatible with Burst enabled/disabled at any time. * lot of memory copies for loop invariants. This also reduced some SafetyChecks and costly operations. * avoid costly re-serialization of the whole chunk when the temp buffer can't fit all the data. This is one of the biggest costs during the serialisation loop. By default now the buffer is 8KB that reduce this possibility almost to 0. * Assigned InterpolationTick to always be equal ServerTick on the Server simulation (as stated in the summary for this parameter). Additionally the typos pointed out in the parameter summary were corrected. * Issue where prespawn failed to initialize when relevancy list was updated before replicating internal prespawn ghosts.
1 parent b55e3ed commit 362f449

File tree

58 files changed

+3905
-1068
lines changed

Some content is hidden

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

58 files changed

+3905
-1068
lines changed

CHANGELOG.md

+25
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,31 @@ uid: changelog
44

55
# Changelog
66

7+
## [1.2.0-pre.12] - 2024-02-13
8+
9+
### Added
10+
11+
* Optimisations for the gather-ghost-chunk by batching function pointer calls and using a better hash map.
12+
* BatchScaleImportanceDelegate, a new version of the importance scaling function that work in batches. It is not required to set both the ScaleImportance and the BatchScaleImportance function pointers. If the BatchScaleImportance is set, it is the preferred.
13+
* TempStreamInitialSize, a new parameter in the GhostSendSystemData for tuning the initial size of the temporary buffer used by server to serialise ghosts. By default now the size is 8KB.
14+
* AlwaysRelevantQuery to specify general rules for relevancy without specifying it ghost by ghost.
15+
16+
### Changed
17+
18+
* StreamCompressionDataModel is passed as in parameter to avoid many copy every time a WriteXXX or ReadXXX was called.
19+
* Updated Burst dependency to version 1.8.12
20+
21+
### Fixed
22+
23+
* UI issue disallowing the user from enabling the Network Emulator utility when upgrading with a now-deprecated EditorPref value.
24+
* an issue with pre-serialised ghosts, corrupting memory, crashing or copying wrong data into the snapshot buffer in certain conditions.
25+
* avoided GC allocation and the costly Marshal.GetDelegateFromFunctionPointer every time an FunctionPointer.Invoke is called. This is done by using directly unmanaged function pointers. All this, compatible with Burst enabled/disabled at any time.
26+
* lot of memory copies for loop invariants. This also reduced some SafetyChecks and costly operations.
27+
* avoid costly re-serialization of the whole chunk when the temp buffer can't fit all the data. This is one of the biggest costs during the serialisation loop. By default now the buffer is 8KB that reduce this possibility almost to 0.
28+
* Assigned InterpolationTick to always be equal ServerTick on the Server simulation (as stated in the summary for this parameter). Additionally the typos pointed out in the parameter summary were corrected.
29+
* Issue where prespawn failed to initialize when relevancy list was updated before replicating internal prespawn ghosts.
30+
31+
732
## [1.2.0-pre.6] - 2023-12-13
833

934
### Changed

Documentation~/network-connection.md

+55
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,58 @@ The request will be then consumed at runtime by the [NetworkStreamReceiveSystem]
106106
Unity Transport provides a [SimulatorUtility](playmode-tool.md#networksimulator), which is available (and configurable) in the Netcode package. Access it via `Multiplayer > PlayMode Tools`.
107107

108108
We strongly recommend that you frequently test your gameplay with the simulator enabled, as it more closely resembles real-world conditions.
109+
110+
## Listening for Client Connection Events
111+
We provide a `public NativeArray<NetCodeConnectionEvent>.ReadOnly ConnectionEventsForTick` collection (via the `NetworkStreamDriver` singleton), allowing you to iterate over (and thus react to) client connection events on the Client & Server.
112+
113+
```csharp
114+
// Example System:
115+
[UpdateAfter(typeof(NetworkReceiveSystemGroup))]
116+
[BurstCompile]
117+
public partial struct NetCodeConnectionEventListener : ISystem
118+
{
119+
[BurstCompile]
120+
public void OnUpdate(ref SystemState state)
121+
{
122+
var connectionEventsForClient = SystemAPI.GetSingleton<NetworkStreamDriver>().ConnectionEventsForTick;
123+
foreach (var evt in connectionEventsForClient)
124+
{
125+
UnityEngine.Debug.Log($"[{state.WorldUnmanaged.Name}] {evt.ToFixedString()}!");
126+
}
127+
}
128+
}
129+
```
130+
> [!NOTE]
131+
> These events will only live for a single `SimulationSystemGroup` tick, and are reset during `NetworkStreamConnectSystem` and `NetworkStreamListenSystem` respectively.
132+
> Therefore, if your system runs **_after_** these aforementioned system's job's execute, you'll receive notifications on the same tick that they were raised.
133+
> However, if you query this collection **_before_** this system's job's execute, you'll be iterating over the **_previous_** tick's values.
134+
135+
> [!NOTE]
136+
> Because the Server runs on a fixed delta-time, the `SimulationSystemGroup` may tick any number of times (including zero times) on each render frame.
137+
> Because of this, `ConnectionEventsForTick` is only valid to be read inside a system running inside the `SimulationSystemGroup`.
138+
> I.e. Trying to access it outside the `SimulationSystemGroup` can lead to a) either **_only_** seeing events for the current tick (meaning you miss events for previous ticks) or b) receiving events multiple times, if the simulation doesn't tick on this render frame.
139+
> Therefore, do not access `ConnectionEventsForTick` inside the `InitializationSystemGroup`, nor inside the `PresentationSystemGroup`, nor inside any `MonoBehaviour` Unity method (non-exhaustive list!).
140+
141+
### NetCodeConnectionEvent's on the Client
142+
| Connection Status | Invocation Rules |
143+
|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
144+
| `Unknown` | Never raised. |
145+
| `Connecting` | Raised once for your own client, once the `NetworkStreamReceiveSystem` registers your `Connect` call (which may be one frame after you call `Connect`). |
146+
| `Handshake` | Raised once for your own client, once your client has received a message from the server notifying your client that its connection was accepted. |
147+
| `Connected` | Raised once for your own client, once the server sends you your `NetworkId`. |
148+
| `Disconnected` | Raised once for your own client, once you disconnect from / timeout from / are disconnected by the server. The `DisconnectReason` will be set. |
149+
150+
> [!NOTE]
151+
> Clients do **_not_** receive events for other clients. Any events raised in a client world will only be for it's own client connection.
152+
153+
### NetCodeConnectionEvent's on the Server
154+
| Connection Status | Invocation Rules |
155+
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
156+
| `Unknown` | Never raised. |
157+
| `Connecting` | Never raised on the server, as the server does not know when a client begins to connect. |
158+
| `Handshake` | Never raised on the server, as accepted clients are assigned `NetworkId`'s immediately. I.e. Handshake is instant. |
159+
| `Connected` | Raised once for every accepted client, on the frame the server accepts the connection (and assigns said client a `NetworkId`). |
160+
| `Disconnected` | Raised once for every accepted client, which then disconnects, on the frame we receive the Disconnect event or state. The `DisconnectReason` will be set. |
161+
162+
> [!NOTE]
163+
> The server does not raise any events when it successfully `Binds`, nor when it begins to `Listen`. Use existing APIs to query these statuses.

Documentation~/optimizations.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ _Note that applying this setting will cause **all** ghosts to default to **not b
5757
* **SetIsIrrelevant** - Ghosts added to relevancy set (`GhostRelevancySet`, below) are considered "not-relevant to that client", and thus will be not serialized for the specified connection. In other words: Set this mode if you want to specifically ignore specific entities for a given client.
5858

5959
`GhostRelevancySet` is the map that stores a these (connection, ghost) pairs. The behaviour (of adding a (connection, ghost) item) is determined according to the above rule.
60-
61-
> [!NOTE]
60+
`DefaultRelevancyQuery` is a global rule denoting that all ghost chunks matching this query are always considered relevant to all connections (unless you've added the ghosts in said chunk to the `GhostRelevancySet`). This is useful for creating general relevancy rules (e.g. "the entities in charge of tracking player scores are always relevant"). `GhostRelevancySet` takes precedence over this rule. See the [example](https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/NetcodeSamples/Assets/Samples/Asteroids/Authoring/Server/SetAlwaysRelevantSystem.cs) in Asteroids.
61+
```c#
62+
var relevancy = SystemAPI.GetSingletonRW<GhostRelevancy>();
63+
relevancy.ValueRW.DefaultRelevancyQuery = GetEntityQuery(typeof(AsteroidScore));
64+
```
65+
> [!NOTE]~~~~
6266
> If a ghost has been replicated to a client, then is set to **not be** relevant to said client, that client will be notified that this entity has been **destroyed**, and will do so. This misnomer can be confusing, as the entity being despawned does not imply the server entity was destroyed.
6367
> Example: Despawning an enemy monster in a MOBA because it became hidden in the Fog of War should not trigger a death animation (nor S/VFX). Thus, use some other data to notify what kind of entity-destruction state your entity has entered (e.g. enabling an `IsDead`/`IsCorpse` component).
6468

0 commit comments

Comments
 (0)