Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

DOTS Multiplayer discussion

Discussion in 'Data Oriented Technology Stack' started by PhilSA, Jun 14, 2019.

  1. Kelevra

    Kelevra

    Joined:
    Dec 27, 2012
    Posts:
    82
    @timjohansson Thank you for the answer!
    So RPC's don't share packed size with entities snapshots. Did I get it right?

    What is the best possible way to organize Response/Request flow for information that will be rarely sent? The question more about the best way of using the unity transport layer and what is better, create a separate driver or hook up into NetworkStreamRecieveSystem.
    Because, I've found that using entities RPC it's not very convenient, especially for sending arrays and writing all boilerplate code only for sending a message over the network.
     
  2. olenkaAtmoetsi

    olenkaAtmoetsi

    Joined:
    Apr 29, 2020
    Posts:
    6
    Thank you @timjohansson !
     
  3. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    Sorry to keep bothering @Jawsarn but I am a bit confused on how for #1 the code snippet showed that they are using predicted when spawning.

    Code (CSharp):
    1.  
    2.                else
    3.                 {
    4.                     bulletSpawnArchetype = EntityManager.CreateArchetype(
    5.                         ComponentType.ReadWrite<PredictedGhostSpawnRequestComponent>(),
    6.                         ComponentType.ReadWrite<BulletSnapshotData>());
    7.                 }
    That ^ "else" statement is run on clients. Why is an Archetype needed with those components fort predicting a spawn?

    (cc @timjohansson )
     
  4. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    @timjohansson what is the purpose of the CalculateVelocityJob in the asteroids sample?
     
  5. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    That is correct right now. We are planning to merge those two packets when possible, but we have lots of tasks with higher priority so it will probably be a while before we do.
    Using RPCs is better since you'll have more packets per frame if you add another way of sending packets. If you setup a second driver you would have to have two separate connect flows. We are planning to reduce the boilderplate for RPC messages, you could also write your own system which generates RPCs or build your own system which goes through a single RPC with dynamic content if you need it now. Our RPC request entities are essentially a layer on top of the low level RPC queues already.
     
  6. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    That is the archetype the current predictive spawn system operate on. On a per ghost type basis it goes through all those requests and spawn ghosts based on the content of the snapshot data as if it got that snapshot data from the server. When a snapshot arrives from the server you can compare against the predictive snapshot data and if they match up you mark it as a correct spawn. Snapshots which are not matched will be auto deleted after a while (but there is a bug with that in the current netcode release). We are trying to improve that flow to avoid the manual serialization in the new workflows we are currently working on.
     
    adammpolak likes this.
  7. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    To reduce bandwidth the velocity for bullets is not ghosted because it can be calculated from a constant and the rotation. For predicted bullets we do need to velocity or the prediction code will not work, so for all new spawned bullets which are predicted we calculate the velocity using that job.
     
    adammpolak likes this.
  8. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    thank you!
     
  9. Kelevra

    Kelevra

    Joined:
    Dec 27, 2012
    Posts:
    82
    @timjohansson Thank you a lot!
     
  10. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    148
     
    emkusa likes this.
  11. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    148
    @timjohansson I've posted the problem in some other thread and on issues a while ago without answer. But do you know about the problem of the serializers causing "InvalidProgramException: Passing an argument of size '10568'." and when it will be fixed? Right now I have to manually go update the IGhostSerializers to remove duplicate ComponentDataFromEntity (as child entities using same component create redudant ComponentDataFromEntity variables) when I generate ghosts.
     
    Last edited: Jun 15, 2020
  12. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    I was not aware of that problem until now. This should be fixed by the new workflows we are working on since that will only ever have one accessor per component type shared between the main entity and all children.
     
    Jawsarn likes this.
  13. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    26
    I wasn't even aware that such a restriction existed before the exception popped up.
    Can we not fix that by making the GhostSerializerCollection unmanaged and just pass a pointer around for it?
     
  14. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    @timjohansson

    Thank you for updating the sample projects! huge help!

    1. Is there a way to add a DynamicBuffer of CommandData directly onto a Gameobject using [GenerateAuthoringComponent] ?

    Currently I am still using:

    Code (CSharp):
    1. public class PlayerCommandDataAuthoringComponent : MonoBehaviour, IConvertGameObjectToEntity
    2. {
    3.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    4.     {
    5.         dstManager.AddBuffer<PlayerCommandData>(entity);
    6.     }
    7. }
    Not the biggest deal, but thought I would check for consistency in my project.

    2. Do I need to add Current Simulated Position/Rotation to all my Ghost objects? In the Asteroids sample project they are on ships/bullets/asteroids but I do not see them being called explicitly in the code. What happens if these are not included on Ghost objects?

    (cc @Jawsarn :) )
     
  15. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    Generally no - GenerateAuthoringComponent cannot deal with buffers containing more than one member in the data iirc. I don't know when or if a fix for that is planned as it is developed by another team.

    You should not add the CurrentSimulatedPos/Rot unless you explicitly enabled fixed timestep mode (it is not the default) and want to use render interpolation (rendering at a higher framerate than the simulation is running). The render interpolation predates dynamic timestep in netcode and is very limited - only supporting position and rotation. It might be removed going forward.
     
    adammpolak and WAYN_Games like this.
  16. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    You rock thank you @timjohansson !
     
  17. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    how do I disable fixed client tick rate?

    In the sample project GameMain.cs I see:

    `world.EntityManager.CreateEntity(typeof(FixedClientTickRate));`

    What should I be using instead?

    Edit, I found the solution but thought I would leave the comment in case anyone else was wondering:

    `world.EntityManager.CreateEntity(typeof(ClientServerTickRate));`
     
  18. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    19
    @timjohansson

    I am running into issues when trying to deploy a WebGL build.

    upload_2020-6-30_17-38-43.png

    I am guessing the issue is WebRTC not supporting the sockets used by the current Netcode.

    What would be the approach to get this working or is it a non-starter to build multiplayer games using Unity ECS/Netcode?

    I am guessing there needs to be some kind of an

    if (WebGL build) then use...[insert WebRTC interface here]

    at the Transport low level code.

    Or is this an il2cpp issue?
     
  19. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    You should not be using anything instead, just do not create a FixedClientTickRate singleton and you will run with dynamic time step.

    The ClientServerTickRate is not related to FixedClientTickRate, ClientServerTickRate is something you create in the server world to control simulation and network send frequency. FixedClientTickRate on the other hand is something you create on the client to switch to the fixed timestep. No matter which mode you pick ClientServerTickRate is used on the server to control the frequency, and the prediction group will always run at a fixed timestep.
     
    adammpolak likes this.
  20. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    We do not have any support for WebSockets yet. The way to get it working would be to write a new INetworkInterface implementation for the transport and use that instead of the standard one.
     
  21. pavelmo4alov

    pavelmo4alov

    Joined:
    Mar 13, 2013
    Posts:
    11
    Hello everyone!
    Help me please, I need create thin clients and generate fake input.
    1) Create. I now way by create custom bootstrap. Are there any other ways ?
    2) Fake input. I managed to make input from the server side ( generate physical parameters and apply thees, objects are moving ), but i need to make input from client side. I think, i need to write fake data to Input buffer in ClientSimulationSystemGroup at thin world, but i can't do this, because i can't find at what entity i must write buffer.
     
  22. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    The usual way is to change the number of thin clients in `Multiplayer > PlayModeTools`. If you want to do it from code you can just call `ClientSeverBootStrap.CreateClientWorld` (and add the thin client singleton) from any system to create more clients. I would probably put a system in the default world to do it.

    Yes, you should generate the input on the thin client. Since the thin client does not actually create the ghosts from the snapshots what I usually do is something like this pseudo code
    Code (CSharp):
    1. if (EntityManager.HasSingleton<ThinClientComponent>())
    2. {
    3.     if (EntityManager.GetSingleton<CommandTargetComponent>().targetEntity == Entity.Null)
    4.     {
    5.         var target = EntityManager.CreateEntity(typeof(MyInputBuffer));
    6.         EntityManager.SetSingleton(new CommandTargetComponent{targetEntity=target});
    7.     }
    8. }
    Then I just put fake inputs in that target entity I created.
     
  23. pavelmo4alov

    pavelmo4alov

    Joined:
    Mar 13, 2013
    Posts:
    11
    Thank you very much!!! You helped me a lot!!!
     
  24. pavelmo4alov

    pavelmo4alov

    Joined:
    Mar 13, 2013
    Posts:
    11
    How many players are available in current version on NetCode ? I was extend your example with thin clients and fake input. Conducted tests show that more than 64 clients do not work correctly. Entities for new client are created at server and old clients, but not created at new client. Therefor new client don't show players, don't generate fake input - at server and other clients new players are not moving.
     
  25. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    There is no limit by design, but we have not tried to push it yet so there might be bugs preventing it from working.
    The behavior you describe does not sound netcode related since the entities are created on the server and other clients though, sounds more like there is a problem with having that many ecs worlds in the same process.
    What do you mean by entities not being created? The thin clients do not create any entities from ghosts since it skips the deserialization of the snapshots, so which entities are not created? It sounds like something is created since the server picks up the connections right?
     
    bb8_1 likes this.
  26. pavelmo4alov

    pavelmo4alov

    Joined:
    Mar 13, 2013
    Posts:
    11
    I recorded a video for you, please watch.
     
  27. Kelevra

    Kelevra

    Joined:
    Dec 27, 2012
    Posts:
    82
    Hello @timjohansson ! Is there any way to know when Ghost on the client will be despawned? The problem that I want to solve is to clean up references to an entity that will be destroyed.
     
    Last edited: Jul 16, 2020
  28. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    That looks like a bug, can you please file one through the bug reporter in unity? Thanks!
     
    bb8_1 likes this.
  29. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    There is no special netcode way of telling when it will be despawned, you should use the same patterns you would in any other ecs game, add a system state component to the ghost when you start referencing it, then have a system checking for all entities which have you system state component but not whatever regular component you need - like the ghost component - and cleanup references to those.
     
    bb8_1 and Kender like this.
  30. bb8_1

    bb8_1

    Joined:
    Jan 20, 2019
    Posts:
    28
    1. In my game(spaceship flight simulator) I need to implement my own physics so basically to make smoother movements I need for example velocity(but also a direction vector and possibly some other variables for my simulator physics) so i can gradually increase/decrease the value. My question is should velocity be ghost authoring component or should i maintain on server and client along with snapshots velocity values calculated at fixed timestep (in current tick we use value that refer to previous tick/snapshot so newVelocityValue=prevSnapshotVelocityValue+acceleration*fixedTimestep - ofc this is based on user input)? What is the best approach for flight simulator game i want to make? So on server we would have special buffers attached to each player's entity with velocity value and those entities we create when snapshot is created and destroyed when the snapshot they refer to are destroyed. I already implemented velocity as ghost component and it works well although i tested the game only locally(i still use netcode 0.1 in my game).
    2nd approach would probably decrease the size of the snapshot?

    2. In a similar game i believe they used fixed timestep also i think they send 10 snapshots/sec and maintain 4 last snapshots and the game worked very well - is this also possible in the Netcode to change number of snapshots sent by server per sec?

    @timjohansson
     
    Last edited: Jul 23, 2020
  31. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    26
    Is there already a fix for that?

    I'm spawning rockets using predictive spawning which works pretty well.
    Sometimes netcode spawns another rocket when it receives the first snapshot without deleting the old one.
    The old one does get deleted once i spawn another one of the same Archetype.
     
  32. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    26
    I was able to fix my issue by replacing the if statement inside the DefaultyGhostSpawnSystem.cs at line 316 with
    Code (CSharp):
    1.          
    2. if (m_NewGhosts.Length == 0 && m_DelayedSpawnQueue.Count == 0 && m_PredictedSpawnQueue.Count == 0 && m_SpawnRequestGroup.IsEmptyIgnoreFilter && m_PredictSpawnGhosts.Length == 0)
    3.     return inputDeps;
    4.  
    The system was just not updating when it still had predictedSpawnGhosts pending which is why the rockets(predicted entities) did despawn once another one of the same type did get spawned.
     
    bb8_1 likes this.
  33. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    120
    I'm reaching the icomponent data limit, im currently capped of at 10 ghosts. are there any plans to lift this restriction? or is there some way of reusing ghost components (ie. have one projectile ghost and 20 variants of that one ghost for all the projectiles in the game)?


    what should be and should not be a ghost? should a door be a ghost? i currently have 12 different door ghosts, seems like codesmell, but i need the door positions to be synced across all players, but i can't because of the size limit. what about pickups, should each pickup item be a ghost?

    does a door in this case constantly use up bandwidth even though no one's interacting with it?

    Edit: just scrolled up and saw it is getting fixed
     

    Attached Files:

    • gds.png
      gds.png
      File size:
      400.6 KB
      Views:
      1,043
    Last edited: Jul 22, 2020
    bb8_1 and florianhanke like this.
  34. Kelevra

    Kelevra

    Joined:
    Dec 27, 2012
    Posts:
    82
    Hello, @Stroustrup !
    I would recommend you to differ between GhostPrefab as a template and actual visual representation. This will allow you to have an infinite number of door variants with only one DoorGhost. Also, it will save you from modifying all your doors if you decide to add more components later.
    You can go further and move all your data to some kind of database/scriptobject whatever, and configure your ghost with that data after spawn.
    So your workflow will be like:

    Code (CSharp):
    1. struct PickUpItem
    2. {
    3.     [GhostDefaultField]
    4.     public int ItemId;
    5. }
    6.  
    7. // Later in the code
    8. var itemData = db.Get(pickUpItem.ItemId);
    9. LoadVisual(itemData.Visual)
    10. // etc.
    11.  
     
  35. pavelmo4alov

    pavelmo4alov

    Joined:
    Mar 13, 2013
    Posts:
    11
    Ok, i sent bug report. Let's wait the answer
     
  36. Kelevra

    Kelevra

    Joined:
    Dec 27, 2012
    Posts:
    82
    Hello @timjohansson !
    I've encountered an issue (at least from my perspective) and want to clarify if this behavior is intentional or it's a bug.

    On the server I spawn a ghost and set some data:
    var ghostEntity = commandBuffer.Instantiate(ghostPprefab);
    commandBuffer.SetComponent(ghostEntity, new Component { ImportantData = value });

    On the client I making some actions based on that ImportantData. When I run client and server in one process everything works fine and I'm receiving data from the server when the ghost is spawned. But when I run client and server in separate applications it looks like the ghost is spawned on the client without data from the first snapshot and receives it later. I thought that notification about newly spawned ghosts should come alongside with initial snapshot of data. Am I wrong?

    Instatiation type of the ghost is "Interpolated"

    Thank you!
     
  37. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    591
    Hi @timjohansson. Any plan to release new version of DOTS Netcode soon to compatible with latest Entities?
     
    Stroustrup, bb8_1 and GliderGuy like this.
  38. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    120
    currently stuck on 2020.1 beta 14, neither netcode nor uitoolkit works on anything after that. hdrp 9 also broke for me
     
    Last edited: Jul 23, 2020
  39. bb8_1

    bb8_1

    Joined:
    Jan 20, 2019
    Posts:
    28
    I use 2020.1.0f1 and it(netcode) works - though i (still) use netcode 0.1
     
  40. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    120
    but thats only compatible with entities 9 though?
     
  41. bb8_1

    bb8_1

    Joined:
    Jan 20, 2019
    Posts:
    28
    entities 6 i think
     
    Last edited: Jul 25, 2020
  42. Occuros

    Occuros

    Joined:
    Sep 4, 2018
    Posts:
    18
    While experimenting with the netcode, I struggle the most with custom type serialization for the ghost snapshot data.

    For example in the Dots Physics package, there are many types (
    PhysicsConstrainedBodyPair, PhysicsJoint etc.) which get picked up as fields in the ghost editor component, but don't get serialized to the snapshot data (and therefore not synchronized between client and server).

    What would be the best way to add additional serialization for those types, so it won't get overwritten when code generation is triggered?
     

    Attached Files:

  43. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    120
    you need to add a ghost default field attribute to your components, note that very few components get serialized. i use the ascii characters inside of a nativestring 64 to sync player inventory because that's the longest ghost type.
    alternatively to adding a ghost default field, you can manually enter the variable name inside your component by ticking the manual field list and regenerating code. but again, only thing that get's synced by default are byte, int, bool, nativestring64, float, float2, float3, float4 and that's all i think

     

    Attached Files:

  44. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,467
    I see a bunch of different netcode topics here in the DOTS forum. Wouldn't it be helpful to have a NetCode subforum like physics has?
     
    Mikael-H, Jawsarn, Occuros and 4 others like this.
  45. bb8_1

    bb8_1

    Joined:
    Jan 20, 2019
    Posts:
    28
    Yeah many asked for subforum and admins never replied. Or at least someone could create NetCode discord channel and invite us that would be also nice(preferably devs) - solution not that good might be creating page with links to all NetCode threads or when ever someone posts NetCode thread she/he should start title with [NetCode]
     
    Last edited: Aug 1, 2020
    Lukas_Kastern likes this.
  46. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    120
    has anyone got netcode to work with 2020.1?
     
  47. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    321
    bb8_1 likes this.
  48. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    26
    There's code for 2020.1 compatibility, ghost prediction despawning fix, and the Passing an argument of size '10568' laying around in the forum.

    And those are just the posts that i'm aware of.

    Even if you as the Netcode team don't like those changes and plan on doing something fancy in the future there are people who are looking for this stuff right now.

    I think having a place where we could group all this stuff would benefit a lot.
     
    Jawsarn, Enzi, bb8_1 and 2 others like this.
  49. Occuros

    Occuros

    Joined:
    Sep 4, 2018
    Posts:
    18
    +1 for topic specific sub forum for NetCode.

    if components get added (or removed) at runtime to a ghost, how to best sync it between client and server?

    does everything need to be handled with RPC’s or is there a better way?
     
    Mikael-H, BlindSeher and bb8_1 like this.
  50. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    232
    Any value you set like that is applied the first frame the entity exists on the client. It is not applied immediately when the entity is spawned though, the entity is spawned at the beginning of the simulation update, and the values are applied in GhostUpdateSystemGroup inside GhostSimulationSystemGroup. You need to make sure that the system where you read the values updates after GhostUpdateSystemGroup (or after GhostSimulationSystemGroup).
     
    Lukas_Kastern likes this.
unityunity