Search Unity

Bug [1.0.0-pre.44] Ghosts failed to sync across network properly

Discussion in 'NetCode for ECS' started by optimise, Jun 19, 2022.

  1. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    I believe it's the bug that exists since dots 0.17 release up until current latest dots 0.51 release. Let say when u have ghost 1 that has child ghost A, B, C and then ghost 2 that has child ghost A, B, D. If you dun put
    SharedComponentData at each parent ghost to force them split as different chunk i.e. ghost A at chunk A and ghost B at chunk B instead of both ghosts at chunk A only, you will hit the following error that they will fail to sync the ghosts properly across network. I believe it's like dots netocode sync snapshot to wrong ghost that it syncs ghost snapshot A to ghost B and ghost snapshot B to ghost A.

    IndexOutOfRangeException: Index 50 is out of range in DynamicBuffer of '50' Length.
    Unity.Entities.DynamicBuffer`1[T].CheckBounds (System.Int32 index) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/Iterators/DynamicBuffer.cs:145)
    Unity.Entities.DynamicBuffer`1[T].get_Item (System.Int32 index) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/Iterators/DynamicBuffer.cs:186)
    Unity.NetCode.GhostUpdateSystem+UpdateJob.Execute (Unity.Entities.ArchetypeChunk chunk, System.Int32 chunkIndex, System.Int32 firstEntityIndex) (at Library/PackageCache/com.unity.netcode@6ce8343d06/Runtime/Snapshot/GhostUpdateSystem.cs:342)
    Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].ExecuteInternal (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/IJobChunk.cs:401)
    Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].Execute (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/IJobChunk.cs:368)
    Unity.Jobs.JobHandle:ScheduleBatchedJobsAndComplete(JobHandle&)
    Unity.Jobs.JobHandle:Complete()
    Unity.NetCode.GhostPredictionSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.netcode@6ce8343d06/Runtime/Snapshot/GhostPredictionSystemGroup.cs:77)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystem.cs:114)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystemGroup.cs:583)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystemGroup.cs:523)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystem.cs:114)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystemGroup.cs:583)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystemGroup.cs:523)
    Unity.NetCode.ClientSimulationSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.netcode@6ce8343d06/Runtime/ClientServerWorld/ClientSimulationSystemGroup.cs:91)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystem.cs:114)
    Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ScriptBehaviourUpdateOrder.cs:426)
     
  2. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    900
    Ghost A,B,C and ghost A,B,D should be different if they have different prefab.
    If they don't, then this is the problem.
    If they are the same prefab but you remove a child that will break everything and it is expected.
    You are not supposed to do that.
    You can remove components from child entities and that still works, but removing or switching, or changing the ones in the linked entity group you will incurs in these problem.
     
  3. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Oh maybe u misunderstand wat I mean. Both ghost 1 and 2 are baked at authoring. I dun do any changes at runtime. Basically wat I want to say is at runtime when parent entity of ghost 1 and 2 is at same chunk but their child entities has a little bit different then it will cause this bug.
     
  4. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    900
    Oh yeah, I confused thing, my fault.
    I confirm that, yes, it is a issue. It is only for for the client, since on the client we remote the SharedGhostTypeComponent (that is already present on the server) that differentiate and split the entities in different chunks.
    There are other systems affected by that too (not only for the GhostUpdateSystem).

    We will provide a fix for that, but if you like to do fix by yourself, without the need to add another shared component, please remove or comment the following lines from the GhostConversion.cs:

    line 94 - 100
    Code (csharp):
    1.  
    2. if (target != NetcodeConversionTarget.Client)
    3. {
    4.     // If this ghost should be usable on a server we must add a shared ghost type to make sure different ghost types
    5.     // with the same archetype end up in different chunks. If conversion is client and server the client needs to remove
    6.     // this at runtime
    7.     DstEntityManager.AddSharedComponentData(rootEntity, new SharedGhostTypeComponent {SharedValue = ghostType});
    8. }
    9.  
    and line 406
    Code (csharp):
    1.  
    2. removeOnClient.Add(new GhostPrefabMetaData.ComponentReference(0,TypeManager.GetTypeInfo(ComponentType.ReadWrite<SharedGhostTypeComponent>().TypeIndex).StableTypeHash));
    3.  
    This would not remove the shared component on the client and split them in different chunks based on the ghost prefab.
    I didn't test it yet but should work as expected.
     
  5. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Tested with your changes but still doesn't work properly. I guess the proper fix is line 94-100 just only need to comment out if (target != NetcodeConversionTarget.Client).

    If I understand correctly it means that client also needs to split them in different chunks. Is that any plan to make it in same chunk to improve performance? Or actually it's not really possible to achieve?
     
    Last edited: Jun 21, 2022
  6. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    900
    Yes, sorry, only line 94. My bad I didn't explain it.

    [/quote]
    We are planning to properly fix that later on so that we can exploit some chunk coherence. However,
    I don't think we are going to have much of improvement in performance here. That because you are dealing with child entities, that lives potentially in other chunks. So accessing the children cause a lot of cache misses and poor memory access (in the end we are jumping from one entity in one chunk to another entity in another chunk.
     
  7. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    • SharedGhostTypeComponent is also added to the client ghost prefab to split ghosts in different chunks.
    Will chunk coherence improvement coming soon since currently at 1.0.0-pre.44 every ghost entity is still split into different chunk per entity by default at client and server ?
     
  8. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    900
    The plan was to try to put some improvement for 1.0. But we are very close. No promise, but if we can we will definitively do. Server though has the same exact logic. And on the server it is quite trickier, since there are very strong assumption about the fact the ghost chunks are split per ghost type.

    To better clarify the current state (before it is mistaken): entities are not split like one entity per chunk. They are just split in chunk based on the prefab-type.
    (There is a problem in general with entities and shared component that ends splitting the entities all in different chunks but that is another thing).
     
    optimise likes this.