Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Modifying the fields of ISystemStateSharedComponentData does not persists changes

Discussion in 'Data Oriented Technology Stack' started by Abbrew, Jan 9, 2019.

  1. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    125
    I have an ISystemStateSharedComponentData component called CalculationIO that contains two structs called RequestsQueue and ResultsCache which act like a request queue and results cache. A system will read from the requests queue, clear it, and write to the results cache, discarding older results if the cache gets too big. Other systems can append requests to the system and read results from the cache. Each system that accesses or owns the component injects the ISystemStateSharedComponentData into itself. My issue is that the changes made by one system to the component is not visible to another system. Is there a way of persisting changes to an ISystemStateSharedComponentData, or is there another way of message passing? Here is the relevant code:

    ResultsCache:
    Code (CSharp):
    1. public struct ResultCache<K,V> : ISystemStateSharedComponentData where K : struct, IEquatable<K> where V : struct
    2. {
    3.  
    4.     public NativeLRUCacheComponent<K,V> cache;
    5.  
    6.     public ResultCache(int cacheSize)
    7.     {
    8.         cache = new NativeLRUCacheComponent<K, V>(cacheSize);
    9.     }
    10. }
    11.  
    CalculationIO:
    Code (CSharp):
    1. public struct CalculationIO<Request,Result>: IDisposable, ISystemStateSharedComponentData where Request : struct, IEquatable<Request> where Result : struct
    2. {
    3.     private Entity reference;
    4.     public RequestQueue<Request> requests;
    5.     public ResultCache<Request, Result> results;
    6.  
    7.     public CalculationIO(Entity reference,int maxRequestSize,int maxResultSize)
    8.     {
    9.         this.reference = reference;
    10.         requests = new RequestQueue<Request>(maxRequestSize);
    11.         results = new ResultCache<Request, Result>(maxResultSize);
    12.     }
    13.  
    14.     public CalculationIO<Request, Result> Acquire()
    15.     {
    16.         EntityManager manager = World.Active.GetOrCreateManager<EntityManager>();
    17.         var requestRef = manager.GetSharedComponentData<CalculationIO<Request, Result>>(reference);
    18.         return requestRef;
    19.     }
    20.  
    21.     public void Save()
    22.     {
    23.         EntityManager manager = World.Active.GetOrCreateManager<EntityManager>();
    24.         manager.GetSharedComponentData<CalculationIO<Request,Result>>(reference);
    25.     }
    26.  
    27.     public void Dispose()
    28.     {
    29.         requests.requests.Dispose();
    30.         results.cache.Dispose();
    31.     }
    32.  
    33.     public void Clean()
    34.     {
    35.         requests.requests.Clean();
    36.         results.cache.Clean();
    37.     }
    38.  
    39. }
    40.  
    Modifying the component through accessing a group:

    Code (CSharp):
    1. var io = ioGroup.io[0].Acquire();
    2.  
    3.         var requestQueue = io.requests;
    4.         requestQueue.requests.Load(req);
    5.         io.Save();
    Reading the component through accessing a group:

    Code (CSharp):
    1. var io = ioGroup.io[0].Acquire();
    2.  
    3.         var cache = io.results;
    4.         var request = io.requests;
    5.  
    6.  
    7.  
    8.  
    9.         int length = request.requests.Count;
    This code was written based off reading @5argon 's explanation of how to modify a SharedComponentData
    from https://forum.unity.com/threads/modifying-a-shared-component-across-many-entities.534196/
     
  2. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    125
    The issue is that I was getting a copy of the ResultCache struct when accessing it. To modify CalculationIO's version, I have to fully access it. I fixed the issue by accessing the fields using its full "qualified" name. Like in
    Code (CSharp):
    1. // persists changes
    2. io.requests.requests.Load(newRequests)
    3. // does not persist changes
    4. var requests = io.requests
    5. requests.Load(newRequests)
    I should probably write some wrapper methods in the CalculationIO struct to make the code cleaner. Friggin structs.
     
  3. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    125
    Sorry for spamming this thread with self-replies. I still can't modify the ISystemStateSharedComponentData. The replies from Unity staff implies that you're supposed to be able to modify ISystemStateSharedComponentData since it's meant to keep track of system-specific data. I can't use ISystemStateComponentData because the system-specific data I want to store is a NativeMultiHashMap, which is not blittable on IComponentData. Any solutions or alternatives? I considered having the NativeMultiHashMap as a field in the system, exposing a getter, and injecting that system into other systems, but this is considered bad practice.
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,571
    This is not supported at the moment. Storing the container on the system itself is a more performant and better approach.
     
    Abbrew likes this.