Skip to content

Commit d5cd132

Browse files
author
Unity Technologies
committed
com.unity.netcode@1.0.0-pre.44
## [1.0.0-pre.44] - 2023-02-13 ### Added * Validation checks to the `GhostDistanceData` `TileSize` to prevent invalid tile assignment or DivideByZeroException. * Added a HelpURL (linking to docs) for `DisableAutomaticPrespawnSectionReportingAuthoring`, `GhostAuthoringComponent`, `GhostAuthoringInspectionComponent`, `DefaultSmoothingActionUserParamsAuthoring`, `GhostPresentationGameObjectAuthoring`, `NetCodeDebugConfigAuthoring`, `GhostAnimationController`, `GhostPresentationGameObjectEntityOwner`, and `NetCodePhysicsConfig`. * New GetLocalEndPoint API to NetworkStreamDriver ### Changed * Make EnablePacketLogging component public to allow for per connection debug information. * Updated `com.unity.transport` dependency to version 2.0.0-pre.6. ### Fixed * An issue with the `NetworkEmulator` in the editor when enabling domain reload (while switching play-mode) that was causing the game to forcibly immediately exit the the play state. * An issue with pre-spawned ghost baking when the baked entity has not LocalTransform (position/rotation for transform v1) component. * "Ghost Distance Importance Scaling" is now working again. Ensure you read the updated documentation. * Missing field write in `NetworkStreamListenSystem.OnCreate`, fixing Relay servers. * Code-Generated Burst-compiled Serializer methods will now only compile inside worlds with `WorldFlag.GameClient` and `WorldFlag.GameServer` WorldFlags. This improves exit play-mode speeds (when Domain Reload is enabled), baking (in all cases), and recompilation speeds. * Fixed an issue where multiple ghost types with the same archetype but difference data could sometime trigger errors about ghosts changing type. * Fix a mistake where the relay sample will create a client driver rather than a server driver * Fix logic for relay set up on the client. Making sure when calling DefaultDriverConstructor.RegisterClientDriver with relay settings that we skip this unless, requested playtype is client or clientandserver (if no server is found), the simulator is enabled, or on a client only build. * Fixed `ArgumentException: ArchetypeChunk.GetDynamicComponentDataArrayReinterpret<System.Byte> cannot be called on zero-sized IComponentData` in `GhostPredictionHistorySystem.PredictionBackupJob`. Added comprehensive test coverage for the `GhostPredictionHistorySystem` (via adding a predicted ghost version of the `GhostSerializationTestsForEnableableBits` tests). * Fixed serialization of components on child entities in the case where `SentForChildEntities = true`. This fix may introduce a small performance regression in baking and netcode world initialization. Contact us with all performance related issues. * `GhostUpdateSystem` now supports Change Filtering, so components on the client will now only be marked as changed _when they actually are changed_. We strongly recommend implementing change filtering when reading components containing `[GhostField]`s and `[GhostEnabledBit]`s on the client. * Fixed input component codegen issue when the type is nested in a parent class * Exposed NetworkTick value to Entity Inspector
1 parent daf5f44 commit d5cd132

File tree

148 files changed

+5262
-2877
lines changed

Some content is hidden

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

148 files changed

+5262
-2877
lines changed

CHANGELOG.md

Lines changed: 86 additions & 31 deletions
Large diffs are not rendered by default.

Documentation~/command-stream.md

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,27 @@ The queued commands are then automatically sent at regular interval by `CommandS
1717

1818
The systems responsible for writing to the command buffers must all run inside the [GhostInputSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.GhostInputSystemGroup.html).
1919

20+
### ICommandData serialization and payload limit
21+
When using ICommand, the Netcode for Entities package automatically generated the command serialization code for you. </br>
22+
Commands serialization take place in the `CommandSendSystemGroup`. Each individual command is serialized and enqueued into the `OutgoingCommandDataStreamBufferComponent` (present on the network connection)
23+
by its own code-generated system. </br> The `CommandSendPacketSystem` is then responsible to flush the outgoing buffer at `SimulationTickRate` interval.
24+
25+
In order to fight packet losses, along with with last input, we also include as a form of redundancy the last 3 input.
26+
Each redundant command is delta compressed against the command for the current tick. The final serialized data looks something like:
27+
28+
```
29+
| Tick, Command | CommandDelta(Tick-1, Tick) | CommandDelta(Tick-2, Tick) | CommandDelta(Tick-3, Tick)|
30+
```
31+
32+
**The package enforce a size limit of 1024 bytes** to the command payload. The check is performed when the command is serialise into the outgoing buffer and
33+
an error will be reported to the application if the encoded payload that does not respect the constraint.
34+
2035
### Receiving commands on the server
21-
`ICommamdData` are automatically received by the server by the `NetworkStreamReceiveSystem` and added to the `IncomingCommandDataStreamBufferComponent` buffer. The `CommandReceiveSystem` is then responsible
36+
`ICommandData` are automatically received by the server by the `NetworkStreamReceiveSystem` and added to the `IncomingCommandDataStreamBufferComponent` buffer. The `CommandReceiveSystem` is then responsible
2237
to dispatch the command data to the target entity (which the command belong to).
23-
>![NOTE] The server must only receive commands from the clients. It should never overwrite or change the input received by the client.
38+
39+
> [!NOTE]
40+
> The server must only receive commands from the clients. It should never overwrite or change the input received by the client.
2441
2542
## Automatic handling of commands. The AutoCommandTarget component.
2643
If you add your `ICommandData` component to a ghost (for which the following options has been enabled in the `GhostAuthoringComponent):
@@ -29,23 +46,24 @@ If you add your `ICommandData` component to a ghost (for which the following opt
2946

3047
<img src="images/enable-autocommand.png" width="500" alt="enable-autocommand"/>
3148

32-
the commands for that ghost will **automatically be sent to the server**. Obviously, the following rules apply:
49+
the commands for that ghost will **automatically be sent to the server**. The following rules apply:
3350
- the ghost must be owned by your client (requiring the server to set the `GhostOwnerComponent` to your `NetworkIdComponent.Value`),
34-
- the ghost is `Predicted` or `OwnerPredicted` (i.e. you therefore cannot use an `ICommandData` to control interpolated ghosts),
51+
- the ghost is `Predicted` or `OwnerPredicted` (i.e. you cannot use an `ICommandData` to control interpolated ghosts),
3552
- the [AutoCommandTarget](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.AutoCommandTarget.html).Enabled flag is set to true.
3653

3754
If you are not using `Auto Command Target`, your game code must set the [CommandTargetComponent](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.CommandTargetComponent.html) on the connection entity to reference the entity that the `ICommandData` component has been attached to.
38-
<br/> You can have multiple command systems, and Netcode for Entities will select the correct one (based on the `ICommandData` type of the entity that points to `CommandTargetComponent`).
55+
<br/> You can have multiple `ICommandData` in your game, and Netcode for Entities will only send the `ICommandData` for the entity that `CommandTargetComponent` points to.
3956

4057
When you need to access the inputs from the buffer, you can use an extension method for `DynamicBuffer<ICommandData>` called `GetDataAtTick` which gets the matching tick for a specific frame. You can also use the `AddCommandData` utility method (which adds more commands to the ring-buffer for you).
4158

42-
>~[NOTE] When you update the state of your simulation inside the prediction loop, you must rely only on the commands present in the `ICommandData` buffer (for a given input type).
59+
> [!NOTE]
60+
> When you update the state of your simulation inside the prediction loop, you must rely only on the commands present in the `ICommandData` buffer (for a given input type).
4361
Polling input directly, by using UnityEngine.Input or other similar method, or relying on input information not present in the struct implementing the `ICommandData` interface may cause client
4462
mis-prediction. </br>
4563

4664
## Checking which ghost entities are owned by the player, on the client.
4765
> [!NOTE]
48-
It is required you use (and implement) the `GhostOwnerComponent` functionality, for commands to work properly. For example: By checking the 'Has Owner' checkbox in the `GhostAuthoringComponent`.
66+
> It is required you use (and implement) the `GhostOwnerComponent` functionality, for commands to work properly. For example: By checking the 'Has Owner' checkbox in the `GhostAuthoringComponent`.
4967
5068
**On the client, it is very common to want to lookup (i.e. query for) entities that are owned by the local player.**
5169
This is problematic, as multiple ghosts may have the same `CommandBuffer` as your "locally owned" ghost (e.g. when using [Remove Player Prediction](prediction.md#remote-players-prediction), _every other "player" ghost_ will have this buffer),
@@ -62,7 +80,7 @@ Entities
6280
.WithAll<GhostOwnerIsLocal>()
6381
.ForEach((ref MyComponent myComponent)=>
6482
{
65-
// your logic here will be applied only to the entities onwed by "you" (the local player).
83+
// your logic here will be applied only to the entities owned by the local player.
6684
}).Run();
6785
```
6886
### Use the GhostOwnerComponent
@@ -71,12 +89,11 @@ You can filter the entities manually by checking that the `GhostOwnerComponent.N
7189
```c#
7290
var localPlayerId = GetSingleton<NetworkIdComponent>().Value;
7391
Entities
74-
.WithAll<GhostOwnerIsLocal>()
7592
.ForEach((ref MyComponent myComponent, in GhostOwnerComponent owner)=>
7693
{
7794
if(owner.NetworkId == localPlayerId)
7895
{
79-
// your logic here will be applied only to the entitis onwed by the local player.
96+
// your logic here will be applied only to the entities owned by the local player.
8097
}
8198
}).Run();
8299
```
@@ -86,11 +103,13 @@ Entities
86103
It's possible to have most of the things mentioned above for command data usage set up automatically for you given an input component data struct you have set up. You need to inherit the `IInputComponentData` interface on the input struct and the task of adding it to the command data buffer and retrieving back from the buffer when processing inputs will be handled automatically via code generated systems. For this to work it is required to have input gathering and input processing (like movement system) set up in two separate systems.
87104

88105
> [!NOTE]
89-
> It is required you use the `GhostOwnerComponent` functionality, for example by checking the `Has Owner` checkbox in the ghost authoring component for this to work.
106+
> It is required that you use the `GhostOwnerComponent` functionality, for example by checking the `Has Owner` checkbox in the ghost authoring component for this to work.
90107
>
91-
>[!NOTE]
108+
> [!NOTE]
92109
> Per prefab overrides done in the ghost authoring component inspector are disabled for input components and their companion buffer. You can add a ghost component attribute on the input component in code and it will apply to the buffer as well.
93110
111+
Because input struct implementing `IInputComponentData` are baked by `ICommandData`, [the 1024 bytes limit for the payload](ICommandData serialization and payload limit) also apply.
112+
94113
### Input events
95114

96115
By using the `InputEvent` type within `IInputComponentData` inputs you can guarantee one off events (for example gathered by `UnityEngine.Input.GetKeyDown`) will be synchronized properly with the server and registered exactly once. Even when the exact input tick where the input event was first registered is dropped on its way to the server.
@@ -99,21 +118,21 @@ By using the `InputEvent` type within `IInputComponentData` inputs you can guara
99118

100119
Given an input component data you'll have these systems set up.
101120

102-
- Gather input system
103-
- Take input events and save in the input component data
104-
- Process input system
105-
- Take current input component and process the values
121+
- Gather input system (Client loop)
122+
- Take input events and save them in the input component data. This happens in `GhostInputSystemGroup`.
123+
- Process input system (Server or prediction loop)
124+
- Take current input component and process the values. This _usually_ happens in `PredictedSimulationSystemGroup`.
106125

107126
With `IInputComponentData` netcode handling it looks like this with code generated systems.
108127

109-
- _Gather input system_
110-
- _Take input events and save in an input component data_
111-
- Copy input to command buffer
128+
- _Gather input system (Client loop)_
129+
- _Take input events and save them in the input component data. This happens in `GhostInputSystemGroup`._
130+
- Copy input to command buffer (Client loop)
112131
- Take current input data component and add to command buffer, also recording current tick
113-
- Apply inputs for current tick to input component data
132+
- Apply inputs for current tick to input component data (Server or prediction loop)
114133
- Retrieve inputs from command buffer for current tick and apply to input component. With prediction multiple input values could be applied as prediction rolls back (see [Prediction](prediction.md)).
115-
- _Process input system_
116-
- _Take current input component and process the values_
134+
- _Process input system (Server or prediction loop)_
135+
- _Take current input component and process the values. This _usually_ happens in `PredictedSimulationSystemGroup`._
117136

118137
The first and last steps are the same as with the single player input handling, and these are the only systems you need to write/manage. An important difference, with netcode enabled input, is that the processing system can be called multiple times per tick as previous ticks (rollback) are handled.
119138

@@ -223,9 +242,6 @@ public partial struct MyCommandSendCommandSystem : ISystem
223242
m_CommandSend.OnCreate(ref state);
224243
}
225244
[BurstCompile]
226-
public void OnDestroy(ref SystemState state)
227-
{}
228-
[BurstCompile]
229245
public void OnUpdate(ref SystemState state)
230246
{
231247
if (!m_CommandSend.ShouldRunCommandJob(ref state))
@@ -255,9 +271,6 @@ public partial struct MyCommandReceiveCommandSystem : ISystem
255271
m_CommandRecv.OnCreate(ref state);
256272
}
257273
[BurstCompile]
258-
public void OnDestroy(ref SystemState state)
259-
{}
260-
[BurstCompile]
261274
public void OnUpdate(ref SystemState state)
262275
{
263276
var recvJob = new ReceiveJob{data = m_CommandRecv.InitJobData(ref state)};

0 commit comments

Comments
 (0)