Search Unity

Question How can we send IInputComponentData from thin clients to server?

Discussion in 'NetCode for ECS' started by RamType0, Dec 20, 2022.

  1. RamType0

    RamType0

    Joined:
    Sep 11, 2018
    Posts:
    67
    https://docs.unity3d.com/Packages/c...manual/client-server-worlds.html#thin-clients

    It is documented that
    But how?
    How can we make the dummy entity whose input is applied to the ghost in the server?
     
    ArgenticsMT likes this.
  2. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    94
    Here is my ThinClientInputSystem code. I create the entity here.

    Code (CSharp):
    1.     [WorldSystemFilter(WorldSystemFilterFlags.ThinClientSimulation)]
    2.     [UpdateInGroup(typeof(GhostInputSystemGroup))]
    3.     public partial class ThinClientInputSystem : SystemBase
    4.     {
    5.         protected override void OnCreate()
    6.         {
    7.             RequireForUpdate<NetworkStreamInGame>();
    8.         }
    9.  
    10.         protected override void OnUpdate()
    11.         {
    12.             Entity localInput = GetSingleton<CommandTargetComponent>().targetEntity;
    13.  
    14.             if (localInput == Entity.Null || !EntityManager.HasComponent<PlayerInput>(localInput))
    15.             {
    16.                 var ent = EntityManager.CreateEntity();
    17.                 EntityManager.AddBuffer<PlayerInput>(ent);
    18.                 SystemAPI.SetSingleton(new CommandTargetComponent{targetEntity = ent});
    19.                 return;
    20.             }
    21.  
    22.             if (!TryGetSingleton(out NetworkTime networkTime))
    23.                 return;
    24.  
    25.             float horizontal = 0f;
    26.             float vertical = 1f;
    27.             var playerInputFromEntity = GetBufferLookup<PlayerInput>();
    28.             var inputTargetTick = networkTime.ServerTick;
    29.  
    30.             SystemAPI.TryGetSingletonEntity<PlayerInput>(out var targetEntity);
    31.  
    32.             Job.WithCode(() =>
    33.             {
    34.                 if (targetEntity != Entity.Null)
    35.                 {
    36.                     if (playerInputFromEntity.HasBuffer(targetEntity))
    37.                     {
    38.                         var input = playerInputFromEntity[targetEntity];
    39.                         input.AddCommandData(new PlayerInput()
    40.                         {
    41.                             Tick = inputTargetTick,
    42.                             Move = new float2(horizontal, vertical)
    43.                         });
    44.                     }
    45.                 }
    46.             }).Schedule();
    47.         }
    48.     }
     
  3. RamType0

    RamType0

    Joined:
    Sep 11, 2018
    Posts:
    67
    Should we need to replace all IInputComponentData with ICommandData ?
     
    ArgenticsMT likes this.
  4. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    94
    I don't know why I chose ICommandData over IInputComponentData. I'm afraid I don't know much about the difference between them yet.
     
  5. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    894
    You can still use the IInputComponentData but there is some manual step to do. We will provide a sample showcasing that but meanwhile:

    Code (csharp):
    1.  
    2. // Create a dummy entity to store the thin clients inputs.
    3. var ent = EntityManager.CreateEntity();
    4.  
    5. // Set the ghost owner
    6. var connectionId = SystemAPI.GetSingleton<NetworkIdComponent>().Value;
    7. EntityManager.AddComponentData(ent, new GhostOwnerComponent() { NetworkId = connectionId });
    8.  
    9. // Add the IInputComponent to it
    10. EntityManager.AddComponent<MyNamespace.MyInputComponentInputBufferData>(ent);
    11.  
    12. // When using IInputComponentData the entity will need the input component and its generated
    13.  // buffer. The buffer is added to the same namespace where the MyInputComponentInputBufferData has been declared, ex: MyNamespace.Generated.MyInputComponentInputBufferData.
    14. EntityManager.AddComponent<MyNamespace.Generated.MyInputComponentInputBufferData>(ent);
    15.  
    16. // Because auto-command does not work for thin clients you need to setup the command target.
    17. SystemAPI.SetSingleton(new CommandTargetComponent { targetEntity = ent });
    18.  
     
    Kmsxkuse likes this.
  6. ArgenticsMT

    ArgenticsMT

    Joined:
    Dec 9, 2022
    Posts:
    3
    I can't find MyInputComponentInputBufferData, there is no Generated namespace.
    I'm using Netcode for Entities 1.0.0-pre.15
     
    Last edited: Jan 3, 2023
  7. wrp8314

    wrp8314

    Joined:
    May 13, 2020
    Posts:
    6
    I tried to add it this way and it seems to work, the component is added but the server doesn't accept commands. I do not know the reason. perhaps you can do it.

    Code (CSharp):
    1. EntityManager.AddComponent(ent, System.Type.GetType("Assembly_CSharp.Generated.MyInputComponentInputBufferData"));
     
  8. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    280
    Right, currently you need to figure out the name of the generated component from the name of your input component. Like in this case the input component is in the MyNamespace namespace and named MyInputComponent. Unfortunately you can't "see" the generated component in your IDE with code completion etc as it doesn't see the generated files. You can find it yourself in the Temp/NetCodeGenerated/ folder, which is split into folders with the namespace names (in this case it would be in folder called MyNamespace and a file called MyNamespace.Generated_MyInputComponentInputBufferDataSerializer.cs

    We've shipped samples now which show this particular case, see the 06_ThinClients sample in the HelloNetcode sample collection. This sample reuses an input component from an earlier sample called
    CharacterControllerPlayerInput and you can see how it is manually added along with the generated buffer component for each thin client player created on the client.
     
  9. ArgenticsMT

    ArgenticsMT

    Joined:
    Dec 9, 2022
    Posts:
    3
    Thanks a lot!
    In my case file called Assembly_CSharp.Generated_InputCommandsInputBufferDataCommandSerializer.cs and InputCommandsInputBufferData was under Assembly_CSharp.Generated namespace. I don't use asmdef.