Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

API Deprecation FAQ (0.0.23)

Discussion in 'Data Oriented Technology Stack' started by AriaBonczek, Feb 28, 2019.

  1. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    Which APIs are being deprecated?
    • [Inject]
    • ComponentDataArray
    • SharedComponentDataArray
    • EntityArray
    • BufferArray
    • ComponentArray
    • GameObjectArray
    • ComponentGroupArray
    • Edit: Removed TransformAccessArray from this list until we have a good alternative
    Why are they being deprecated?
    Usability is always at the core of Unity, and the simplicity of our APIs is a key part of that. But simplicity should never come at the cost of transparency, especially when performance is involved. We've recently identified some key performance problems with these APIs which are not immediately obvious from the surface. While they provide a neat and simple way to access your data, they abstract away the systems underneath them, which makes identifying bottlenecks and optimizing your code more difficult. It becomes more difficult to move to the low-level APIs when performance or control requires it.

    So simply put, they make it harder to learn how to use ECS to write fast code.

    A more detailed explanation can be found in this talk from Unite LA 2018:


    What are the recommended replacements for _Array?
    • IJobProcessComponentData provides a simple way to iterate through and transform component data.
      • You can also use ForEach in a main-thread ComponentSystem for added simplicity, but at the cost of performance and parallelization.
    • IJobChunk and ComponentGroup.CreateArchetypeChunkArray provide more manual control, which may be necessary to solve certain problems efficiently.
    What are the recommended replacements for [Inject]
    • ComponentGroup injection (injecting structs) is replaced by (Job)ComponentSystem.GetComponentGroup, ForEach, IJobProcessComponentData, IJobChunk, and manual chunk iteration.
    • ComponentDataFromEntity injection is replaced by (Job)ComponentSystem.GetComponentDataFromEntity.
    • Injecting other systems is replaced by (Job)ComponentSystem.World.GetOrCreateManager.
      • Note: When converting the injection of a EntityCommandBufferSystem (formerly BarrierSystem), you must explicitly inform the EntityCommandBufferSystem of which JobHandle(s) to wait on before executing with EntityCommandBufferSystem.AddJobHandleForProducer. A well-commented example of this can be found in the HelloCube_06 sample.
    You can read about all of these APIs on the GitHub Documentation page. The repository also has Samples which show how these APIs are used.

    When will they be removed from the Entities package?
    All of these APIs will be marked as Obsolete in either release 0.0.23 or 0.0.24. At the earliest, they will be removed in release 0.0.25.

    What about my use case [x]?
    It's possible we've missed something, or that the new APIs aren't completely clear. Feel free to use this thread as a place to discuss your individual use cases and provide feedback.
     
    Last edited: Mar 1, 2019
    PixelJ, pcg, 5argon and 11 others like this.
  2. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    327
    Hi, how about IJobParallelForTransform? If TransformAccessArray is deprecated, how to iterate TransformAccess with other ComponentData?
     
    snaecoperth likes this.
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,708
    I think you can just iterate in ForEach on objects attached to entities.

    these particular delegates for example
    protected delegate void F_C<T0>(T0 c0) where T0 : class;
    protected delegate void F_EC<T0>(Entity entity, T0 c0) where T0 : class;
    protected delegate void F_ECD<T0, T1>(Entity entity, T0 c0, ref T1 c1) where T0 : class where T1 : struct, IComponentData;

    Look something like this
    this.ForEach((Transform transform) => {})
    this.ForEach((Entity entity, Transform transform) => {})
    this.ForEach((Entity entity, Transform transform, ref Position position) => {})

    There are other more overloaded versions for more components but you get the idea.
     
  4. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    327
    @tertle Thanks for reply, I didn't know that ForEach can iterate non-struct component. But it seems that using ForEach for Transform cannot obtain any advantage of IJob and Burst. CopyTransformFromGameObjectSystem still used GetTransformAccessArray() in p24.
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,708
    There is going to have to be a replacement because the Unity Hybrid systems depend on
    IJobParallelForTransform but I don't think you should really be using this yourself. You're probably better off manipulating the Position, Rotation, Scale components and letting the CopyTransfromToGameObjectSystem handle the sync back.
     
  6. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,395
    We use IJobParallelForTransform quite a bit although mostly because it was there not that we can't replace it easily. It was a good bridge for transforms between ECS and non ECS code. Plus just using TransformAccess everywhere in non ECS code for read only access shaved half a ms per frame, transforms are expensive suckers to access.
     
    M_R likes this.
  7. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    We're still working on the right replacement for TransformAccessArray. It'll likely be the last of these APIs to be officially deprecated. If we don't find a good replacement, we may end up just keeping it and deprecating the others.
     
    FROS7 likes this.
  8. yossi_horowitz_artie

    yossi_horowitz_artie

    Joined:
    Jan 30, 2019
    Posts:
    60
    I can't find anything in the samples repo by the name -- is that still to come?
     
  9. Fabrice_Lete

    Fabrice_Lete

    Unity Technologies

    Joined:
    May 5, 2018
    Posts:
    17
    Yes, there's an update to the HelloECS samples coming with the next package release. So it's not there yet but soon.
     
  10. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    497
    I've wanted to avoid ComponentDataArray. There's this one case where I couldn't find an alternative. I use ComponentGroup.SetFilter() then pass an instance of a SharedComponent to filter entities under a certain grouping, say manager. The filtered entities only works with ComponentGroup.GetComponentDataArray() after calling SetFilter(). It doesn't work with CreateArchetypeChunkArray() (still returns all entities).

    Any workaround for this?
     
  11. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,708
    Let me quote something from the source code of the package.
    Code (CSharp):
    1. m_FrozenGroup.SetFilter(subsceneTag);
    2.  
    3. //@TODO - revert to CreateArchetypeChunkArray once it supports filtering
    4. //var filteredChunks = m_FrozenGroup.CreateArchetypeChunkArray(Allocator.TempJob);
    5. var filteredChunks = m_FrozenGroup.GetAllMatchingChunks(Allocator.TempJob);
    So they know about it. Hopefully be supported by time it is officially marked as depreciated otherwise that'll be a bit awkward.

    I haven't used GetAllMatchingChunks but maybe that's a workaround?
     
    davenirline likes this.
  12. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    497
    Thanks! I'll try it.

    Edit: GetAllMatchingChunks() works. Unfortunately, it's set as internal. I had to hack it to set it to public.
     
  13. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    Good news everyone!
    CreateArchetypeChunkArray
    will support filtering in the next release!
     
    GliderGuy, jdoxbotica, 5argon and 4 others like this.
  14. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    928
    Say, I have entities with only this an IBufferElemenData

    Does accessing them in a job require me to add a "dummy" component?

    Code (CSharp):
    1. // components  
    2.     public struct KeyBuffer: IBufferElementData {public int Value;}
    3.     public struct KeyBufferDummy: IComponentData {public byte Dummy;}
    4.  
    5. // job
    6.     public struct ClearKeyBufferJob : IJobProcessComponentDataWithEntity<KeyBufferDummy>
    7.     {
    8.         [NativeDisableParallelForRestriction, WriteOnly] public BufferFromEntity<KeyBuffer> keyBufferFromEntity;
    9.          
    10.         public void Execute(Entity e, int i, [ReadOnly] ref KeyBufferDummy dummy)
    11.         {  
    12.             keyBufferFromEntity[e].Clear();
    13.         }
    14.     }
     
  15. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    379
    I'm having trouble understanding how to not use these in the newest version.

    Here's a preview of a system I have that changes Volume weight based on the time of the day.

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using UnityEngine;
    5. using UnityEngine.Rendering;
    6.  
    7. namespace Game
    8. {
    9.     public class WorldTimeVolumeSystem : ComponentSystem
    10.     { ComponentGroup m_volumes;
    11.  
    12.         protected override void OnStartRunning()
    13.         {
    14.             base.OnStartRunning();
    15.             m_volumes = GetComponentGroup(
    16.                 typeof(WorldTimeSpan),
    17.                 typeof(WorldTimeVolume),
    18.                 typeof(Volume));
    19.         }
    20.  
    21.         protected override void OnUpdate()
    22.         {
    23.             var volumes     = m_volumes.GetComponentArray<Volume>();
    24.             var wtVolumes   = m_volumes.GetComponentDataArray<WorldTimeVolume>();
    25.             var spans       = m_volumes.GetComponentDataArray<WorldTimeSpan>();
    26.      
    27.             // DO THINGS
    28.            
    29.         }
    30.      
    31.     }
    32. }
    33.  
    34.  
    Now the "GetComponentDataArray" parts get underlined in green saying the method is deprecated.

    It seems like the suggested alternatives are for Jobs, but what if, like in my case, I can't use Jobs because I'm playing with a legacy component (UnityEngine.Rendering.Volume)? And I can't use prefabs as these things are level art related and therefore are better if they stay in the scene.

    It would be nice if ECS examples provided this kind of scenario where it shows how we can play with non-jobifiable components such as rigidbodies, lights, animators or volumes. And not instanced as prefabs but just regular scene objects.

    I may be able to figure how out to convert my existing code to fit the deprecation, but everytime these changes come I'm a bit lost :( I know it is a preview but any hint would be greatly appreciated :) Cheers!
     
  16. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    You can use ComponentSystem.ForEach to access Components and ComponentData from a main thread ComponentSystem. An example of this can be found here: https://github.com/Unity-Technologi...S/HelloCube_01_ForEach/RotationSpeedSystem.cs
     
  17. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    Also as far as ToEntityArray()/ToComponentDataArray() etc goes, these functions are copying data from the chunks. This has a cost associated with it. Using IJobProcessComponentData, IJobChunk, or CreateArchetypeChunkArray will allow you to access and transform the data in place, and will generally be faster and allocate less memory.
     
    Cynicat, FROS7 and Piefayth like this.
  18. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    379
    Both interfaces can't be used with non-IComponentData. As for CreateArchetypeChunkArray, I simply don't know how to use this, and again unsure this can query standard components.

    That only works with IComponentData, it seems.

    So my question remains: What's the best / fastest way to iterate through standard components in ECS if not the two deprecated methods?

    Any example of that would be greatly appreciated as they aren't shown in the GitHub Samples (RotationSystem uses ForEach which can't process my Volume components as they aren't IComponentData) nor are they documented anywhere.

    Standard components, such as Volumes, Lights and Rigidbodies won't be ECS-compliant for quite a while (years?) so keeping them examplified would be really nice IMO.
     
    Last edited: Mar 5, 2019
    pahe likes this.
  19. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    80
    The order of the parameters for the ForEach delegate is very specific. If you look at the ForEachIterator.generated.cs in Unity.Entities/Iterators in the packages folder you'll find a each of the different possible delegates one can use as well as their constraints. I've used some regex to extract each of the different permutations - all 178 of them - and jammed it into the file I attached with this post. It essentially lists the delegates with the naming schema of F_xxxx where xxxx is the combination and order of specific parameter types. The legend to those types can be seen here:

    • E - Entity
    • C - Component
    • B - IBufferElementData
    • D - IComponentData
    • S - ISharedComponentData
    This list might still be very incomplete, but it should give you a basic idea of what you can and a can not do. For IJobProcessComponentData the type Component can't be used as these don't have the same performance guarantees an IComponentData would have.
     

    Attached Files:

  20. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    379
    I assume this is a temporary measure as scrolling through 178 permutations to find the right order isn't super convenient :p but anyway good to know at least it is compatible with components.
     
  21. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    There is also a ToComponentAray<T>() coming down the pipe which will create a T[]. Will likely be in this week's release (0.0.24 I believe).

    As far the ForEach parameter orders, I'm not sure if there are specific plans to add more permutations, but I can bring this up as an issue with the team.
     
    FROS7 likes this.
  22. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    The plan is to provide overloads for IJobProcessComponentData that allow the use of IBufferElementData. No ETA on this currently, but it's on our todo list.

    For now a dummy component seems like the right choice.
     
    sngdan likes this.
  23. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    80
    Those delegates are generated so adding more should be relatively trivial, but personally I would be fine with just a consistent order for the parameters.

    @alexandre-fiset this made me realise I need to become more comfortable with tools like grep to easily find a specific order.
     
  24. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    598
    At least, once you realize the naming scheme, if you have an IDE with code completion or navigate to symbol you can look them up pretty quick.
     
  25. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    379
    I don't think we need more parameters but maybe more examples with standard components, and better lisibility.

    Navigating to them was not my issue. I had issue figuring out what they meant. F_D = IComponentData wasn't super intuitive. Furthermore, following the samples format of ForEach (ref RotationSpeed speed) did not work with Components (here F_C). I had to do something like ForEach (RigidBody rigidBody, ref RotationSpeed speed).

    In the end I just find that method a bit bloated and unclear, but that can be fixed with better naming of properties and more diverse samples in the GitHub repo.
     
    Last edited: Mar 5, 2019
  26. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    598
    It'd be good for the tool that generates the code (or perhaps the one that crawls for documentation) to generate a convenient table of current valid combinations for a lot of these delegate signatures to put on the doc/samples repo. This could probably be applied to all of the IJobProcessComponent<> variants as well.
     
  27. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,395
    So my take on this is if you have ECS based features that are relatively stable, it's probably a good idea to just sit on whatever version they are using now and wait until ECS api's settle a bit? At a glance I see a good 2-3 days work in refactoring our existing systems, and I'm guessing if I did that now I'd be doing it again in a few months also.
     
  28. Seto

    Seto

    Joined:
    Oct 10, 2010
    Posts:
    226
  29. Seto

    Seto

    Joined:
    Oct 10, 2010
    Posts:
    226
    You can with IJobChunk directly with only DynamicBuffers.
    https://gist.github.com/SetoKaiba/c323ac39775023d3992132eb4072a6a7
    You can just take my code as reference. You can only use the archetype for buffer to iterate with it.
    But for me the problem is I can't iterate the SharedComponentData.
     
    marwi likes this.
  30. Whitepot

    Whitepot

    Joined:
    May 19, 2017
    Posts:
    8
    I'm in the process of moving my hybrid systems to using ComponentSystem.ForEach and I'm having issues using it with zero-sized ICompoentData components that act as a tag. When I run the system I get the following error:

    ArgumentException: ArchetypeChunk.GetNativeArray<Selected> cannot be called on zero-sized IComponentData
    Unity.Entities.ArchetypeChunk.GetNativeArray[T]​

    Where "Selected" is the component I'm using as a tag.

    I understand Unity ECS handles zero-sized IComponentData differently for optimisation sake but is there a way to use such an IComponentData to filter the component group ForEach iterates over, since I only want to run this system on entities that have the "Selected" tag? Something like IJobProcessComponentData's RequireComponentTag attribute? Or will I just have to use chunk iteration when I want to use a tag component?

    This is my current code that's running into the issue:
    Code (CSharp):
    1. ForEach((SomeManagedComponent foo, ref Selected selected) =>
    2.             {
    3.                 foo.bar();
    4.             });
    where selected is just:
    Code (CSharp):
    1. public struct Selected : IComponentData
    2. {
    3. }
    4.  
    Edit: Thanks arielsan that did the trick
     
    Last edited: Mar 14, 2019
  31. arielsan

    arielsan

    Joined:
    Dec 3, 2013
    Posts:
    28
    Hi, you can't use tag components in ForEach (don't know if they will ever be supported), however, if you are on preview27 you can do:

    Code (CSharp):
    1. Entities.WithAll<Selected>().ForEach(...);
    And If you are on a previous version, you can create a group with the Selected component data and then use:

    Code (CSharp):
    1. ForEach((SomeManagedComponent foo) => { ... }, myGroup);
    Hope this answers your question.
     
  32. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,265
    1. Should
    UpdateInjectedComponentGroups()
    be marked as deprecated too?
    2. For some reason only `JobComponentSystem` has `GetBufferFromEntity`, so I have been using [Inject] to get GetBufferFromEntity for my normal ComponentSystem. But with Inject deprecated I am not sure how to get GetBufferFromEntity now. (Other than making a dummy JCS just for getting that)
     
    Last edited: Mar 10, 2019
  33. Seto

    Seto

    Joined:
    Oct 10, 2010
    Posts:
    226
    For problem 2, EntityManager.GetBuffer<T>(entity)?
     
  34. Seto

    Seto

    Joined:
    Oct 10, 2010
    Posts:
    226
    What about my use case [x]?
    It's possible we've missed something, or that the new APIs aren't completely clear. Feel free to use this thread as a place to discuss your individual use cases and provide feedback.
    @AriaBonczek Could you please have a look at it? It's a case which is unsupported after the deprecation.
     
  35. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    80
    @Seto if I were you I wouldn't worry too much about not being able to use Burst with that job. Looking at the example I see no reason why this won't work without Burst. Without knowing precisely what the use case is for requiring a SharedComponentData for this particular case there's no way to discern if there is some Burst-friendly workaround.
     
  36. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    For now the right solution for this is to use ArchetypeChunk.GetSharedComponentData(...) to do this. Unfortunately ISharedComponentData in jobs is currently unsupported since ISharedComponentData can be managed. Its on our roadmap to add the ability to use unmanaged ISharedComponentData in a job, but for now if you'd like to use ISharedComponentData in a job, you must pass the unmanaged data from inside of it into the job struct directly.

    An example of accessing ISharedComponentData by chunk can be found in the
    MoveEntitiesWithSharedComponentData test in "Packages/com.unity.entities/Unity.Entities.Tests/MoveEntitiesFromTests.cs"
     
    Bas-Smit, Sylmerria, Seto and 2 others like this.
  37. Justin_Larrabee

    Justin_Larrabee

    Joined:
    Apr 24, 2018
    Posts:
    88
    Why has GetComponentDataFromEntity (and the buffer version) been removed from regular component systems in the latest release?
     
    MostHated likes this.
  38. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,395
    We are on 2018 with Entities preview.21. I want to hold off upgrading until more things settle. If we moved to 2019 when it's released, would preview 21 still work there? I don't want to end up having to upgrade everything at once, that's the worst case scenario I want to avoid.
     
  39. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    191
    • "ComponentDataFromEntity injection is replaced by (Job)ComponentSystem.GetComponentDataFromEntity."
    Quick question: should GetComponentDataFromEntity be called from OnUpdate() or OnCreateManager() ?
     
  40. Ziboo

    Ziboo

    Joined:
    Aug 30, 2011
    Posts:
    295
    So I'm kind of lost now...
    I have a IJobProcessComponentData that run though some component, but I also need to modify another group from what's happening in this job...
    Basically having a IJobProcessComponentData runing on two differents sets, writing.in both of them.
    How can I do that ?
     
  41. AriaBonczek

    AriaBonczek

    Unity Technologies

    Joined:
    Jul 20, 2018
    Posts:
    24
    OnUpdate(). ComponentDataFromEntity requires the version number of the system for safety checks.
     
    Mr-Mechanical likes this.
  42. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,714
    If you want to schedule them from the same system, schedule them with a JobHandle of the first job as the dependency of the second.
     
  43. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,395
    Btw thanks for not rushing to remove stuff, makes upgrading a lot easier and I imagine more then a few people are waiting for 2019 release to hit before making the jump.
     
  44. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,395
    So we have a IJobParallelForTransform job where we have been passing in component arrays with ComponentDataArray. Our own manual syncing of transforms to entities.

    When a transform is added/removed we re create the entire transform array. Doesn't happen that often but what is the best way to handle this type of synchronization now?
     
  45. Justin_Larrabee

    Justin_Larrabee

    Joined:
    Apr 24, 2018
    Posts:
    88
    It's mentioned in the release notes that "GetBufferFromEntity and GetComponentDataFromEntity only available on JobComponentSystem", but GetComponentDataFromEntity is still available on ComponentSystemBase. Should we migrate any non-job systems away from using this API?

    And if so, what is the best way to access optional component types on entities outside of a ComponentGroup, just calling directly into the EntityManager via Has/GetComponent?
     
    Last edited: Mar 28, 2019
  46. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    327
    Why ToComponentArray() allocates managed array at every call? I think that if ToComponentArray() return
    non-garbage array (old ComponentArray), it will help many hybrid approaches. ForEach() does not fit for creating temporary array which has same size to components. In example, create NativeArray<RaycastCommand> from monobehaviour components. Although chunk iteration with ArchetypeChunkComponentObjects can achieve this, but that code will be very annoying for simply createing single large array from multiple chunks.
     
  47. mmankt

    mmankt

    Joined:
    Apr 29, 2015
    Posts:
    35
    Spuds Unearthed was built with the very first release of ECS , now i have an almost finished, well running project and i'm looking forward to converting 128 inject-based systems to the new api :D
     
    Flurgle, Alverik, jdtec and 1 other person like this.
  48. Skyblade

    Skyblade

    Joined:
    Nov 19, 2013
    Posts:
    73
    Formerly I created my entitites in a game bootstrap using the following code:
    Code (CSharp):
    1. var entityManager = World.Active.GetOrCreateManager<EntityManager>();
    2. var springArchetype = entityManager.CreateArchetype(...)
    Now there is an error:
    How do I reference EntityManager now?
     
  49. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    165
    Use World.EntityManager. The latest Entities update renamed a lot of the API
     
    Alverik and Skyblade like this.
  50. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    456
    Hi @AriaBonczek,
    1) Will IComponent class happen anytime soon? It was announced since last year November.
    2) any plan to implement accessing multiple components for singleton entity at once API just like Entities.With(query).ForEach API? I expect it will get better performance than Entities.With(query).ForEach API.
     
    Last edited: Apr 15, 2019
    Abbrew likes this.