Select and access data
Entities.ForEach
has its own mechanism to define the entity query that it uses to select the entities to process. The query automatically includes any components that you use as parameters of the lambda expression.
You can use the WithAll
, WithAny
, and WithNone
clauses to further refine which entities Entities.ForEach
selects. Refer to the SystemBase.Entities
API documentation for the complete list of query options.
The following example uses these clauses to select entities based on these parameters:
- The entity has the components,
Destination
,Source
, andLocalToWorld
- The entity has at least one of the components,
ObjectRotation
,ObjectPosition
, orObjectUniformScale
- The entity doesn't have a
ObjectNonUniformScale
component.
Entities.WithAll<LocalToWorld>()
.WithAny<Rotation, ObjectPosition, ObjectUniformScale>()
.WithNone<ObjectNonUniformScale>()
.ForEach((ref Destination outputData, in Source inputData) =>
{
/* do some work */
})
.Schedule();
In this example, only the Destination
and Source
components are accessed inside the lambda expression because they're the only components in the parameter list.
Access the EntityQuery object
Entities.ForEach
creates an EntityQuery
in OnCreate
, which you can use a copy of at any time, even before Entities.ForEach
is invoked.
To access this entity query, use WithStoreEntityQueryInField(ref query)
with the ref
parameter modifier. This method assigns a reference to the query to the field you provide. However, this EntityQuery
doesn't have any of the filters that the Entities.ForEach
invocation sets up.
The following example illustrates how to access the EntityQuery
object implicitly created for an Entities.ForEach
construction. The example uses the EntityQuery
object to invoke the CalculateEntityCount()
method and uses this count to create a native array with enough space to store one value per entity that the query selects:
private EntityQuery query;
protected override void OnUpdate()
{
int dataCount = query.CalculateEntityCount();
NativeArray<float> dataSquared
= new NativeArray<float>(dataCount, Allocator.Temp);
Entities
.WithStoreEntityQueryInField(ref query)
.ForEach((int entityInQueryIndex, in Data data) =>
{
dataSquared[entityInQueryIndex] = data.Value * data.Value;
})
.ScheduleParallel();
Job
.WithCode(() =>
{
//Use dataSquared array...
var v = dataSquared[dataSquared.Length - 1];
})
.WithDisposeOnCompletion(dataSquared)
.Schedule();
}
Access optional components
The Entities.ForEach
lambda expression doesn't support querying and accessing optional components with WithAny<T,U>
.
If you want to read or write to an optional component, split the Entities.ForEach
construction into multiple jobs for each combination of the optional components. For example, if you have two optional components, you need three ForEach
constructions: one including the first optional component, one including the second, and one including both components. Another alternative is to use IJobChunk
iterate by chunk. For more information, refer to Iterating over data by chunk.