### Client input packet dump example Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/testing/logging.html Example output from a client world dump showing the input packet dump. It includes the CommandSendSystem prefix [CSS], the input type name and hash, and details about the entity and input commands being sent. The dump breaks down the bit sizes for each field, including stableHash, commandSize, autoCommandTargetGhost, numCommandsToSend, and the serialized input commands. ```text [CSS][ShipCommandData:15257441568649283849] Sent for inputTargetTick: 262 | Entity(1205:3) on GhostInst[type:0|id:191,st:56] | isAutoTarget:True | stableHash: 64 bits [8 bytes] | commandSize: 16 bits [2 bytes] | autoCommandTargetGhost: 64 bits [8 bytes] | numCommandsToSend(4): 5 bits [b]=[355|→-1 ↑-1] (tick: 32 bits [4 bytes]) (data: 8 bits) [1]=[354|→-1 ↑-1] (cb: 0) (tΔ: 2 bits) [2]=[353|→-1 ↑-1] (cb: 0) (tΔ: 2 bits) [3]=[352|→1 ↑-1] (cb: 1) (tΔ: 2 bits) (data: 6 bits) | payloadTicks: 38 bits [5 bytes] | payload: 10 bits [2 bytes] | changeBits: 3 bits | flush: 5 bits --- 208 bits [26 bytes] ``` -------------------------------- ### Manual command serialization and system implementation Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/command-stream.html This example shows the implementation of a custom command struct with manual serialization logic, followed by the required CommandSendSystem and CommandReceiveSystem definitions. ```csharp [NetCodeDisableCommandCodeGen] public struct MyCommand : ICommandData, ICommandDataSerializer { public NetworkTick Tick { get; set; } public int Value; public void Serialize(ref DataStreamWriter writer, in RpcSerializerState state, in MyCommand data) { writer.WriteInt(data.Value); } public void Deserialize(ref DataStreamReader reader, in RpcDeserializerState state, ref MyCommand data) { data.Value = reader.ReadInt(); } public void Serialize(ref DataStreamWriter writer, in RpcSerializerState state, in MyCommand data, in MyCommand baseline, StreamCompressionModel compressionModel) { // Don't do any delta compression for this example Serialize(ref writer, state, data); } public void Deserialize(ref DataStreamReader reader, in RpcDeserializerState state, ref MyCommand data, in MyCommand baseline, StreamCompressionModel compressionModel) { Deserialize(ref reader, state, ref data); } } [UpdateInGroup(typeof(CommandSendSystemGroup))] [BurstCompile] public partial struct MyCommandSendCommandSystem : ISystem { CommandSendSystem m_CommandSend; [BurstCompile] struct SendJob : IJobChunk { public CommandSendSystem.SendJobData data; public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { data.Execute(chunk, unfilteredChunkIndex); } } [BurstCompile] public void OnCreate(ref SystemState state) { m_CommandSend.OnCreate(ref state); } [BurstCompile] public void OnUpdate(ref SystemState state) { if (!m_CommandSend.ShouldRunCommandJob(ref state)) return; var sendJob = new SendJob{data = m_CommandSend.InitJobData(ref state)}; state.Dependency = sendJob.Schedule(m_CommandSend.Query, state.Dependency); } } [UpdateInGroup(typeof(CommandReceiveSystemGroup))] [BurstCompile] public partial struct MyCommandReceiveCommandSystem : ISystem { CommandReceiveSystem m_CommandRecv; [BurstCompile] struct ReceiveJob : IJobChunk { public CommandReceiveSystem.ReceiveJobData data; public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { data.Execute(chunk, unfilteredChunkIndex); } } [BurstCompile] public void OnCreate(ref SystemState state) { m_CommandRecv.OnCreate(ref state); } [BurstCompile] public void OnUpdate(ref SystemState state) { var recvJob = new ReceiveJob{data = m_CommandRecv.InitJobData(ref state)}; state.Dependency = recvJob.Schedule(m_CommandRecv.Query, state.Dependency); } } ``` -------------------------------- ### Server input packet dump example Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/testing/logging.html Example output from a server world dump showing the received command packet. It includes the CommandReceiveSystem prefix [CRS], the entity and ghost instance, the target tick, arrival tick, margin, and the list of input commands with their change bits and a 'Late!' marker for a late input. ```text [CRS][3480158943696179440] Received command packet from Entity(623:9) on GhostInst[type:??|id:191,st:56] targeting tick 355: | arrivalTick:353 | margin:2 [b]=[355|→-1 ↑-1] [1]=[354|→-1 ↑-1] (cb:0) [2]=[353|→-1 ↑-1] (cb:0) [3]=[352|→1 ↑-1] (cb:1) Late! --- 26 bytes ``` -------------------------------- ### Download migration data with DownloadMigrationDataAsync Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/host-migration/lobby-relay-integration.html Use this snippet to download migration data as the new host. Pass the host migration data info structure to DownloadMigrationDataAsync. This executes an HTTP GET request using UnityWebRequest. ```csharp byte[] data = await LobbyService.Instance.DownloadMigrationDataAsync(info); ``` -------------------------------- ### Send RPC using RpcQueue in a client simulation system Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/rpcs.html This example shows a client simulation system that sends an RPC using the RpcQueue when the space bar is pressed. It requires the RpcCollection and NetworkId components, and uses GetRpcQueue() to obtain the queue. ```csharp [WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)] public partial struct ClientQueueRpcSendSystem : ISystem { public void OnCreate(ref SystemState state) { state.RequireForUpdate(); state.RequireForUpdate(); } public void OnUpdate(ref SystemState state) { if (Input.GetKey("space")) { var ghostFromEntity = state.GetComponentLookup(true); var rpcQueue = SystemAPI.GetSingleton().GetRpcQueue(); foreach (var rpcDataStreamBuffer in SystemAPI.Query>()) { rpcQueue.Schedule(rpcDataStreamBuffer, ghostFromEntity, new OurRpcCommandSerializer()); } } } } ``` -------------------------------- ### MigrateDataToNewServerWorld helper function Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/host-migration/host-migration-systems.html Creates a new server world using the provided driver constructor, sets the host migration data, listens on AnyIpv4, and connects the client world via IPC. Returns false if listening fails. Logs a warning if no migration data is provided. ```csharp public static bool MigrateDataToNewServerWorld(INetworkStreamDriverConstructor driverConstructor, ref NativeArray migrationData) { var oldConstructor = NetworkStreamReceiveSystem.DriverConstructor; NetworkStreamReceiveSystem.DriverConstructor = driverConstructor; var serverWorld = ClientServerBootstrap.CreateServerWorld("ServerWorld"); NetworkStreamReceiveSystem.DriverConstructor = oldConstructor; if (migrationData.Length == 0) Debug.LogWarning($"No host migration data given during host migration, no data will be deployed."); else HostMigrationUtility.SetHostMigrationData(serverWorld, migrationData); using var serverDriverQuery = serverWorld.EntityManager.CreateEntityQuery(ComponentType.ReadWrite()); var serverDriver = serverDriverQuery.GetSingletonRW(); if (!serverDriver.ValueRW.Listen(NetworkEndpoint.AnyIpv4)) { Debug.LogError($"NetworkStreamDriver.Listen() failed"); return false; } var ipcPort = serverDriver.ValueRW.GetLocalEndPoint(serverDriver.ValueRW.DriverStore.FirstDriver).Port; // The client driver needs to be recreated, and then directly connected to new server world via IPC return ConfigureClientAndConnect(ClientServerBootstrap.ClientWorld, driverConstructor, NetworkEndpoint.LoopbackIpv4.WithPort(ipcPort)); } ``` -------------------------------- ### GhostField inheritance example Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/ghostfield-synchronize.html Shows how a [GhostField] attribute on a non-primitive field is inherited by subfields that don't have their own attribute. In this example, Value.x inherits the parent's quantization (1000) while Value.y keeps its own (100). ```csharp public struct Vector2 { public float x; [GhostField(Quantization = 100)] public float y; } public struct MyComponent : IComponentData { //Value.x will inherit the quantization value specified by the parent definition (1000). //Value.y will maintain its original quantization value (100). [GhostField(Quantization = 1000)] public Vector2 Value; } ``` -------------------------------- ### Create client, server, and thin client worlds manually Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/client-server-worlds.html Call ClientServerBootstrap.CreateClientWorld and CreateServerWorld to create client and server worlds. For soak testing, set AutomaticThinClientWorldsUtility.NumThinClientsRequested and call BootstrapThinClientWorlds. ```csharp void OnPlayButtonClicked() { // Typically this: var clientWorld = ClientServerBootstrap.CreateClientWorld("ClientWorld"); // And/Or this: var serverWorld = ClientServerBootstrap.CreateServerWorld("ServerWorld"); // And/Or something like this, for soak testing: AutomaticThinClientWorldsUtility.NumThinClientsRequested = 10; AutomaticThinClientWorldsUtility.BootstrapThinClientWorlds(); } ``` -------------------------------- ### GoInGameServerSystem OnCreate with CubeSpawner Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/networked-cube.html Updated GoInGameServerSystem.OnCreate method that requires CubeSpawner and an entity query for GoInGameRequest and ReceiveRpcCommandRequest, and initializes the NetworkId lookup. ```csharp [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate(); var builder = new EntityQueryBuilder(Allocator.Temp) .WithAll() .WithAll(); state.RequireForUpdate(state.GetEntityQuery(builder)); networkIdFromEntity = state.GetComponentLookup(true); } ``` -------------------------------- ### GhostComponent attribute usage example Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/ghostcomponentattribute.html Shows how to apply GhostComponentAttribute with properties to a component. Requires GhostFieldAttribute on fields for serialization. ```csharp [GhostComponent(PrefabType=GhostPrefabType.All, SendTypeOptimization=GhostSendType.OnlyInterpolatedClients, SendDataForChildEntity=false)] public struct MyComponent : IComponentData { [GhostField(Quantization = 1000)] public float3 Value; } ``` -------------------------------- ### Create CubeAuthoring.cs for ghost prefab Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/networked-cube.html Create a CubeAuthoring.cs file with an IComponentData struct and a baker that adds the component to the entity. Add this component to the Cube prefab before attaching the Ghost Authoring Component. ```csharp public struct Cube : IComponentData { } [DisallowMultipleComponent] public class CubeAuthoring : MonoBehaviour { class CubeBaker : Baker { public override void Bake(CubeAuthoring authoring) { var entity = GetEntity(TransformUsageFlags.Dynamic); AddComponent(entity); } } } ``` -------------------------------- ### Set up CommandTarget for thin client input Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/testing/thin-clients.html Sets up a thin client to send input by creating an entity with the input component and its input buffer, then pointing the connection entity's CommandTarget to that entity. Place this in a system filtered with [WorldSystemFilter(WorldSystemFilterFlags.ThinClientSimulation)]. The IDE may show a missing assembly definition error for the generated buffer type, but it will compile. ```csharp var myDummyGhostCharacterControllerEntity = state.EntityManager.CreateEntity(typeof(MyNamespace.MyInputComponent), typeof(InputBufferData)); var myConnectionEntity = SystemAPI.GetSingletonEntity(); // This tells the netcode package which entity it should be sending inputs for. state.EntityManager.SetComponentData(myConnectionEntity, new CommandTarget { targetEntity = myDummyGhostCharacterControllerEntity }); ``` -------------------------------- ### Assign default variant for LocalTransform Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/ghost-variants.html Shows how to specify the default variant for a type using DefaultVariantSystemBase. This example ensures LocalTransform uses TransformDefaultVariant. ```csharp sealed partial class DefaultVariantSystem : DefaultVariantSystemBase { protected override void RegisterDefaultVariants(Dictionary defaultVariants) { defaultVariants.Add(typeof(LocalTransform), Rule.OnlyParents(typeof(TransformDefaultVariant))); } } ``` -------------------------------- ### Register default variants for special types Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/ghost-variants.html Shows how to register default variants for special component types using DefaultVariantSystemBase. This example assigns ClientOnlyVariant, ServerOnlyVariant, and DontSerializeVariant to specific components. ```csharp sealed partial class SpecialVariantSystem : DefaultVariantSystemBase { protected override void RegisterDefaultVariants(Dictionary defaultVariants) { defaultVariants.Add(typeof(SomeClientOnlyComponent), Rule.ForAll(typeof(ClientOnlyVariant))); defaultVariants.Add(typeof(SomeServerOnlyComponent), Rule.ForAll(typeof(ServerOnlyVariant))); defaultVariants.Add(typeof(NoNeedToSyncComponent), Rule.ForAll(typeof(DontSerializeVariant))); } } ``` -------------------------------- ### CubeInputAuthoring and SampleCubeInput system Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/networked-cube.html Defines the CubeInput component and authoring/baking script for the networked cube. The SampleCubeInput system fills input data from keyboard keys (left/right/down/up) into the CubeInput component for the local ghost owner. Requires the NetworkStreamInGame and CubeSpawner components to be present. ```csharp public struct CubeInput : IInputComponentData { public int Horizontal; public int Vertical; } [DisallowMultipleComponent] public class CubeInputAuthoring : MonoBehaviour { class CubeInputBaking : Unity.Entities.Baker { public override void Bake(CubeInputAuthoring authoring) { var entity = GetEntity(TransformUsageFlags.Dynamic); AddComponent(entity); } } } [UpdateInGroup(typeof(GhostInputSystemGroup))] public partial struct SampleCubeInput : ISystem { public void OnCreate(ref SystemState state) { state.RequireForUpdate(); state.RequireForUpdate(); } public void OnUpdate(ref SystemState state) { foreach (var playerInput in SystemAPI.Query>().WithAll()) { playerInput.ValueRW = default; if (Input.GetKey("left")) playerInput.ValueRW.Horizontal -= 1; if (Input.GetKey("right")) playerInput.ValueRW.Horizontal += 1; if (Input.GetKey("down")) playerInput.ValueRW.Vertical -= 1; if (Input.GetKey("up")) playerInput.ValueRW.Vertical += 1; } } } ``` -------------------------------- ### Filter a system with WorldSystemFilter Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/client-server-worlds.html Use the WorldSystemFilter attribute to specify the world types a system belongs to. This example makes MySystem present only for worlds that can run the client simulation (any world with WorldFlags.GameClient set). ```csharp [WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)] public partial class MySystem : SystemBase { protected override void OnUpdate() { // ... } } ``` -------------------------------- ### Ghost prefab configurations for Player and Gun Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/ghost-groups.html Example ghost prefab configurations for a Player and Gun in a First-Person Shooter. The Player is dynamic with a GhostGroup buffer, while the Gun is static with lower importance and send rate. ```text 'Player' Ghost Prefab Importance:100, Max Send Rate:60, Owner Predicted, Has Owner, Dynamic, RelevantWithinRadius:1km, DynamicBuffer (Count:0) ``` ```text 'Gun' Ghost Prefab Importance:10, MaxSendRate:10, Owner Predicted, Has Owner, Static, RelevantWithinRadius:200m ``` -------------------------------- ### Download migration data and create new server world Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/host-migration/host-migration-systems.html Downloads migration data from the lobby, creates a relay allocation, constructs a driver with relay data, copies the migration data into a NativeArray, and calls MigrateDataToNewServerWorld. Logs an error if migration fails. ```csharp var migrationData = await LobbyService.Instance.DownloadMigrationDataAsync(m_MigrationConfig, new LobbyDownloadMigrationDataOptions()); var allocation = await RelayService.Instance.CreateAllocationAsync(10); var hostRelayData = allocation.ToRelayServerData("dtls"); var driverConstructor = new HostMigrationDriverConstructor(hostRelayData, new RelayServerData()); var arrayData = new NativeArray(migrationData.Data.Length, Allocator.Temp); var slice = new NativeSlice(arrayData); slice.CopyFrom(migrationData.Data); if (!HostMigration.MigrateDataToNewServerWorld(driverConstructor, ref arrayData)) { Debug.LogError($"Host migration failed while migrating data to new server world"); } ``` -------------------------------- ### Get NetworkTime singleton and server tick Source: https://docs.unity3d.com/Packages/com.unity.netcode%406.6/manual/time-synchronization.html Retrieves the NetworkTime singleton and the current server tick. Use this to access simulated/predicted tick and other time-related properties on both client and server, inside or outside the prediction loop. ```csharp var networkTime = SystemAPI.GetSingleton(); var currentTick = networkTime.ServerTick; // ... ```