Skip to content

Commit e24c89b

Browse files
author
Unity Technologies
committed
com.unity.netcode@1.0.0-exp.8
## [1.0.0-exp.8] - 2022-09-21 ### Added * Added a new unified `NetCodePhysicsConfig` to configure in one place all the netcode physics settings. LagCompensationConfig and PredictedPhysicsConfig are generated from these settings at conversion time. * Predicted ghost physics now use multiple physics world: A predicted physics wold simulated the ghost physics and a client-only physics world can be used for effect. For more information please refer to the predicted physics documentation. * When there is a protocol version mismatch error when connecting, the versions and hashes used for the protocol are dumped to the log so it's easier to see why the versions don't match * added some sanity check to prevent updating invalid ghosts * Added a new method, `GhostPrefabCreation.ConvertToGhostPrefab` which can be used to create ghost prefabs from code without having an asset for them. * Added a support for creating multiple network drivers. It is now possible to have a server that listen to the same port using different network interfaces (ex: IPC, Socket, WebSocket at the same time). * Hybrid assemblies will not be included in DOTS Runtime builds. * code generation documentation * RegisterPredictedPhysicsRuntimeSystemReadWrite and RegisterPredictedPhysicsRuntimeSystemReadOnly extension methods, for tracking dependencies when using predicted networked physics systems. * Support for runtime editing the number of ThinClients. * Added: A new NetworkTime component that contains all the time and tick information for the client/server simulation. Please look at the upgrade guide for more information on how to update your project. * Support for enabledbits. * An input interface, IInputData, has been added which can be used to automatically handle input data as networked command data. The input is automatically copied into the command buffer and retrieved from it as appropriate given the current tick. Also added an InputEvent type which can be used inside such an input component to reliably synchronize single event type things. * Added support for running the prediction loop in batches by setting `ClientTickRate.MaxPredictionStepBatchSizeRepeatedTick` and `ClientTickRate.MaxPredictionStepBatchSizeFirstTimeTick`. The batches will be broken on input changes unless the input data that changes is marked with `[BatchPredict]`. * Some optimisation to reduce the number of predicted tick and interpolation frames when using InProc client/server and IPC connection. * Added a `ConnectionState` system state component which can be added to connection to track state changes, new connections and disconnects. * Added a `NetworkStreamRequestConnect` component which can be added to a new entity to create a new connection sintead of calling `Connect`. * Added `IsClient`, `IsServer` and `IsThinClient` helper methods to `World` and `WorldUnmanaged`. * Dependency on Unity.Logging package. * Ghosts are now marked-up as Ghosts in the DOTS Hierarchy (Pink = Replicated, Blue = Prefab). The built-in Unity Hierarchy has a similar markup, although limited due to API limitations. * The GhostAuthoringComponent now uses a ghost icon. * Update API documentation for importance scaling functions and types * Predicted Physics API documentation * Helper methods to DefaultDriverBuilder, these allows creation and registering IPC- and Socket drivers. On the server both are used for the editor and only socket for player build. On the client either IPC if server and client is in the same process or socket otherwise. * A Singleton API for Ghost Metrics. * Helper methods RegisterClientDriver and RegisterServerDriver added to DefaultDriverBuilder. These takes certificate and keys necessary to initialize a secure connection. * Improved the `GhostAuthoringComponent` window, and moved `ComponentOverrides` to a new, optional component; `GhostAuthoringInspectionComponent`. * Source generators now use a CancellationToken to early exit execution when cancellation is requested. * NetworkStreamRequestListen to start listening to a new connection instead of invoking NetworkStreamDriver.Listen * Helper methods RegisterClientDriver and RegisterServerDriver added to DefaultDriverBuilder. These takes relay server data to connect using a relay server. * Analytics callback for ghost configuration as well as scene setup scaling. * A default spawn classification system is will now handle client predicted spawns if the spawn isn't handled by a user system first (matches spawns of ghost types within 5 ticks of the spawn tick). * GhostCollectionSystem optimisation when importing and processing ghost prefabs. * A new sample that show how to backup/rollback non replicated components as part of the prediction loop. * ChangeMaskArraySizeInBytes and SnapshotHeaderSizeInBytes utility methods * internal extension to dynamic buffer, ElementAtRO, that let to get a readonly reference for a buffer element. ### Changed * hybrid will tick the client and server world using the player loop instead of relying on the default world updating the client and server world via the Tick systems. * Predicted ghost physics now use custom system to update the physics simulation. The built-in system are instead used for updating the client-only simulatiom. * The limit of 128 components with serialization is now for actively used components instead of components in the project. * all errors are now reporting the location and is possible to go the offending source code file / class by clicking the error in the console log. * removed unused __GHOST_MASK_BATCH__ region from all templates * PhysicsWorldHistory register readonly dependencies to the predicted runtime physics data when predicted physics is enabled. * fixed crash in source generator if package cache folder contains temporary or invalid directory names. * refactored source generators and added support for .additionalfile (2021.2+) * Renamed `ClientServerTickRate.MaxSimulationLongStepTimeMultiplier` to `ClientServerTickRate.MaxSimulationStepBatchSize` * `NetDebugSystem.NetDebug` has been replaced by a `NetDebug` singleton. * `GhostSimulationSystemGroup.SpawnedGhostEntityMap` has been replaced by a `SpawnedGhostEntityMap` singleton. * The interpolation delay is now calculated based on the perceived average snapshot ratio perceived by client, that help compensate for packet loss and jitter. * Update to use StreamCompressionModel rather than deprecated type NetworkCompressionModel. * Various improvements to the `Multiplayer PlayMode Tools Window`, including; simulator "profiles" (which are representative of real-world speeds), runtime thin client creation/destruction support, live modification of simulator parameters, and a tool to simulate lag spikes via shortcut key. * The ghost relevancy map and mode has moved from the `GhostSendSystem` to a `GhostRelevancy` singleton. * The `Connect` and `Listen` methods have moved to the `NetworkStreamDriver` singleton. * The utility method `GhostPredictionSystemGroup.ShouldPredict` has been moved to the `PredictedGhostComponent`. * `GhostCountOnServer` and `GhostCountOnClient` has been moved from `GhostReceiveSystem` to a singleton API `GhostCount` * The API to register smoothing functions for prediction has moved from the `GhostPredictionSmoothingSystem` system to the `GhostPredictionSmoothing` singleton. * The API to register RPCs and get RPC queues has moved from `RpcSystem` to the singleton `RpcCollection` * Removed use of the obsolete AlwaysUpdateSystem attribute. The new RequireMatchingQueriesForUpdate attribute has been added where appropriate. * Convert GhostDistancePartitioningSystem to ISystem * GhostReceiveSystem converted to ISystem. * Convert GhostSendSystem to ISystem. Public APIs have been moved to SingletonEntity named GhostSendSystemData * PredictedPhysicsWorldHelper class visibility is internal. * CommandReceiveClearSystem and CommandSendPacketSystem are not internal * StartStreamingSceneGhosts and StopStreamingSceneGhosts to be internal RPC. If user wants to customise the prespawn scene flow, they need to add their own RPC. * PrespawnsSceneInitialized, SubScenePrespawnBaselineResolved, PrespawnGhostBaseline,PrespawnSceneLoaded, PrespawnGhostIdRange have internal visibility. * PrespawnSubsceneElementExtensions has internal visibility. * LiveLinkPrespawnSectionReference are now internal. Used only in the Editor as a work around to entities conversion limitation. It should not be a public component that can be added by the user. * Serialization code is now generated also for Component/Buffers/Commands/Rpcs that have internal visibility. * The GhostCollectionSystem.CreatePredictedSpawnPrefab API is deprecated as clients will now automatically have predict spawned ghost prefabs set up for them. They can instantiate prefabs the normal way and don't need to call this API. * Child entities in Ghosts now default to the `DontSerializeVariant` as serializing child ghosts is relatively expensive (due to poor 'locality of reference' of child entities in other chunks, and the random-access nature of iterating child entities). Thus, `GhostComponentAttribute.SendDataForChildEntity = false` is now the default, and you'll need to set this flag to true for all types that should be sent for children. If you'd like to replicate hierarchies, we strongly encourage you to create multiple ghost prefabs, with custom, faked transform parenting logic that keeps the hierarchy flat. Explicit child hierarchies should only be used if the snapshot updates of one hierarchy must be in sync. * `RegisterDefaultVariants` has changed signature to now use a `Rule`. This forces users to be explicit about whether or not they want their user-defined defaults to apply to child entities too. * You must now opt-into "Prefab Override" customization for a specific type, via either: **a)** Explicitly adding the `[SupportPrefabOverride]` attribute to the component. **b)** Explicitly adding a custom variant of a Component via `[GhostComponentVariation]`. **c)** Explicitly adding a default variant via `DefaultVariantSystemBase.RegisterDefaultVariant`. **Note:** You may also explicitly ban all overrides via the `[DontSupportPrefabOverride]` attribute. * `GhostComponentAttribute.OwnerPredictedSendType` has been renamed to `GhostComponentAttribute.SendTypeOptimization`. * Replaced obsolete EntityQueryBuilder APIs with current ones. * SnapshotSizeAligned, ChangeMaskArraySizeInUInts moved to the GhostComponentSerializer class. * DefaultUserParams has been renamed to DefaultSmoothingActionUserParams. * DefaultTranslateSmoothingAction has been renamed to DefaultTranslationSmoothingAction. ### Deprecated ### Removed * The static bool `RpcSystem.DynamicAssemblyList` has been removed, replaced by a non-static property with the same name. See upgrade guide (below). * `ClientServerBootstrap.RequestedAutoConnect` (an editor only property) has been replaced with `ClientServerBootstrap.TryFindAutoConnectEndPoint`. * The custom client/server top-level groups `ClientSimulationSystemGroup` and similar have been removed, use `[WorldSystemFilter]` and the built-in top-level groups instead. * `[UpdateInWorld]` has been removed, use `[WorldSystemFilter]` instead. * `ThinClientComponent` has been removed, use `World.IsThinClient()` instead. * PopulateList overload taking SystemBase, calls should use ref SystemState instead from ISystem. Internalized DynamicTypeList, this should not be used in user code. ### Fixed * An issue with prediction system that calculate on client the wrong number of tick to predict when a rollback occurs and the predicting tick wraps around 0. - A sudden increment in delta time and elapsed time when the client exit from game our disconnect from the server. * SourceGenerator errors not showing in the editor * Ghost physics proxy rotation not synched correctly in some cases (large angles) * A rare issue where predicted ghost entities might be spawned on a client before it had reached the correct predicted tick * Some rare interpolation tick rollback * restoring components and buffers from the backup didn't check the SendToOnwer settings. * Crash on Android/iOS when using il2cpp, caused by packet logger * OnUpdate for GhostSendSystem is now burst compiled * Ensure unique serial number when patching up entity guids * Ensure that we do not count zero update length in analytic results. Fix assertion error when entering and exiting playmode * Compilation errors when the DedicatedServer platform is selected. NOTE: this does not imply the dedicated server platform is supported by the NetCode package or any other packages dependencies. ### Security ### Upgrade guide * Prefer using the new unified `NetCodePhysicsConfig` authoring component instead of using the `LagCompensationConfig` authoring component to enable lag compensation. * Any calls to the static `RpcSystem.DynamicAssemblyList` should be replaced with instanced calls to the property with the same name. Ensure you do so during world creation, before `RpcSystem.OnUpdate` is called. See `SetRpcSystemDynamicAssemblyListSystem` for an example of this. * `ClientServerTickRate.MaxSimulationLongStepTimeMultiplier` is renamed to `ClientServerTickRate.MaxSimulationStepBatchSize`. * Any editor-only calls to `ClientServerBootstrap.RequestedAutoConnect` should be replaced with `ClientServerBootstrap.TryFindAutoConnectEndPoint`, which handles all `PlayTypes`. * The `NetworkStreamDisconnected` component has been removed, add a `ConnectionState` component to connections you want to detect disconnects for and use a reactive system. * When using the netcode logging system calls to `GetExistingSystem<NetDebugSystem>().NetDebug` must be replaced with `GetSingleton<NetDebug>()`, or `GetSingletonRW<NetDebug>` if you are changing the log level. * Calls to `GetExistingSystem<GhostSimulationSystemGroup>().SpawnedGhostEntityMap` must be replaced with `GetSingleton<SpawnedGhostEntityMap>().Value`. Waiting for or setting `LastGhostMapWriter` is no longer required and should be removed. * Calls to `GetExistingSystem<GhostSendSystem>().GhostRelevancySet` and `GetExistingSystem<GhostSendSystem>().GhostRelevancyMode` must be replaced with `GetSingletonRW<GhostRelevancy>.GhostRelevancySet` and `GetSingletonRW<GhostRelevancy>.GhostRelevancyMode`. Waiting for or setting `GhostRelevancySetWriteHandle` is no longer required and should be removed. * Calls to `GetExistingSystem<NetworkStreamReceiveSystem>().Connect` and `GetExistingSystem<NetworkStreamReceiveSystem>().Listen` must be replaced with `GetSingletonRW<NetworkStreamDriver>.Connect` and `GetSingletonRW<NetworkStreamDriver>.Listen`. * Usage of `ThinClientComponent` must be replaced with calls to `World.IsThinClient()`. * The netcode specific top-level system groups and `[UpdateInWorld]` have been removed, the replacement is `[WorldSystemFilter]` and the mappings are * `[UpdateInGroup(typeof(ClientInitializationSystemGroup))]` => `[UpdateInGroup(typeof(InitializationSystemGroup))][WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]` * `[UpdateInGroup(typeof(ClientSimulationSystemGroup))]` => `[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]` * `[UpdateInGroup(typeof(ClientPresentationSystemGroup))]` => `[UpdateInGroup(typeof(PresentationSystemGroup)]` * `[UpdateInGroup(typeof(ServerInitializationSystemGroup))]` => `[UpdateInGroup(typeof(InitializationSystemGroup))][WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]` * `[UpdateInGroup(typeof(ServerSimulationSystemGroup))]` => `[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]` * `[UpdateInGroup(typeof(ClientAndServerInitializationSystemGroup))]` => `[UpdateInGroup(typeof(InitializationSystemGroup))][WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation | WorldSystemFilterFlags.ClientSimulation)]` * `[UpdateInGroup(typeof(ClientAndServerSimulationSystemGroup))]` => `[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation | WorldSystemFilterFlags.ClientSimulation)]` * `[UpdateInWorld(TargetWorld.Client)]` => `[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]` * `[UpdateInWorld(TargetWorld.Server)]` => `[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]` * `[UpdateInWorld(TargetWorld.ClientAndServer)]` => `[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation | WorldSystemFilterFlags.ClientSimulation)]` * `[UpdateInWorld(TargetWorld.Default)]` => `[WorldSystemFilter(WorldSystemFilterFlags.LocalSimulation)]` * `if (World.GetExistingSystem<ServerSimulationSystemGroup>()!=null)` => `if (World.IsServer())` * `if (World.GetExistingSystem<ClientSimulationSystemGroup>()!=null)` => `if (World.IsClient())` * The `GhostCollectionSystem.CreatePredictedSpawnPrefab` API has been removed as clients will now automatically have predict spawned ghost prefabs set up for them. They can instantiate prefabs the normal way and don't need to call this API. * `GhostPredictionSystemGroup` has been renamed to `PredictedSimulationSystemGroup`. * All `GhostAuthoringComponent` `ComponentOverrides` have been clobbered during the upgrade (apologies!). Please re-apply all `ComponentOverrides` via the new (optional) `GhostAuthoringInspectionComponent`. Caveat: Prefer to use attributes wherever possible, as this "manual" form of overriding should only be used for one-off differences that you're unable to express via attributes. * Inside your `RegisterDefaultVariants` method, replace all `defaultVariants.Add(new ComponentType(typeof(SomeType)), typeof(SomeTypeDefaultVariant));` with `defaultVariants.Add(new ComponentType(typeof(SomeType)), Rule.OnlyParent(typeof(SomeTypeDefaultVariant)));`, unless you _also_ want this variant to be applied to children (in which case, use `Rule.ParentAndChildren(typeof(SomeTypeDefaultVariant))`). ### Use the new NetworkTime component All the information in regards the current simulated tick MUST be retrieved from the singleton NetworkTime. In particular: * The GhostPredictionSystemGroup.PredictedTick has been removed. You must always use the NetworkTime.ServerTick instead. The ServerTick value will correcly reflect the current predicted tick when inspected inside the prediction loop. * The GhostPredictionSystemGroup.IsFinalPredictionTick has been removed. Use the NetworkTime.IsFinalPredictionTick property instead. * The ClientSimulationSystemGroup ServerTick, ServerTickFraction, InterpolationTick and InterpolationTickFraction has been removed. You can retrieve the same properties from the NetworkTime singleton. Please refer to the `NetworkTime` component documentation for further information about the different timing properties and the flags behaviours.
1 parent 3890a43 commit e24c89b

File tree

417 files changed

+37498
-12035
lines changed

Some content is hidden

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

417 files changed

+37498
-12035
lines changed

.footignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ValidationExceptions.json

CHANGELOG.md

Lines changed: 127 additions & 23 deletions
Large diffs are not rendered by default.

Documentation~/TableOfContents.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* [Ghost snapshots](ghost-snapshots.md)
88
* [Prediction](prediction.md)
99
* [Time synchronization](time-synchronization.md)
10+
* [Optimizations](optimizations.md)
1011
* [Logging](logging.md)
1112
* [Physics](physics.md)
1213
* [Ghost types and variants](ghost-types-templates.md)

Documentation~/client-server-worlds.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ The default number of simulation ticks is 60. The component also has values for
7676
* `Sleep` for `Application.TargetFrameRate` to reduce CPU load
7777
* `Auto` to use `Sleep` on headless servers and `BusyWait` otherwise
7878

79-
The client updates at a dynamic time step, with the exception of prediction code which always runs at a fixed time step to match the server. The prediction runs in the [GhostPredictionSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.GhostPredictionSystemGroup.html) and applies its own fixed time step for prediction.
79+
The client updates at a dynamic time step, with the exception of prediction code which always runs at a fixed time step to match the server. The prediction runs in the [PredictedSimulationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.PredictedSimulationSystemGroup.html) and applies its own fixed time step for prediction.
8080

8181
## Standalone builds
8282

@@ -86,7 +86,7 @@ To build a client-only game, add the ```UNITY_CLIENT``` define to the __Scriptin
8686

8787
## World migration
8888

89-
Sometimes you want to be able to destroy the world you are in and spin up another world without loosing your connection state. In order to do this we supply a DriverMigrationSystem, that allows a user to Store and Load Transport related information so a smooth world transition can be made.
89+
Sometimes you want to be able to destroy the world you are in and spin up another world without loosing your connection state. In order to do this we supply a DriverMigrationSystem, that allows a user to Store and Load Transport related information so a smooth world transition can be made.
9090

9191
```
9292
public World MigrateWorld(World sourceWorld)
@@ -109,4 +109,16 @@ public World MigrateWorld(World sourceWorld)
109109
110110
return ClientServerBootstrap.CreateServerWorld(DefaultWorld, newWorld.Name, newWorld);
111111
}
112-
```
112+
```
113+
114+
## Thin Clients
115+
116+
Thin clients are a tool to help test and debug in the editor by running simulated dummy clients with your normal client and server worlds. See the _Playmode Tools_ section above for how to configure them
117+
118+
These clients are heavily stripped down and should run as little logic as possible so they don't put a heavy load on the CPU while testing. Each thin client added adds a little bit of extra work to be computed each frame.
119+
120+
Only systems which have explicitly been set up to run on thin client worlds will run, marked with the `WorldSystemFilterFlags.ThinClientSimulation` flag on the `WorldSystemFilter` attribute. No rendering is done for thin client data so they are invisible to the presentation.
121+
122+
In some cases like in `MonoBehaviour` scripts you might need to check if it's running on a thin client and then early out or cancel processing, the `World.IsThinClient()` can be used in those cases.
123+
124+
Most commonly the only important work they need to do is generate random inputs for the server to process. These inputs usually need to be added to a manually created dummy entity as no ghost spawning is done on thin clients. Not even for it's own local ghost/player.

Documentation~/command-stream.md

Lines changed: 154 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,190 @@ When you need to access inputs on the client and server, it is important to read
1616

1717
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 buffer.
1818

19+
## Automatic command input setup using IInputComponentData
20+
21+
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.
22+
23+
> [!NOTE]
24+
> 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.
25+
>
26+
>[!NOTE]
27+
> 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.
28+
29+
### Input events
30+
31+
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.
32+
33+
### How it works
34+
35+
Given an input component data you'll have these systems set up.
36+
37+
- Gather input system
38+
- Take input events and save in the input component data
39+
- Process input system
40+
- Take current input component and process the values
41+
42+
With `IInputComponentData` netcode handling it looks like this with code generated systems.
43+
44+
- _Gather input system_
45+
- _Take input events and save in an input component data_
46+
- Copy input to command buffer
47+
- Take current input data component and add to command buffer, also recording current tick
48+
- Apply inputs for current tick to input component data
49+
- 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)).
50+
- _Process input system_
51+
- _Take current input component and process the values_
52+
53+
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.
54+
55+
### Example code
56+
57+
Simple input values for character movement (with jumping):
58+
59+
```c#
60+
using Unity.Entities;
61+
using Unity.NetCode;
62+
63+
[GenerateAuthoringComponent]
64+
public struct PlayerInput : IInputComponentData
65+
{
66+
public int Horizontal;
67+
public int Vertical;
68+
public InputEvent Jump;
69+
}
70+
```
71+
72+
Input gathering system, it basically takes current inputs and applies to the input component data on the local players entity.
73+
74+
```c#
75+
[UpdateInGroup(typeof(GhostInputSystemGroup))]
76+
[AlwaysSynchronizeSystem]
77+
public partial class GatherInputs : SystemBase
78+
{
79+
protected override void OnCreate()
80+
{
81+
RequireForUpdate<PlayerInput>();
82+
}
83+
84+
protected override void OnUpdate()
85+
{
86+
bool jump = UnityEngine.Input.GetKeyDown("space");
87+
bool left = UnityEngine.Input.GetKey("left");
88+
//...
89+
90+
var networkId = GetSingleton<NetworkIdComponent>().Value;
91+
Entities
92+
.WithName("GatherInput")
93+
.ForEach((ref PlayerInput inputData, ref GhostOwnerComponent owner) =>
94+
{
95+
if (owner.NetworkId != networkId)
96+
return;
97+
98+
inputData = default;
99+
100+
if (jump)
101+
inputData.Jump.Set();
102+
if (left)
103+
inputData.Horizontal -= 1;
104+
//...
105+
}).ScheduleParallel();
106+
}
107+
}
108+
```
109+
110+
Processing input system, takes current input values stored on the players input component and applies the equivalent movement actions.
111+
112+
```c#
113+
[UpdateInGroup(typeof(PredictedSimulationSystemGroup))]
114+
public partial class ProcessInputs : SystemBase
115+
{
116+
protected override void OnCreate()
117+
{
118+
RequireForUpdate<PlayerInput>();
119+
}
120+
protected override void OnUpdate()
121+
{
122+
var movementSpeed = Time.DeltaTime * 3;
123+
Entities.WithAll<Simulate>().WithName("ProcessInputForTick").ForEach(
124+
(ref PlayerInput input, ref Translation trans, ref PlayerMovement movement) =>
125+
{
126+
if (input.Jump.IsSet)
127+
movement.JumpVelocity = 10; // start jump routine
128+
129+
// handle jump event logic, movement logic etc
130+
}).ScheduleParallel();
131+
}
132+
}
133+
```
134+
19135
## Manual serialization
20136

21137
In order to implement serialization manually you need to add the `[NetCodeDisableCommandCodeGen]` attribute to the struct implementing the `ICommandData` interface.
22138

23-
You will also need to create a struct implementing `ICommandDataSerializaer<T>` - where `<T>` is your `ICommandData` struct.
139+
You will also need to create a struct implementing `ICommandDataSerializer<T>` - where `<T>` is your `ICommandData` struct.
24140

25-
[ICommandDataSerializaer](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ICommandDataSerializer-1.html) has two __Serialize__ and two __Deserialize__ methods: one pair for raw values, and one pair for delta compressed values. The system sends multiple inputs in each command packet. The first packet contains raw data but the rest are compressed using delta compression. Delta compression compresses inputs well because the rate of change is low.
141+
[ICommandDataSerializer](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ICommandDataSerializer-1.html) has two __Serialize__ and two __Deserialize__ methods: one pair for raw values, and one pair for delta compressed values. The system sends multiple inputs in each command packet. The first packet contains raw data but the rest are compressed using delta compression. Delta compression compresses inputs well because the rate of change is low.
26142

27143
As well as creating a struct you need to create specific instances of the generic systems `CommandSendSystem` and `CommandReceiveSystem`. To do this, extend the base system, for example with
28144
```c#
29-
public class MyCommandSendCommandSystem : CommandSendSystem<MyCommandSerializer, MyCommand>
145+
[UpdateInGroup(typeof(CommandSendSystemGroup))]
146+
[BurstCompile]
147+
public partial struct MyCommandSendCommandSystem : ISystem
30148
{
149+
CommandSendSystem<MyCommandSerializer, MyCommand> m_CommandSend;
31150
[BurstCompile]
32151
struct SendJob : IJobEntityBatch
33152
{
34-
public SendJobData data;
153+
public CommandSendSystem<MyCommandSerializer, MyCommand>.SendJobData data;
35154
public void Execute(ArchetypeChunk chunk, int orderIndex)
36155
{
37156
data.Execute(chunk, orderIndex);
38157
}
39158
}
40-
protected override void OnUpdate()
159+
[BurstCompile]
160+
public void OnCreate(ref SystemState state)
161+
{
162+
m_CommandSend.OnCreate(ref state);
163+
}
164+
[BurstCompile]
165+
public void OnDestroy(ref SystemState state)
166+
{}
167+
[BurstCompile]
168+
public void OnUpdate(ref SystemState state)
41169
{
42-
var sendJob = new SendJob{data = InitJobData()};
43-
ScheduleJobData(sendJob);
170+
if (!m_CommandSend.ShouldRunCommandJob(ref state))
171+
return;
172+
var sendJob = new SendJob{data = m_CommandSend.InitJobData(ref state)};
173+
state.Dependency = sendJob.Schedule(m_CommandSend.Query, state.Dependency);
44174
}
45175
}
46-
public class MyCommandReceiveCommandSystem : CommandReceiveSystem<MyCommandSerializer, MyCommand>
176+
[UpdateInGroup(typeof(CommandReceiveSystemGroup))]
177+
[BurstCompile]
178+
public partial struct MyCommandReceiveCommandSystem : ISystem
47179
{
180+
CommandReceiveSystem<MyCommandSerializer, MyCommand> m_CommandRecv;
48181
[BurstCompile]
49182
struct ReceiveJob : IJobEntityBatch
50183
{
51-
public ReceiveJobData data;
184+
public CommandReceiveSystem<MyCommandSerializer, MyCommand>.ReceiveJobData data;
52185
public void Execute(ArchetypeChunk chunk, int orderIndex)
53186
{
54187
data.Execute(chunk, orderIndex);
55188
}
56189
}
57-
protected override void OnUpdate()
190+
[BurstCompile]
191+
public void OnCreate(ref SystemState state)
192+
{
193+
m_CommandRecv.OnCreate(ref state);
194+
}
195+
[BurstCompile]
196+
public void OnDestroy(ref SystemState state)
197+
{}
198+
[BurstCompile]
199+
public void OnUpdate(ref SystemState state)
58200
{
59-
var recvJob = new ReceiveJob{data = InitJobData()};
60-
ScheduleJobData(recvJob);
201+
var recvJob = new ReceiveJob{data = m_CommandRecv.InitJobData(ref state)};
202+
state.Dependency = recvJob.Schedule(m_CommandRecv.Query, state.Dependency);
61203
}
62204
}
63205
```

0 commit comments

Comments
 (0)