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

[0.0.12-preview.21] GetBufferFromEntity and GetComponentDataFromEntity no longer public?

Discussion in 'Entity Component System' started by Xerioz, Nov 23, 2018.

  1. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    Seems like it was changed to `internal`, I don't understand the reason behind this change.
    All it does is remove features I found to be extremely useful.

    Could we please have it back?
     
    Sylmerria and Mr-Mechanical like this.
  2. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    I think only the one from EntityManager was changed? Probably because you should use the one from ComponentSystemBase as dependencies are otherwise not tracked correctly.
     
    Mr-Mechanical likes this.
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    As julian-moschuering said, it's because you're not meant to use it from EntityManager.
    You're meant to use the [Job]ComponentSystem version.
    By setting it internal, they're getting rid of a common error.
     
    Mr-Mechanical likes this.
  4. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    --- edit ---

    Guess I had a brainfart where I couldn't see how to fix my issue.
    Passing CompontSystem along with EntityManager was actually enough to re-adapt my code.
     
    Last edited: Nov 24, 2018
  5. Calebsem

    Calebsem

    Joined:
    Mar 17, 2015
    Posts:
    4
    I'm sorry, I think I'm missing something, but I just can't get the compiler to find
    GetBufferFromEntity
    on ComponentSystemBase inside the project context. What's weird is that I can see its public declaration in the entities package, but my editor doesn't seem to want to use it, even after deleting all the editor temp folders and getting the package again. Am I missing something? Running beta11 btw
     
  6. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    GetBufferFromEntity still happens through EntityManager
     
  7. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    GetComponentDataFromEntity exists both in CS and JCS, but GetBufferFromEntity exists only in JCS, of course we can use reflection for AddReaderWriter(isReadOnly ? ComponentType.ReadOnly<T>() : ComponentType.Create<T>()); in CS and then use EntityManager.GetBufferFromEntity but I think it's bug and GetBufferFromEntity also must be implemented in CS for convention. @Joachim_Ante, or I missing some thing and EntityManager.GetBufferFromEntity works fine in CS without adding dependencies in SafetyManager? (I just not use GetBufferFromEntity in ComponentSystem :) in all my cases it's in JobComponentSystem)
     
    Last edited: Nov 25, 2018
    Calebsem likes this.
  8. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Without adding dependencies in SafetyManager (by AddReaderWriter which internal) it can throw errors in some cases. Look how it work in JCS source code, Unity sets dependencies for correct work:
    Code (CSharp):
    1. public BufferFromEntity<T> GetBufferFromEntity<T>(bool isReadOnly = false) where T : struct, IBufferElementData
    2.         {
    3.             AddReaderWriter(isReadOnly ? ComponentType.ReadOnly<T>() : ComponentType.Create<T>());
    4.             return EntityManager.GetBufferFromEntity<T>(isReadOnly);
    5.         }
     
  9. Calebsem

    Calebsem

    Joined:
    Mar 17, 2015
    Posts:
    4
    Oh yeah I got it! Thanks! Got to use a JobComponentSystem, it's working fine now
     
  10. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    Example of using
    What are the cases?

    You can get buffer using EntityManager.GetBuffer<TBuffer> only on the main thread using ComponentSystem, and safety check is necessary only when you have some parallelized jobs using JobComponentSystem.
    Am I missing something?
     
    Last edited: Nov 25, 2018
  11. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    You can get buffer in parallel as I write before not only in main thread.
     
  12. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Multiple jobs reads/writes same buffer.
     
  13. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    maybe only when you have two systems that write the same buffer - one ComponentSystem on the main thread (without safety check) and another JobComponentSystem with parallel jobs(i don't know how to write buffer there without disabling safety check), but unless you start mixing ComponentSystems with parallelized jobs in JobComponentSystems and disabling safety check there should not be any problems
     
    Last edited: Nov 25, 2018
  14. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    is it even possible to write to Dynamic Buffer in a parallel job without disabling safety check?
     
  15. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    Yes it is possible with IJobChunk
    Code (CSharp):
    1.  
    2. public struct BBuffer : IBufferElementData{
    3.   public int Value;
    4.   public static implicit operator int(BBuffer item) { return item.Value; }
    5.   public static implicit operator BBuffer(int id) { return new BBuffer { Value = id }; }
    6. }
    7. public class TestJobSys : JobComponentSystem{
    8.   private ComponentGroup _g;
    9.   protected override void OnCreateManager(){
    10.     base.OnCreateManager();
    11.     _g = GetComponentGroup( new EntityArchetypeQuery(){
    12.       All = new ComponentType[] { ComponentType.Create<BBuffer>(), },
    13.       None = Array.Empty<ComponentType>(),
    14.       Any = Array.Empty<ComponentType>(),
    15.     } );
    16.   }
    17.  
    18.   protected override JobHandle OnUpdate(JobHandle deps) => new Job(){
    19.     BBufferChunkType = GetArchetypeChunkBufferType<BBuffer>() // -RW
    20.   }.Schedule(_g, deps);
    21.  
    22.   [BurstCompile]
    23.   private struct Job : IJobChunk{
    24.     public ArchetypeChunkBufferType<BBuffer> BBufferChunkType;
    25.     public void Execute( ArchetypeChunk chunk, int chunkIndex ){
    26.       var buffers = chunk.GetBufferAccessor(BBufferChunkType);
    27.       for( int i = 0; i < buffers.Length; i++ ){
    28.         var buffer = buffers[i];
    29.         buffer[0] = 7;
    30.       }
    31.     }
    32.   }
    33. }
    34.  
    the open question is how to write to DynamicBuffer without disabling safety check in IJobProcessComponentDataWithEntity ?
     
  16. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    Weird, after recompilation I could no longer access GetBufferFromEntity from EntityManager.

    How can I get it from a ComponentSystem?
     
  17. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    You can't. This is probably an oversight and I assume it'll be added at some point.

    That said, what is the use case where you need GetBufferFromEntity in a ComponentSystem but can't use JobComponentSystem?

    What I'm trying to figure out is, GetBufferFromEntity should be used in jobs. But if you're chaining jobs you should be using JobComponentSystem. And if you're not using it in jobs you should just use EntityManager.GetBuffer<T>.
     
    Xerioz likes this.
  18. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    Guess you're right, although I do remember seeing performance improvements when using GetXXXFromEntity<T> lookups instead of the single GetXXX<T> lookup functions for non-job cases, so I thought it just made sense to have it accessible everywhere.
     
  19. b2937

    b2937

    Joined:
    Jul 1, 2019
    Posts:
    13
    A year passed and no change regarding this :(

    Would be nice if GetBufferFromEntity and GetComponentDataFromEntity could be made public again in EntityManager.

    It seems the only reason is because the API wants to promote the usage of jobs but sometimes things need to be processed on the main thread and having less type lookup overhead would certainly help.

    As a workaround I keep a dummy JobComponentSystem instance which I don't call Update() for in my custom ComponentSystemGroup to use them in regular component systems (luckily the two functions are public).

    Also it seems to me the safety checks through ENABLE_UNITY_COLLECTIONS_CHECKS are unnecessary for these, yet they are in the code which means GetBufferFromEntity and GetComponentDataFromEntity needs to be called in every function it is used instead of once at World boot-up.
     
  20. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Other reason than having to register reader/writer with the system, is probably it has high chance of not working when it read/write while other read/write that is going on when used arbitrarily outside of systems and therefore make the method feels buggy if available that they would rather not allow it.

    What if they are named "CompleteAllJobsAndGetComponentDataFromEntity", maybe it could become a more suitable API for EntityManager? But in that case it may sounds overly specific and verbose though it solve the problem and you can feel the inefficientcy just by reading the name. And I think they don't want to add a method that sounds inefficient. (And what if you hold onto that for a bit longer and use later when some other jobs start running again? Your CDFE then doesn't work anymore unless asked to CompleteAllJobs and use it synchronously consecutively.)
     
  21. b2937

    b2937

    Joined:
    Jul 1, 2019
    Posts:
    13
    Hmm, I guess that applies to all EntityManager.Get functions though...

    Oh well, it turns out in entities 0.3.0 GetBufferFromEntity and GetComponentDataFromEntity are available in both JobComponentSystem and ComponentSystem. Not mentioned at all in the changelog.
     
  22. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Method such as em.GetComponentData didn't return you a new thing to use to get the result, but return the result instantly so I think it is a bit different. (Therefore they can have a built-in job completion in there while still feel natural?) I think Unity do not want to give you any more data accessor that could go spoiled in a few moment and have EntityManager be the only one that can go straight to data with Get_