Search Unity

Question Unity Netcode throws error.

Discussion in 'NetCode for ECS' started by harryblack, Feb 14, 2021.

  1. harryblack

    harryblack

    Joined:
    Dec 26, 2016
    Posts:
    19
    Hi,
    I was following Unity Netcode getting started tutorial "https://docs.unity3d.com/Packages/com.unity.netcode@0.6/manual/getting-started.html"

    Instead of using "Convert to Client Server Entity" I used subscene workflow.
    Then all the other scripts for system were using ComponentSystem which I replaced with the SystemBase class and this required me to replace all the PostUpdateCommands with the EntityCommandBuffer.

    Now when I run the code everything looks fine but I get the runtime exceptions in the console as can be seen in the screenshot.


    upload_2021-2-14_16-26-5.png

    One of the Systems was GoInGameServerSystem. I am pasting its code here (I made similar changes to other systems as well):

    using System;
    using Unity.NetCode;
    using Unity.Entities;
    // When server receives go in game request, go in game and delete request
    [UpdateInGroup(typeof(ServerSimulationSystemGroup))]
    public class GoInGameServerSystem : SystemBase
    {
    EndSimulationEntityCommandBufferSystem _mECB;
    protected override void OnCreate()
    {
    _mECB = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    }
    protected override void OnUpdate()
    {
    var ecb = _mECB.CreateCommandBuffer();//.AsParallelWriter();
    Entities.WithNone<SendRpcCommandRequestComponent>().ForEach((Entity reqEnt, ref GoInGameRequest req, ref ReceiveRpcCommandRequestComponent reqSrc) =>
    {
    //PostUpdateCommands.AddComponent<NetworkStreamInGame>(reqSrc.SourceConnection);
    //UnityEngine.Debug.Log(String.Format("Server setting connection {0} to in game", EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value));
    //var ghostCollection = GetSingletonEntity<GhostPrefabCollectionComponent>();
    //var prefab = Entity.Null;
    //var prefabs = EntityManager.GetBuffer<GhostPrefabBuffer>(ghostCollection);
    //for (int ghostId = 0; ghostId < prefabs.Length; ++ghostId)
    //{
    // if (EntityManager.HasComponent<MovableCubeData>(prefabs[ghostId].Value))
    // prefab = prefabs[ghostId].Value;
    //}
    //var player = EntityManager.Instantiate(prefab);
    //EntityManager.SetComponentData(player, new GhostOwnerComponent { NetworkId = EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value });
    //PostUpdateCommands.AddBuffer<CubeInput>(player);
    //PostUpdateCommands.SetComponent(reqSrc.SourceConnection, new CommandTargetComponent { targetEntity = player });
    //PostUpdateCommands.DestroyEntity(reqEnt);
    ecb.AddComponent<NetworkStreamInGame>(reqSrc.SourceConnection);
    UnityEngine.Debug.Log(String.Format("Server setting connection {0} to in game", EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value));
    var ghostCollection = GetSingletonEntity<GhostPrefabCollectionComponent>();
    var prefab = Entity.Null;
    var prefabs = EntityManager.GetBuffer<GhostPrefabBuffer>(ghostCollection);
    for (int ghostId = 0; ghostId < prefabs.Length; ++ghostId)
    {
    if (EntityManager.HasComponent<MovableCubeData>(prefabs[ghostId].Value))
    prefab = prefabs[ghostId].Value;
    }
    //var player = EntityManager.Instantiate(prefab);
    var player = ecb.Instantiate(prefab);
    EntityManager.SetComponentData(player, new GhostOwnerComponent { NetworkId = EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value });
    ecb.AddBuffer<CubeInput>(player);
    ecb.SetComponent(reqSrc.SourceConnection, new CommandTargetComponent { targetEntity = player });
    ecb.DestroyEntity(reqEnt);
    }).WithoutBurst().Run();
    _mECB.AddJobHandleForProducer(this.Dependency);
    }
    }


    Can someone look into this and provide some guidance.

    Regards
     

    Attached Files:

  2. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Code (CSharp):
    1. var player = ecb.Instantiate(prefab);
    2. EntityManager.SetComponentData(player,
    Not sure if this is the error you are getting, but this is not correct. You cannot create an entity with an ecb and use it with EntityManager since the entity does not really exist until it has been played back.
     
    harryblack likes this.
  3. harryblack

    harryblack

    Joined:
    Dec 26, 2016
    Posts:
    19
    Thanks for the response.
    Now when I think about it that is actually right.

    But the problem that I am facing is that the Netcode example uses following for the same
    //var player = EntityManager.Instantiate(prefab);
    //EntityManager.SetComponentData(player, new GhostOwnerComponent { NetworkId = EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value });
    //PostUpdateCommands.AddBuffer<CubeInput>(player);

    but if I put this inside the foreach loop (i.e., var player = EntityManager.Instantiate(prefab)) then it gives me error for structural changes inside the forEach.. I used ecb and that removed the error but now I realize it was completely wrong as you have already mentioned.
    Is there any other way? or I will have to go with WithStructuralChanges?
    (that would mean I will need to understand how that will impact the whole example as I have just started to try DOTS)
     
  4. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    harryblack likes this.
  5. harryblack

    harryblack

    Joined:
    Dec 26, 2016
    Posts:
    19