Search Unity

Unity DOTS NetCode getting started issues

Discussion in 'NetCode for ECS' started by mikaelK, Nov 18, 2020.

  1. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    Edit: Found out the reason was old openvr version, if somebody has issue download latest steamvr from their github. https://github.com/ValveSoftware/steamvr_unity_plugin/releases
    -------------------------------------------------------------------------
    Hi, I started a NetCode project and run into some issues.

    So I did this tutorial and started receiving errors.

    upload_2020-11-18_15-12-30.png

    Also, if I do a build and try to start it when a client server setup is running in editor, then the just opened build crashes the editor.

    How can I get rid of these errors and how can I test that the netcode works by making a build and connecting it to a server?
    I'm on NetCode version 0.5 and latest Unity.

    Clearly the Getting started has been working at some point as seen in this video.

    Would be nice to know, if someone can confirm.
     
    Last edited: Jan 28, 2021
    adammpolak likes this.
  2. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    @mikaelK the "Getting started" in the documentation has been out of date since 0.3.

    I posted the same question to @timjohansson here

    When did the error start occurring, when you added the cube? Try following the "get started" and hitting "play" after you make the client/server connection and see if the error still appears.

    This might have something to do with it: https://forum.unity.com/threads/netcode-prediction-jitter.985701/#post-6531164

    also reported here: https://forum.unity.com/threads/issues-with-netcode-0-5.1001329/#post-6498694
     
    Last edited: Nov 23, 2020
  3. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
  4. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    @mikaelK

    For this part of the tutorial:
    upload_2020-11-29_18-48-12.png

    The new NetCode 0.5 has this in the change log:
    upload_2020-11-29_18-49-0.png

    So change
    [UpdateInGroup(typeof(ClientSimulationSystemGroup))]
    to
    [UpdateInGroup(typeof(GhostInputSystemGroup))]
    in SampleCubeInput and I think it might fix it.
     
  5. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    @adammpolak Thanks for the good help.I don't know why it still doesn't work. Here is the code, but hard to say what is the issue since I tried removing code from both of the classes and the issues still persists

    Code (CSharp):
    1. namespace Game.Netcode
    2. {
    3.     [UpdateInGroup(typeof(GhostInputSystemGroup))]
    4.     public class SamplePlayerInput : ComponentSystem
    5.     {
    6.         protected override void OnCreate()
    7.         {
    8.             RequireSingletonForUpdate<NetworkIdComponent>();
    9.         }
    10.  
    11.         protected override void OnUpdate()
    12.         {
    13.             var localInput = GetSingleton<CommandTargetComponent>().targetEntity;
    14.             if (localInput == Entity.Null)
    15.             {
    16.                 var localPlayerId = GetSingleton<NetworkIdComponent>().Value;
    17.                 Entities.WithAll<MovePlayerComponent>().WithNone<PlayerInput>().ForEach((Entity ent, ref GhostOwnerComponent ghostOwner) =>
    18.                 {
    19.                     if (ghostOwner.NetworkId == localPlayerId)
    20.                     {
    21.                         PostUpdateCommands.AddBuffer<PlayerInput>(ent);
    22.                         PostUpdateCommands.SetComponent(GetSingletonEntity<CommandTargetComponent>(), new CommandTargetComponent {targetEntity = ent});
    23.                     }
    24.                 });
    25.                 return;
    26.             }
    27.             var input = default(PlayerInput);
    28.             input.Tick = World.GetExistingSystem<ClientSimulationSystemGroup>().ServerTick;
    29.             if (Input.GetKey("a"))
    30.                 input.horizontal -= 1;
    31.             if (Input.GetKey("d"))
    32.                 input.horizontal += 1;
    33.             if (Input.GetKey("s"))
    34.                 input.vertical -= 1;
    35.             if (Input.GetKey("w"))
    36.                 input.vertical += 1;
    37.             var inputBuffer = EntityManager.GetBuffer<PlayerInput>(localInput);
    38.             inputBuffer.AddCommandData(input);
    39.         }
    40.     }
    41. }

    Code (CSharp):
    1. namespace Game.NetCode
    2. {
    3.     [UpdateInGroup(typeof(GhostPredictionSystemGroup))]
    4.     public class MoveCubeSystem : ComponentSystem
    5.     {
    6.         protected override void OnCreate()
    7.         {
    8.             RequireSingletonForUpdate<NetworkIdComponent>();
    9.         }
    10.  
    11.         protected override void OnUpdate()
    12.         {
    13.          
    14.             var group = World.GetExistingSystem<GhostPredictionSystemGroup>();
    15.             var tick = group.PredictingTick;
    16.             var deltaTime = Time.DeltaTime;
    17.             Entities.ForEach((DynamicBuffer<PlayerInput> inputBuffer, ref Translation trans, ref MovePlayerComponent mp, ref PredictedGhostComponent prediction) =>
    18.             {
    19.                 if (!GhostPredictionSystemGroup.ShouldPredict(tick, prediction))
    20.                 {
    21.                     return;
    22.                 }
    23.  
    24.                 PlayerInput input;
    25.                 inputBuffer.GetDataAtTick(tick, out input);
    26.                 if (input.horizontal > 0)
    27.                 {
    28.                     trans.Value.x += deltaTime;
    29.                 }
    30.                 if (input.horizontal < 0)
    31.                 {
    32.                     trans.Value.x -= deltaTime;
    33.                 }
    34.                 if (input.vertical > 0)
    35.                 {
    36.                     trans.Value.z += deltaTime;
    37.                 }
    38.                 if (input.vertical < 0)
    39.                 {
    40.                     trans.Value.z -= deltaTime;
    41.                 }
    42.             });
    43.          
    44.         }
    45.     }
    46. }
     
  6. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    @adammpolak On the client world the tick and prediction tick gets updated all the time, but not in the server world.
    upload_2020-11-30_3-47-22.png
    Image of the server world.
    upload_2020-11-30_3-47-57.png
    Image of clöient world showing that tick values have changed.
     
  7. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    ok there is something weird. There is 2 entities with player component. On client side 1 entity is updating and on server side both entities that has that component are not updating. I don't think this should be happening
    upload_2020-11-30_3-49-29.png
     
  8. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    @mikaelK

    What are your settings on the multiplayer mode tools (just in case)?

    It looks like the client and the server and not sending data back and forth.

    Can you send screenshots of your entity debugger and what systems are running on the client/server? (include inactive systems)

    Both the client and the server need to have "NetworkStreamInGame" on the Network Connection to send snapshot data:
    upload_2020-11-30_13-34-23.png

    This occurs in this section of the Getting Started Page:
    upload_2020-11-30_13-33-28.png

    Can you check the Network Connection Entity on the client and server and see if these components are on it?

    EDIT: From this post: https://forum.unity.com/threads/bug...r-tick-rollback-to-delta.997526/#post-6571975 it seems like you have not sent back the "go in game" from the client to the server. This means the server isn't going through the motions it needs to.
     
  9. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    @adammpolak Here, it looks like they are present.
    upload_2020-11-30_23-24-42.png
    Server
    upload_2020-11-30_23-25-0.png
    mp tools window
    upload_2020-11-30_23-25-48.png
     

    Attached Files:

  10. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    @adammpolak I also add the code for adding these comonents.
    GoInGameClientSystem

    Code (CSharp):
    1. // When client has a connection with network id, go in game and tell server to also go in game
    2.  
    3. using Unity.Entities;
    4. using Unity.NetCode;
    5. using UnityEngine;
    6.  
    7. namespace Game.NetCode.Client
    8. {
    9.     [UpdateInGroup(typeof(ClientSimulationSystemGroup))]
    10.     [DisableAutoCreation]
    11.     [AlwaysUpdateSystem]
    12.     public class GoInGameClientSystem : ComponentSystem
    13.     {
    14.         private bool multiPlayerGameStarted = false;
    15.  
    16.         public bool MultiPlayerGameStarted
    17.         {
    18.             get { return multiPlayerGameStarted; }
    19.             set { multiPlayerGameStarted = value; }
    20.         }
    21.  
    22.         protected override void OnCreate()
    23.         {
    24.          
    25.         }
    26.  
    27.         protected override void OnUpdate()
    28.         {
    29.             Entities.WithNone<NetworkStreamInGame>().ForEach((Entity ent, ref NetworkIdComponent id) =>
    30.             {
    31.                 PostUpdateCommands.AddComponent<NetworkStreamInGame>(ent);
    32.                 var req = PostUpdateCommands.CreateEntity();
    33.  
    34.                 PostUpdateCommands.AddComponent<GoInGameCommandRequest>(req);
    35.  
    36.                 PostUpdateCommands.AddComponent(req, new SendRpcCommandRequestComponent {TargetConnection = ent});
    37.             });
    38.         }
    39.     }
    40. }
    Go in game server system.
    Code (CSharp):
    1. // When server receives go in game request, go in game and delete request
    2.  
    3. using System;
    4. using Unity.Entities;
    5. using Unity.NetCode;
    6. using UnityEngine;
    7.  
    8. namespace Game.NetCode.Server
    9. {
    10.     [UpdateInGroup(typeof(ServerSimulationSystemGroup))]
    11.  
    12.     public class GoInGameServerSystem : ComponentSystem
    13.     {
    14.         private bool multiPlayerGameStarted = false;
    15.  
    16.         public bool MultiPlayerGameStarted
    17.         {
    18.             get { return multiPlayerGameStarted; }
    19.             set { multiPlayerGameStarted = value; }
    20.         }
    21.  
    22.         protected override void OnUpdate()
    23.         {
    24.             HandleIncomingGoInGameRequests();
    25.         }
    26.  
    27.         private void HandleIncomingGoInGameRequests()
    28.         {
    29.             Entities.WithNone<SendRpcCommandRequestComponent>().ForEach(
    30.                 (Entity reqEnt, ref GoInGameCommandRequest req, ref ReceiveRpcCommandRequestComponent reqSrc) =>
    31.                 {
    32.                     PostUpdateCommands.AddComponent<NetworkStreamInGame>(reqSrc.SourceConnection);
    33.                     UnityEngine.Debug.Log(String.Format("Server setting connection {0} to in game",
    34.                         EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value));
    35.                     var ghostCollection = Entity.Null;
    36.                     ghostCollection = GetSingletonEntity<GhostPrefabCollectionComponent>();
    37.                     var prefab = Entity.Null;
    38.                     var prefabs = EntityManager.GetBuffer<GhostPrefabBuffer>(ghostCollection);
    39.                     for (int ghostId = 0; ghostId < prefabs.Length; ++ghostId)
    40.                     {
    41.                         if (EntityManager.HasComponent<MovePlayerComponent>(prefabs[ghostId].Value))
    42.                         {
    43.                             prefab = prefabs[ghostId].Value;
    44.                         }
    45.                     }
    46.  
    47.                     var player = EntityManager.Instantiate(prefab);
    48.                     EntityManager.SetComponentData(player,
    49.                         new GhostOwnerComponent
    50.                         {
    51.                             NetworkId = EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection)
    52.                                 .Value
    53.                         });
    54.                     PostUpdateCommands.AddBuffer<PlayerInput>(player);
    55.  
    56.                     PostUpdateCommands.SetComponent(reqSrc.SourceConnection,
    57.                         new CommandTargetComponent {targetEntity = player});
    58.  
    59.                     PostUpdateCommands.DestroyEntity(reqEnt);
    60.                 });
    61.         }
    62.     }
    63. }
    I have added this to a button so the mp game can be started on request. Here is code for it from game manager class.


    Code (CSharp):
    1.         public void StartMultiPlayer()
    2.         {
    3.  
    4.             foreach (var world in World.All)
    5.             {
    6.                 if (world.Name== "ServerWorld")
    7.                 {
    8.                     App.View.ViewElements.StatsWindowText.text += "found server world" + "\n";
    9.                     ServerWorld = world;
    10.                 }
    11.                 if (world.Name== "ClientWorld0")
    12.                 {
    13.                     App.View.ViewElements.StatsWindowText.text += "found client world" + "\n";
    14.                     ClientWorld = world;
    15.                 }
    16.             }
    17.             serverStart = World.DefaultGameObjectInjectionWorld.GetExistingSystem<GameInitConnection>();
    18.             serverStart.MultiPlayerGameStarted = true;
    19.             serverStart.Update();
    20.             server = ServerWorld.GetExistingSystem<GoInGameServerSystem>();
    21.             server.MultiPlayerGameStarted = true;
    22.             server.Update();
    23.             client = ClientWorld.GetOrCreateSystem<GoInGameClientSystem>();
    24.             client.MultiPlayerGameStarted = true;
    25.             client.Update();
    26.  
    27.             GetComponent<LoadNetCodeSystemAndSubScene>().NetWorkScene.gameObject.GetComponent<SubScene>().enabled = true;
    28.             var playerCount = ServerWorld.GetOrCreateSystem<NetworkGameInformationRelay>().GetPlayerCount();
    29.             App.View.ViewElements.StatsWindowText.text += "Player count: " + playerCount + "\n";
    30.         }
    Also I tried using it like in the getting started manual. Without button and the same issue still persists.
     
  11. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    @adammpolak Maybe this is related to the subscene based loading. That is required. Its not documented, but when I did the getting started I got message to put the ghost collection inside subscene.
    edit. I mean maybe separating the ghost collection group in to a subscene somehow breaks the connection between client and server system stream components(send and receive).
     
    Last edited: Nov 30, 2020
  12. darioreal

    darioreal

    Joined:
    Sep 24, 2020
    Posts:
    5
    Does you game.cs file have a IRpcCommand in bottom?, the [Bust...] is missing on example
    5.0 example works for me

    [BurstCompiler]
    public struct GoInGameRequest : IRpcCommand
    {
    }
     
    mikaelK likes this.
  13. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    Hi and thanks for reply. I do have that on a separate file. Good to know you got it working. On what Unity version are you working on?
     
  14. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    I made empty project and redid the getting started and its now working. Thanks for all the help.
    I'll try to move the other project content to the new. Weird there is no real difference other than the other has vr device added to the project.
     
    darioreal and adammpolak like this.
  15. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    @mikaelK nice! Let me know if you need any pointers on Subscenes.

    It is not much more than create a Subscene in the Scene Hierarchy. Put all the gameobjects in the Subscene.

    Anything in the Subscene gets automatically converted to entities.
     
    mikaelK likes this.
  16. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
  17. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
  18. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
  19. mikaelK

    mikaelK

    Joined:
    Oct 2, 2013
    Posts:
    284
    @adammpolak Thanks a lot!
    I answered and made a video to prove I'm not making things up.
    I'll post it here too.