Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question [NetCode] Passing an argument of size 10136

Discussion in 'NetCode for ECS' started by Stroustrup, Jul 22, 2020.

  1. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    142
    how do i solve this problem?
    the netcode ghost collection produces this message at runtime when i add too many ghosts (11)

     

    Attached Files:

    Last edited: Jul 22, 2020
    florianhanke likes this.
  2. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    How do you know that the issue is adding too many ghosts? I started having this issue recently, but can't say exactly which system the issue originates from.
     
  3. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    142
    disabling ghosts in the ghost collection authoring singleton until i have just 10 and clicking regenerate collection fixes the problem. it doesn't seem to matter which ghosts you disable, just that its only 10 for me..

    how many ghosts do you have?
     
  4. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    Thanks! I have 7, but two of them have quite a few children. I'll try removing ghosts too. Have you tried removing different ones each time to see if the issue stems not from the number of ghosts but from their configuration?
     
  5. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    142
    yes, it doesn't seem to make a difference which ghosts i remove. my ones are all roughly the same size. i encounter this error when i have >10 of any ghosts
     
    florianhanke likes this.
  6. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    Ok, for me it's the same – when I remove one ghost, I probably make it just under a limit (of 10000 what?). If not, I get
    InvalidProgramException: Passing an argument of size '10144'
    .

    I am not yet very well versed in C#, but is it possible that the
    inputJob
    job handle size from in
    public sealed override void Update()
    of
    JobComponentSystem
    and that is passed into
    OnUpdate
    is too large? In any case, I'll have to do some reading…
     
  7. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
  8. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    It's not about the number of the ghosts but about the size of the GhostSerializers.

    Currently code gen generates code like this for serializers:

    Code (CSharp):
    1.     private ArchetypeChunkComponentType<AbilityCollection> ghostAbilityCollectionType;
    2.     private ArchetypeChunkComponentType<PredictingPlayerId> ghostPredictingPlayerIdType;
    3.     private ArchetypeChunkBufferType<LinkedEntityGroup> ghostLinkedEntityGroupType;
    4.     private ComponentDataFromEntity<AbilityControl> ghostChild0AbilityControlType;
    5.     private ComponentDataFromEntity<AbilityControl> ghostChild1AbilityControlType;
    6.     private ComponentDataFromEntity<AbilityControl> ghostChild2AbilityControlType;
    As you can see it creates duplicate ComponentDataFromEntity<T> when a synced component exists on the main entity and children.

    Until the new workflows drop you can just manually remove the duplicates which should free up some space.
     
    Stroustrup and florianhanke like this.
  9. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    I noticed the duplication, but did not make the connection. There should only be one
    ComponentDataFromEntity<T>
    per T, I assume.

    @Lukas_Kastern Do you have any insights when the new workflow drops?
     

    Attached Files:

  10. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    Sadly no, all information i have are from forum threads.

    Do you really need to sync all those translations?
    In case you aren't aware, you can remove them by toggling ManualFieldList on the GhostAuthoringComponent fields.
     
    florianhanke likes this.
  11. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    I've looked at the code gen to make a more automated workaround.

    To implement it replace the GenerateSerializer method inside com.unity.netcode@0.2.0-preview.5\Editor\GhostAuthoringComponentEditor.cs with:

    Code (CSharp):
    1. static void GenerateSerializer(GhostAuthoringComponent ghostInfo, string assetPath, GhostCodeGen.Batch batch)
    2.         {
    3.             var addedTypes = new List<string>( );
    4.          
    5.             var codeGen = new GhostCodeGen("Packages/com.unity.netcode/Editor/CodeGenTemplates/GhostSerializer.cs");
    6.             var replacements = new Dictionary<string, string>();
    7.  
    8.             int serverComponentCount = 0;
    9.             bool needsLinkedEntityGroup = false;
    10.             HashSet<string> imports = new HashSet<string>();
    11.             imports.Add("Unity.Entities");
    12.             imports.Add("Unity.Collections");
    13.             imports.Add("Unity.NetCode");
    14.             for (int comp = 0; comp < ghostInfo.Components.Length; ++comp)
    15.             {
    16.                 var entityIndex = ghostInfo.Components[comp].entityIndex;
    17.                 if (!ghostInfo.Components[comp].server)
    18.                     continue;
    19.                 imports.Add(ghostInfo.Components[comp].NamespaceName);
    20.                 var componentTypeName = GetShortName(ghostInfo.Components[comp]);
    21.                 replacements.Clear();
    22.                 replacements.Add("GHOST_COMPONENT_TYPE_NAME", componentTypeName);
    23.                 replacements.Add("GHOST_COMPONENT_TYPE", ghostInfo.Components[comp].ShortName.Replace("+", "."));
    24.  
    25.                 replacements.Add("GHOST_ENTITY_INDEX", entityIndex.ToString());
    26.                 if (entityIndex == 0)
    27.                 {
    28.                     ++serverComponentCount;
    29.                     //codeGen.GenerateFragment("GHOST_COMPONENT_TYPE", replacements);
    30.                     //codeGen.GenerateFragment("GHOST_ASSIGN_COMPONENT_TYPE", replacements);
    31.                 }
    32.  
    33.                 if (ghostInfo.Components[comp].fields.Length > 0)
    34.                 {
    35.                     var doGenerateComponentData = !addedTypes.Contains( replacements["GHOST_COMPONENT_TYPE"] );
    36.  
    37.  
    38.                     if ( doGenerateComponentData )
    39.                     {
    40.                         addedTypes.Add( replacements["GHOST_COMPONENT_TYPE"] );
    41.                     }
    42.                  
    43.                     if (entityIndex == 0)
    44.                     {
    45.                         codeGen.GenerateFragment("GHOST_COMPONENT_TYPE_DATA", replacements);
    46.                      
    47.                         codeGen.GenerateFragment("GHOST_ASSIGN_COMPONENT_TYPE_DATA", replacements);
    48.                         codeGen.GenerateFragment("GHOST_ASSIGN_CHUNK_ARRAY", replacements);
    49.                     }
    50.                     else
    51.                     {
    52.                         needsLinkedEntityGroup = true;
    53.                         if ( doGenerateComponentData )
    54.                         {
    55.                             codeGen.GenerateFragment( "GHOST_COMPONENT_TYPE_CHILD_DATA", replacements );
    56.                             codeGen.GenerateFragment("GHOST_ASSIGN_COMPONENT_TYPE_CHILD_DATA", replacements);
    57.                         }
    58.                     }
    59.  
    60.                     for (int field = 0; field < ghostInfo.Components[comp].fields.Length; ++field)
    61.                     {
    62.                         replacements["GHOST_FIELD_NAME"] = ghostInfo.Components[comp].fields[field].name;
    63.                         if (entityIndex == 0)
    64.                         {
    65.                             codeGen.GenerateFragment("GHOST_ASSIGN_SNAPSHOT", replacements);
    66.                         }
    67.                         else
    68.                         {
    69.                             codeGen.GenerateFragment("GHOST_ASSIGN_CHILD_SNAPSHOT", replacements);
    70.                         }
    71.                     }
    72.                 }
    73.             }
    74.  
    75.             if (needsLinkedEntityGroup)
    76.             {
    77.                 ++serverComponentCount;
    78.                 replacements.Clear();
    79.                 replacements.Add("GHOST_COMPONENT_TYPE_NAME", "LinkedEntityGroup");
    80.                 replacements.Add("GHOST_COMPONENT_TYPE", "LinkedEntityGroup");
    81.                 //codeGen.GenerateFragment("GHOST_COMPONENT_TYPE", replacements);
    82.                 //codeGen.GenerateFragment("GHOST_ASSIGN_COMPONENT_TYPE", replacements);
    83.  
    84.                 codeGen.GenerateFragment("GHOST_BUFFER_COMPONENT_TYPE_DATA", replacements);
    85.                 codeGen.GenerateFragment("GHOST_ASSIGN_BUFFER_COMPONENT_TYPE_DATA", replacements);
    86.                 codeGen.GenerateFragment("GHOST_ASSIGN_CHUNK_BUFFER_ARRAY", replacements);
    87.             }
    88.  
    89.             replacements.Clear();
    90.             foreach (var ns in imports)
    91.             {
    92.                 if (ns != null && ns != "")
    93.                 {
    94.                     replacements["GHOST_USING"] = ns;
    95.                     codeGen.GenerateFragment("GHOST_USING_STATEMENT", replacements);
    96.                 }
    97.             }
    98.  
    99.             replacements.Clear();
    100.             replacements.Add("GHOST_NAME", ghostInfo.Name);
    101.             replacements.Add("GHOST_IMPORTANCE", ghostInfo.Importance);
    102.             replacements.Add("GHOST_COMPONENT_COUNT", serverComponentCount.ToString());
    103.             codeGen.GenerateFile(assetPath, ghostInfo.RootPath, ghostInfo.SerializerPath, replacements, batch);
    104.         }
    I haven't added anything crazy to that method, it just keeps track of the added child types and only creates one ComponentDataFromEntity fragment.

    Than replace the serializer code gen file which is located at com.unity.netcode@0.2.0-preview.5\Editor\CodeGenTemplates\GhostSerializer.cs with the attached file.
     

    Attached Files:

    florianhanke likes this.
  12. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    Thanks for the reminder – that helps me get under the limit!
    I had resorted to not messing with the child elements as they were/are unhelpfully named in the authoring component (what exactly is "child 7") and one can't set predicted/interpolated per child. Also, I have an automated workflow where I auto-generate the GhostAuthoringComponent, so now I'll update that to override the field list for most children.
     
    Lukas_Kastern likes this.
  13. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    Not syncing Translation/Rotation in all children was quite easy to add to the ghost component authoring generator:
    Code (CSharp):
    1. private static void postProcessGhost(GameObject prefab)
    2. {
    3.     var t     = prefab.transform;
    4.     var ghost = t.GetComponent<GhostAuthoringComponent>();
    5.  
    6.     // Update component list.
    7.     GhostAuthoringComponentEditor.SyncComponentList(ghost);
    8.     // Unset prediction from all components in the list.
    9.     var components = ghost.Components;
    10.     for (var i = 0; i < components.Length; i++)
    11.     {
    12.         components[i].predictedClient = false;
    13.         // Do not sync Translation/Rotation in all children.
    14.         if (components[i].entityIndex != 0) // Child N
    15.         {
    16.             if (components[i].ShortName == "Translation" || components[i].ShortName == "Rotation")
    17.             {
    18.                 components[i].manualFieldList = true;
    19.                 components[i].fields          = new GhostAuthoringComponent.GhostComponentField[] { };
    20.             }
    21.         }
    22.     }
    23.  
    24.     // Generate the ghost code.
    25.     GhostAuthoringComponentEditor.GenerateGhost(ghost);
    26. }
    In case anyone is interested :)
     
    bb8_1 and Lukas_Kastern like this.