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

Is there a way to schedule a CopyFromComponentDataArray

Discussion in 'Entity Component System' started by 8bitgoose, Sep 7, 2019.

  1. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    I am pulling the data out via a job and I want to put it back in as soon as the data is modified.

    Code (CSharp):
    1.  
    2. grabberQuery.CopyFromComponentDataArray(resultHovers, out JobHandle handler);
    This method has to have the job complete before using or it will throw and error.

    The only other way to get around this that I've thought of is to make a hashmap and read from it in another job.

    CopyFromComponentDataArray spits out a handler, is there any way to schedule it?
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    Right now such an API is missing. Best alternative is to use IJobForEachWithEntity or IJobChunk to copy back. Don't use hashmap for this.
     
  3. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    @DreamingImLatios why no hashmap? They only suck for clearing large amount of info. I am not sure how to align the query I've got in an IJobForEachWithEntity with the proper info in the NativeArray.
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    You just use the index parameter of the IJobForEachWithEntity to index the NativeArray. Hashmaps are random access which makes them considerably slower.
     
  5. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    @DreamingImLatios except I am pulling that information via a ToComponentDataArray as opposed to writing my own job. Do you know if that has a consistent order that you can use??
     
  6. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    You can combine that dependecy with your system dependency so it wont complete right away.
    Code (CSharp):
    1. JobHandle.CombineDependencies(handler, systemHandler)
     
  7. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    @GilCat Yup I know that! But the CopyFromComponentDataArray fires on the main thread right away and only returns you a handler, you can't schedule it to fire after some job had been completed before. Idealy, I would love to be able to schedule this so I could do ToCompDataArray, do a job, CopyFrom all in the same scheduled system.

    Unless I am missing something...
     
  8. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    I would consider that a bug if it wasn't. My understanding is that all the APIs that provide indexing or work with NativeArrays and EntityQueries use a consistent deterministic indexing convention. However, I can't say with absolute certainty yet because I don't personally use To/CopyFrom. I usually end up reorganizing my data into an SOAOS of several hot streams and one cold stream when doing these copies. That's because when I extract to NativeArrays, that operation is usually minimal compared to the job that does all of its work using NativeArrays.
     
  9. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Yeah you are right. I never had to use this. Unfortunately like @DreamingImLatios said the API lack the ability to receive a dependency that would make it work.
    You can easy create a job just to copy that data back or create and extension that does just that:
    Code (CSharp):
    1. public static class Extension {
    2.   [BurstCompile]
    3.   struct CopyFromComponentJob<T> : IJobForEachWithEntity<T>
    4.     where T : struct, IComponentData {
    5.  
    6.     [ReadOnly]
    7.     [DeallocateOnJobCompletion]
    8.     public NativeArray<T> Source;
    9.  
    10.     public void Execute(Entity entity, int index, [WriteOnly]ref T hover) {
    11.       hover = Source[index];
    12.     }
    13.   }
    14.  
    15.   public static void CopyFromComponentDataArray<T>(this EntityQuery query, NativeArray<T> componentDataArray, JobHandle inputDeps, out JobHandle jobHandle)
    16.     where T : struct, IComponentData {
    17.     jobHandle = new CopyFromComponentJob<T> {
    18.       Source = componentDataArray
    19.     }.Schedule(query, inputDeps);
    20.   }
    21. }
    Then in your system you can do:
    Code (CSharp):
    1.     m_query.CopyFromComponentDataArray(resultHovers, inputDeps, out var copyJobHandle);
    2.     inputDeps = JobHandle.CombineDependencies(inputDeps, copyJobHandle);
     
  10. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    @GilCat Yeah I realize I can easily make a job to do it. Just wish there was a native job to do that instead of writing it! Hopefully they implement what you made above.