Search Unity

SharedComponentData SharedComponentDataArray<> must always be injected as [ReadOnly]

Discussion in 'Entity Component System' started by any_user, Mar 29, 2018.

  1. any_user

    any_user

    Joined:
    Oct 19, 2008
    Posts:
    374
    I'm trying to get my head around the basics of the ECS. While trying to understand how ISharedComponentData works I ran into some issues. I get this error message after starting play mode:

    Code (CSharp):
    1. ArgumentException: SomeSystem:data SharedComponentDataArray<> must always be injected as [ReadOnly]
    That's the code:

    Code (CSharp):
    1. using System;
    2. using Unity.Entities;
    3.  
    4. public class SomeSystem : ComponentSystem
    5. {
    6.     struct Data
    7.     {
    8.         [ReadOnly]
    9.         public SharedComponentDataArray<SomeSharedComponent> someSharedData;
    10.     }
    11.  
    12.     [Inject] Data data;
    13.    
    14.     protected override void OnUpdate()
    15.     {
    16.         // do something
    17.     }
    18. }
    19.  
    20. [Serializable]
    21. public struct SomeSharedComponent : ISharedComponentData
    22. {
    23.     public float someValue;
    24. }
    Am I doing something wrong or is it a bug? With non-shared data (ComponentData and ComponentDataArray) it works.
     
  2. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    I have the same problem.

    Code (CSharp):
    1. AddCellLinkSystem:_data SharedComponentDataArray<> must always be injected as [ReadOnly]
    Code (CSharp):
    1.  
    2.             internal struct Data
    3.             {
    4.                 public EntityArray NewEntities;
    5.                 [ReadOnly]
    6.                 public ComponentDataArray<AddCellFlag> DatasForAdd;
    7.                 [ReadOnly]
    8.                 public ComponentDataArray<CellValue> CellValues;
    9.                 [ReadOnly]
    10.                 public SharedComponentDataArray<MapIVData> MapIVDatas;
    11.                 public int Length;
    12.             }
    13.  
    14.             [Inject]
    15.             private Data _data;
    Any clues for this problem ?
     
  3. mike_acton

    mike_acton

    Unity Technologies

    Joined:
    Nov 21, 2017
    Posts:
    110
    The [ReadOnly] attribute should be coming from using Unity.Collections.
     
    starikcetin likes this.
  4. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    It's indeed that, I had an another readonly attribut in my project.
    Thanks
     
    starikcetin likes this.
  5. avvie

    avvie

    Joined:
    Jan 26, 2014
    Posts:
    74
    is it impossible to change the meshInstanceRenderer from a job then ? or the color or anything?
    Screenshot_1.png
    I am trying to turn something from black to white by changing the material
     
  6. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    The MeshInstanceRenderer is an ISharedComponentData component, and thus can have reference data (this restricts or eliminates it's ability to be modified on a job). This restriction means that the SharedComponentDataArray<T> is effectively read-only by default.

    Your main option is to track the changes some other way (via a different component that maps to the various MeshInstanceRenderes) and update the MIR state in a ComponentSystem (use the PostUpdateCommands to reassign the data).

    Another option, you can try to use EntityCommandBuffer or EntityCommandBuffer.Concurrent to buffer the changes to a barrier system (EndFrameBarrier is a good choice) so that the changes will happen on the main thread, but can be buffered on your job thread.
     
    avvie and zulfajuniadi like this.
  7. jj_unity328

    jj_unity328

    Joined:
    Jun 7, 2018
    Posts:
    22
    What are your options here?

    If I'm to understand, there is no way to modify it in place and you'd have to use something like `CommandBuffer.SetSharedComponent` and erasing the previous one with an updated one?
     
  8. jj_unity328

    jj_unity328

    Joined:
    Jun 7, 2018
    Posts:
    22
    I'm also not succeeding at changing/updating a material. Can't create or modify a material even in a local variable while in a job. I'm a lill puzzled as how to proceed now.

    In my job:
    Code (CSharp):
    1. Material updatedMat = new Material(meshInstanceRenderer.material); // Copy the previous material
    2. updatedMat.mainTexture = setDynamicTexture.Texture; // Change its texture to a new one
    3.  
    4. CommandBuffer.SetSharedComponent(entity, new MeshInstanceRenderer { mesh = meshInstanceRenderer.mesh, material = updatedMat });
     
  9. avvie

    avvie

    Joined:
    Jan 26, 2014
    Posts:
    74
    Is EntityCommandBuffer.Concurrent buffer you can write in parallel? :S
     
    recursive likes this.
  10. zulfajuniadi

    zulfajuniadi

    Joined:
    Nov 18, 2017
    Posts:
    117
    Yes you can use this in IJobParallelFor. I'm not sure IJobProcessComponentData though.
     
    avvie likes this.
  11. avvie

    avvie

    Joined:
    Jan 26, 2014
    Posts:
    74
    Holy crap and it was bugging me that i cant seem to spawn stuff in parallel and although i was sure i was missing something, made no sense to me.
    Thanks people
     
  12. zulfajuniadi

    zulfajuniadi

    Joined:
    Nov 18, 2017
    Posts:
    117
    Yeah it was released like a couple of days ago
     
    avvie likes this.