(Solved) Unable to get Entities.ForEach( ) examples working

I’m at a loss here.

I want to move multiple entities that all contain a set of components, in this case PlayerInput and Speed. If an entity has both of these components, I want to be able to move them around.

So, for this I create a MovementSystem class.

public class PlayerMovementSystem : ComponentSystem
{
    private struct Group
    {
        public Transform transform;
        public PlayerInput playerInput;
        public Speed speed;
    }

    protected override void OnUpdate()
    {
        Entities.WithAll<Group>().ForEach((entity) => {
            // Do stuff here
        }
    }
}

However, the entity does not have a Group here, nor does it have any of the members that Group contains.

So, I change the method to this instead, which Unity has samples for on their github aswell.

Entities.ForEach((ref Transform transform, ref PlayerInput playerInput, ref Speed speed) => { /*stuff*/ });

However, VS doesn’t like this.

Parameter 1 is declared as type 'ref PlayerInput' but should be 'Unity.Entities.Entity'

But as I learnt before, doing it that way means my Entity does not have the proper items in it.

If I just put the entity as first item in the lambda parameters, I get

Delegate 'EntityQueryBuilder.F_E' does not take 2 arguments

So I don’t know how to use the ForEach method to get all Entities with a component or set of components. Most other materials I found on it use the InjectAttribute. but that’s been deprecated and will no longer work.

For Entities.WithAll(), you pass the ComponentTypes into the params.

// By using Entities.WithAll<Group> you looking for all Entities which happen 
// to have an archetype of types: Group. This isn't valid because this is a local 
// structure which needs to be added to an entity.

    private struct Group
    {
        public Transform transform;
        public PlayerInput playerInput;
        public Speed speed;
    }

You have a few of options for a ComponentSystem:

  1. using an EntityQuery and Entities.With()
public class AComponentSystem : ComponentSystem {
  EntityQuery aUniqueQuery;
  protected override void OnCreate() {
    // I am assuming that PlayerInputs and Speed are structs with IComponentData
    aUniqueQuery = GetEntityQuery(typeof(Transform), typeof(PlayerInput), typeof(Speed));
  }
  
  protected override void OnUpdate() {
    // We follow the F_CDD delegate
    Entities.With(aUniqueQuery).ForEach(Transform transform, ref PlayerInputs inputs, ref Speed speed) => {});
  }
}
  1. What you posted which is just using Entities.ForEach
public class AComponentSystem : ComponentSystem {
 
  protected override void OnUpdate() {
    // We follow the F_CDD delegate
    Entities.ForEach(Transform transform, ref PlayerInputs inputs, ref Speed speed) => {});
  }
}
  1. Enitites.WithAll<>().ForEach
public class AComponentSystem : ComponentSystem {

  protected override void OnUpdate() {
    // We follow the F_CDD delegate
    Entities.WithAll<Transform, PlayerInputs, Speed>().ForEach(Transform transform, ref PlayerInputs inputs, ref Speed speed) => {});
  }
}

If you look at the ForEach in Visual Studio, you’ll see a lot of delegate patterns you can pass into the Entities.ForEach() iterator.

C - stands for class
D - stands for ComponentData (a struct which implements IComponentData)
S - stands for SharedComponentData (a struct which implements ISharedComponentData)
B - stands for BufferElementData (a struct which implements IBufferElementData)
E - stands for Entity

All ComponentDatas are accessed via ref keywords as you need a reference to them.

EDIT: Urgh. Made a classic beginner’s mistake. I didn’t check to see if I changed the IComponentData classes to structs.

After I had done so, the delegates stopped spitting out errors. Thank you very much for your help.

Thank you for responding.
Unfortunately, none of the examples you have presented work for me. All of them fail at the same point, that is, the ForEach gives the same error as above.
Delegate 'EntityQueryBuilder.F_E' does not take 3 arguments
So I checked the declaration of the delegate method in the EntityQueryBuilder class. I searched for ForEach(F_ in this class, which should represent all delegate methods. However, there is only one method that corresponds to this pattern in this file.
public void ForEach(F_E action);
I should have mentioned this before, but the versions I use are:
Unity: 2019.1.5f1
Entities package: preview.33 - 0.0.12
Perhaps an update to one of these packages made the previous method obsolete. but I cannot prove that theory anywhere.

2 Likes

Np, glad you got it working :slight_smile: