Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

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:
    365
    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:
    365
    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.