Search Unity

Entities.With() : Proper way to access Components?

Discussion in 'Entity Component System' started by pakfront, Jun 16, 2019.

  1. pakfront

    pakfront

    Joined:
    Oct 6, 2010
    Posts:
    551
    The docs and package test code don't actually have an example of accessing and modifying component data in a ComponentSystem using Entities.With(). They just have
    //do stuff


    I'm using an exiting EntityQuery.

    Do I just use EntityManager.Get/SetComponentData() or is there a better/more efficient way?

    I realize that ComponentSystem is not efficient, but I have a small number of entities to iterate over and only once in a while. The problem is a bit a hard to parallelize 'til I prototype it, so this seemed a simple way to get it working.

    Current simplified version for example only:
    Code (CSharp):
    1.         protected override void OnUpdate()
    2.         {
    3.             Entities.With(allRootsGroup).ForEach((Entity entity) =>
    4.             {
    5.                 // Debug.Log("Root "+entity);
    6.                 if (EntityManager.HasComponent<PlayerInput>(entity))
    7.                 {
    8.                     var order = EntityManager.GetComponentData<PlayerInput>(entity);
    9.                     //more complex stuff happens here
    10.                     EntityManager.SetComponentData(entity, new Goal
    11.                     {
    12.                         Value = order.Goal
    13.                     });
    14.                 }
    15.                 else {
    16.                   // do other stuff
    17.                 }
    18.             });
    19.         }
     
    Last edited: Jun 16, 2019
  2. pakfront

    pakfront

    Joined:
    Oct 6, 2010
    Posts:
    551
    Ah, I can use generics, though I don't know if this is much faster.Also I cant; use Buffers as args i the lambda.
    Code (CSharp):
    1.         protected override void OnUpdate()
    2.         {
    3.             Entities.With(allRootsGroup).ForEach<Goal>((Entity entity, ref Goal goal) =>
    4.             {
    5.                  var children = EntityManager.GetBuffer<MyChild>(entity);
    6.  
    7.                 // Debug.Log("Root "+entity);
    8.                 if (EntityManager.HasComponent<PlayerInput>(entity))
    9.                 {
    10.                     var order = EntityManager.GetComponentData<PlayerInput>(entity);
    11.                     goal.Value = order.Goal;
    12.                 } else {
    13.                   // do other stuff
    14.                 }
    15.             });
    16.         }
     
    Last edited: Jun 16, 2019
  3. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    In your first example it would be as easy as this:
    Code (CSharp):
    1.     Entities.With(allRootsGroup).ForEach((ref PlayerInput input, ref Goal goal) =>
    2.     {
    3.       goal.Value = input.Goal;
    4.     });
     
  4. Guerro323

    Guerro323

    Joined:
    Sep 2, 2014
    Posts:
    25
    This code would only work if you are sure PlayerInput is on all entities of the group.
    The reason he use With() (and that he check if there is a PlayerInput component) instead of WithAll() is that some components can be present or not, if he access to a component that is not present on an entity, he can have a nullref exception.
     
  5. Guerro323

    Guerro323

    Joined:
    Sep 2, 2014
    Posts:
    25
    You can use buffers in ForEach:
    Code (CSharp):
    1.  
    2. Entities.WithAll(allRootsGroup).ForEach((Entity entity, DynamicBuffer<MyChild> children, ref Goal goal) =>
    3. {
    4.     // your stuff
    5. });
    6.  
     
    pakfront likes this.
  6. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    I've missed that possibility.
    In that case you can use:
    Code (CSharp):
    1.     Entities.With(allRootsGroup).ForEach((ref PlayerInput input, ref Goal goal) => {
    2.       if(UnsafeUtility.AddressOf(ref input) != null && UnsafeUtility.AddressOf(ref goal) != null)
    3.         goal.Value = input.Goal;
    4.     });
     
    Last edited: Jun 17, 2019
    pakfront likes this.