Property Entities
Entities
Provides a mechanism for defining an entity query and invoking a lambda expression on each entity selected by that query.
Declaration
protected ForEachLambdaJobDescription Entities { get; }
Property Value
Type | Description |
---|---|
Unity.Entities.CodeGeneratedJobForEach.ForEachLambdaJobDescription |
Remarks
The Entities property provides a convenient mechanism for implementing the most common operation performed by systems in ECS, namely, iterating over a set of entities to read and update component data. Entities provides a LINQ method-style syntax that you use to describe the work to be performed. Unity uses a compiler extension to convert the description into efficient, (optionally) multi-threaded executable code.
Entities
.WithName("Update_Position") // Shown in error messages and profiler
.WithAll<LocalToWorld>() // Require the LocalToWorld component
.ForEach(
// Write to Displacement (ref), read Velocity (in)
(ref Position position, in Velocity velocity) =>
{
//Execute for each selected entity
position = new Position()
{
// dT is a captured variable
Value = position.Value + velocity.Value * dT
};
}
)
.ScheduleParallel(); // Schedule as a parallel job
Describing the entity query
The components that you specify as parameters for your lambda function are automatically added to the entity query created for an Entities.Foreach construction. You can also add a number of "With" clauses to identify which entities that you want to process These clauses include:
WithAll
-- An entity must have all of these component types (in addition to having all the component types found in the lambda parameter list).WithAny
-- An entity must have one or more of these component types.WithNone
-- An entity must not have any of these component types.WithChangeFilter()
-- Only selects entities in chunks in which the specified component might have changed since the last time this system instance updated.WithSharedComponentFilter(ISharedComponentData)
-- Only select chunks that have a specified value for a shared component.WithEntityQueryOptions(EntityQueryOptions)
-- Specify additonal options defined in a EntityQueryOptions object.WithStoreEntityQueryInField(EntityQuery)
-- Stores the EntityQuery object generated by the Entities.ForEach in an EntityQuery field on your system. You can use this EntityQuery object for such purposes as getting the number of entities that will be selected by the query. Note that this function assigns the EntityQuery instance to your field when the system is created. This means that you can use the query before the first execution of the lambda function.
Defining the lambda function
Define the lambda function inside the ForEach()
method of the entities property. When the system invokes the
lambda function, it assigns values to the function parameters based on the current entity. You can pass ECS
component types as parameters as well as a set of special, named parameters.
- Parameters passed-by-value first (no parameter modifiers)
- Writable parameters second(
ref
parameter modifier) - Read-only parameters last(
in
parameter modifier)
All components should use either the ref
or the in
parameter modifier keywords.
You can pass up to eight parameters to the lambda function. In addition to ECS component types, you can use the following:
Entity entity
— the Entity instance of the current entity. (The parameter can be named anything as long as the type is Entity.)int entityInQueryIndex
— the index of the entity in the list of all entities selected by the query. Use the entity index value when you have a native array that you need to fill with a unique value for each entity. You can use the entityInQueryIndex as the index in that array. The entityInQueryIndex should also be used as thesortKey
for adding commands to a concurrent EntityCommandBuffer.int nativeThreadIndex
— a unique index for the thread executing the current iteration of the lambda function. When you execute the lambda function using Run(), nativeThreadIndex is always zero.
.ForEach((Entity entity,
int entityInQueryIndex,
ref WritableComponent aReadwriteComponent,
in ReadonlyComponent aReadonlyComponent) =>
{
/*..*/
})
Capturing variables
You can capture local variables in the lambda function. When you execute the function using a job (by
calling ScheduleParallel()
or ScheduleSingle()
instead of Run()
) there are some restrictions on the
captured variables and how you use them:
- Only native containers and blittable types can be captured.
- A job can only write to captured variables that are native containers. (To “return” a single value, create a native array with one element.)
You can use the following functions to apply modifiers and attributes to the captured native container variables, including native arrays. See Job.WithCode for a list of these modifiers and attributes.
Executing the lambda function
To execute a ForEach construction, you have three options:
ScheduleParallel()
-- schedules the work to be done in parallel using the C# Job system. Each parallel job instance processes at least one chunk of entities at a time. In other words, if all the selected entities are in the same chunk, then only one job instance is spawned.Schedule()
-- schedules the work to be done in a single job (no matter how many entities are selected).Run()
-- evaluates the entity query and invokes the lambda function for each selected entity immediately on the main thread. CallingRun()
completes the system Dependency JobHandle before running, blocking the main thread, if necessary, while it waits for those jobs to finish.
When you call Schedule() or ScheduleParallel() without parameters, then the scheduled jobs use the current value of Dependency. You can also pass a JobHandle to these functions to define the dependencies of the scheduled job. In this case, the Entities.forEach construction returns a new JobHandle that adds the scheduled job to the passed in JobHandle. See Dependency for more information.
Additional options
WithName(string)
-— assigns the specified string as the name of the generated job class. Assigning a name is optional, but can help identify the function when debugging and profiling.WithStructuralChanges()
-— executes the lambda function on the main thread and disables Burst so that you can make structural changes to your entity data within the function. For better performance, use an EntityCommandBuffer instead.WithoutBurst()
—- disables Burst compilation. Use this function when your lambda function contains code not supported by Burst or while debugging.WithBurst(FloatMode, FloatPrecision, bool)
— sets options for the Burst compiler:- floatMode —- sets the floating point math optimization mode.Fast mode executes faster, but produces larger floating point error than Strict mode.Defaults to Strict. See Burst FloatMode.
- floatPrecision —- sets the floating point math precision. See Burst FloatPrecision.
- synchronousCompilation —- compiles the function immediately instead of scheduling the function for compilation later.