Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Unity Technologies committed Apr 5, 2019
1 parent 167c718 commit 8bb5e65
Show file tree
Hide file tree
Showing 279 changed files with 9,772 additions and 11,302 deletions.
46 changes: 23 additions & 23 deletions Documentation~/TableOfContents.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
<!-- Generated from ../Samples/Packages/com.unity.entities/Documentation~/toc.yml do not edit. -->
* [Overview](index.md)
* Core ECS
** [Entities](ecs_entities.md)
*** [Worlds](world.md)
** [Components](ecs_components.md)
*** [General Purpose Components](component_data.md)
*** [Shared Components](shared_component_data.md)
*** [System State Components](system_state_components.md)
*** [Dynamic Buffer Components](dynamic_buffers.md)
** [System](ecs_systems.md)
*** [Component Systems](component_system.md)
*** [Job Component Systems](job_component_system.md)
*** [Entity Command Buffers](entity_command_buffer.md)
*** [System Update Order](system_update_order.md)
** [Accessing Entity Data](chunk_iteration.md)
*** [Using IJobProcessComponentData](entity_iteration_job.md)
*** [Using IJobChunk](chunk_iteration_job.md)
*** [Using ComponentSystem and ForEach](entity_iteration_foreach.md)
*** [Manual iteration](manual_iteration.md)
*** [Component Groups](component_group.md)
** [Versions and Generations](version_numbers.md)
** [Jobs in ECS](ecs_job_overview.md)
*** [ECS Job System extensions](ecs_job_extensions.md)
* [Entities](ecs_entities.md)
* [Worlds](world.md)
* [Components](ecs_components.md)
* [General Purpose Components](component_data.md)
* [Shared Components](shared_component_data.md)
* [System State Components](system_state_components.md)
* [Dynamic Buffer Components](dynamic_buffers.md)
* [System](ecs_systems.md)
* [Component Systems](component_system.md)
* [Job Component Systems](job_component_system.md)
* [Entity Command Buffers](entity_command_buffer.md)
* [System Update Order](system_update_order.md)
* [Accessing Entity Data](chunk_iteration.md)
* [Using IJobForEach](entity_iteration_job.md)
* [Using IJobChunk](chunk_iteration_job.md)
* [Using ComponentSystem and ForEach](entity_iteration_foreach.md)
* [Manual iteration](manual_iteration.md)
* [Component Groups](component_group.md)
* [Versions and Generations](version_numbers.md)
* [Jobs in ECS](ecs_job_overview.md)
* [ECS Job System extensions](ecs_job_extensions.md)
* Creating Gameplay
** [Transforms](transform_system.md)
** [Rendering](gp_rendering.md)
* [Transforms](transform_system.md)
* [Rendering](gp_rendering.md)
8 changes: 4 additions & 4 deletions Documentation~/chunk_iteration.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ In general, the most efficient way to iterate over your entities and components

The ECS API provides a number of ways to accomplish iteration, each with its own performance implications and restrictions. You can iterate over ECS data in the following ways:

* [IJobProcessComponentData](entity_iteration_job.md) — the simplest efficient way to process component data entity by entity.
* [IJobForEach](entity_iteration_job.md) — the simplest efficient way to process component data entity by entity.

* [IJobProcessComponentDataWithEntity](entity_iteration_job.md#with-entity) — slightly more complex than IJobProcessComponentData, giving you access to the entity handle and array index of the entity you are processing.
* [IJobForEachWithEntity](entity_iteration_job.md#with-entity) — slightly more complex than IJobForEach, giving you access to the entity handle and array index of the entity you are processing.

* [IJobChunk](chunk_iteration_job.md) — iterates over the eligible blocks of memory (called a *Chunk*) containing matching entities. Your Job Execute() function can iterate over the Elements inside each chunk using a for loop. You can use IJobChunk for more complex situations than supported by IJobProcessComponentData, while maintaining maximum efficiency.
* [IJobChunk](chunk_iteration_job.md) — iterates over the eligible blocks of memory (called a *Chunk*) containing matching entities. Your Job Execute() function can iterate over the Elements inside each chunk using a for loop. You can use IJobChunk for more complex situations than supported by IJobForEach, while maintaining maximum efficiency.

* [ComponentSystem](entity_iteration_foreach.md) — the ComponentSystem offers the Entities.ForEach delegate functions to help iterate over your entities. However, ForEach runs on the main thread, so typically, you should only use ComponentSystem implementations for tasks that must be carried out on the main thread anyway.

* [Manual iteration](manual_iteration.md) — if the previous methods are insufficient, you can manually iterate over entities or chunks. For example, you can get a NativeArray containing entities or the chunks of the entities that you want to process and iterate over them using a Job, such as IJobParallelFor.

The [ComponentGroup](component_group.md) class provides a way to construct a view of your data that contains only the specific data you need for a given algorithm or process. Many of the iteration methods in the list above use a ComponentGroup, either explicitly or internally.
The [EntityQuery](component_group.md) class provides a way to construct a view of your data that contains only the specific data you need for a given algorithm or process. Many of the iteration methods in the list above use a EntityQuery, either explicitly or internally.
54 changes: 27 additions & 27 deletions Documentation~/chunk_iteration_job.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,38 @@

You can implement IJobChunk inside a JobComponentSystem to iterate through your data by chunk. The JobComponentSystem calls your Execute() function once for each chunk that contains the entities that you want the system to process. You can then process the data inside each chunk, entity by entity.

Iterating with IJobChunk requires more code setup than does IJobProcessComponentData, but is also more explicit and represents the most direct access to the data, as it is actually stored.
Iterating with IJobChunk requires more code setup than does IJobForEach, but is also more explicit and represents the most direct access to the data, as it is actually stored.

Another benefit of using iterating by chunks is that you can check whether an optional component is present in each chunk (with Archetype.Has<T>) and process all the entities in the chunk accordingly.

The steps involved in implementing an IJobChunk Job include:

1. Identify the entities that you want to process by creating a ComponentGroup.
1. Identify the entities that you want to process by creating a EntityQuery.
2. Defining the Job struct, including fields for ArchetypeChunkComponentType objects to identifying the types of components the Job directly accesses, specifying whether the Job reads or writes to those components.
3. Instantiating the Job struct and scheduling the Job in the system OnUpdate() function.
4. In the Execute() function, getting the NativeArray instances for the components the Job reads or writes and, finally, iterating over the current chunk to perform the desired work.

The [ECS samples repository](https://github.com/Unity-Technologies/EntityComponentSystemSamples) contains a simple example, HelloCube_03_IJobChunk, that uses IJobChunk.

## Query for data with a ComponentGroup
## Query for data with a EntityQuery

A ComponentGroup defines the set of component types that an archetype must contain for the system to process its associated chunks and entities. An archetype can have additional components as well, but it must have at least those defined by the ComponentGroup. You can also exclude archetypes that contain specific types of components.
A EntityQuery defines the set of component types that an archetype must contain for the system to process its associated chunks and entities. An archetype can have additional components as well, but it must have at least those defined by the EntityQuery. You can also exclude archetypes that contain specific types of components.

For simple queries, you can use the JobComponentSystem.GetComponentGroup() function, passing in the component types:
For simple queries, you can use the JobComponentSystem.GetEntityQuery() function, passing in the component types:

``` c#
public class RotationSpeedSystem : JobComponentSystem
{
private ComponentGroup m_Group;
protected override void OnCreateManager()
private EntityQuery m_Group;
protected override void OnCreate()
{
m_Group = GetComponentGroup(typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>());
m_Group = GetEntityQuery(typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>());
}
//
}
````

For more complex situations, you can use an EntityArchetypeQuery. An EntityArchetypeQuery provides a flexible query mechanism to specify the component types:
For more complex situations, you can use an EntityQueryDesc. An EntityQueryDesc provides a flexible query mechanism to specify the component types:

* `All` = All component types in this array must exist in the archetype
* `Any` = At least one of the component types in this array must exist in the archetype
Expand All @@ -42,48 +42,48 @@ For more complex situations, you can use an EntityArchetypeQuery. An EntityArche
For example, the following query includes archetypes containing the RotationQuaternion and RotationSpeed components, but excludes any archetypes containing the Frozen component:

``` c#
protected override void OnCreateManager()
protected override void OnCreate()
{
var query = new EntityArchetypeQuery
var query = new EntityQueryDesc
{
None = new ComponentType[]{ typeof(Frozen) },
All = new ComponentType[]{ typeof(RotationQuaternion), ComponentType.ReadOnly<RotationSpeed>() }
}
};
m_Group = GetComponentGroup(query);
m_Group = GetEntityQuery(query);
}
```

The query uses `ComponentType.ReadOnly<T>` instead of the simpler `typeof` expression to designate that the system does not write to RotationSpeed.

You can also combine multiple queries by passing an array of EntityArchetypeQuery objects rather than a single instance. Each query is combined using a logical OR operation. The following example selects an archetypes that contain a RotationQuaternion component or a RotationSpeed component (or both):
You can also combine multiple queries by passing an array of EntityQueryDesc objects rather than a single instance. Each query is combined using a logical OR operation. The following example selects an archetypes that contain a RotationQuaternion component or a RotationSpeed component (or both):

``` c#
protected override void OnCreateManager()
protected override void OnCreate()
{
var query0 = new EntityArchetypeQuery
var query0 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationQuaternion)}
};

var query1 = new EntityArchetypeQuery
var query1 = new EntityQueryDesc
{
All = new ComponentType[] {typeof(RotationSpeed)}
};

m_Group = GetComponentGroup(new EntityArchetypeQuery[] {query0, query1});
m_Group = GetEntityQuery(new EntityQueryDesc[] {query0, query1});
}
```

**Note:** Do not include completely optional components in the EntityArchetypeQuery. To handle optional components, use the `chunk.Has<T>()` method inside `IJobChunk.Execute()` to determine whether the current ArchetypeChunk has the optional component or not. Since all entities within the same chunk have the same components, you only need to check whether an optional component exists once per chunk -- not once per entity.
**Note:** Do not include completely optional components in the EntityQueryDesc. To handle optional components, use the `chunk.Has<T>()` method inside `IJobChunk.Execute()` to determine whether the current ArchetypeChunk has the optional component or not. Since all entities within the same chunk have the same components, you only need to check whether an optional component exists once per chunk -- not once per entity.

For efficiency and to avoid needless creation of garbage-collected reference types, you should create the ComponentGroups for a system in the system’s OnCreateManager() function and store the result in an instance variable. (In the above examples, the `m_Group` variable is used for this purpose.)
For efficiency and to avoid needless creation of garbage-collected reference types, you should create the EntityQueries for a system in the system’s OnCreate() function and store the result in an instance variable. (In the above examples, the `m_Group` variable is used for this purpose.)

### ## Define the IJobChunk struct

The IJobChunk struct defines fields for the data the Job needs when it runs, as well as the Job’s Execute() method.

In order to access the component arrays inside the chunks that the system passes to your Execute() method, you must create an ArchetypeChunkComponentType<T> object for each type of component that the Job reads or writes. These objects allow you to get instances of the NativeArrays providing access to the components of an entity. Include all the components referenced in the Job’s ComponentGroup that the Execute method reads or writes. You can also provide ArchetypeChunkComponentType variables for optional component types that you do not include in the ComponentGroup. (You must check to make sure that the current chunk has an optional component before trying to access it.)
In order to access the component arrays inside the chunks that the system passes to your Execute() method, you must create an ArchetypeChunkComponentType<T> object for each type of component that the Job reads or writes. These objects allow you to get instances of the NativeArrays providing access to the components of an entity. Include all the components referenced in the Job’s EntityQuery that the Execute method reads or writes. You can also provide ArchetypeChunkComponentType variables for optional component types that you do not include in the EntityQuery. (You must check to make sure that the current chunk has an optional component before trying to access it.)

For example, the HelloCube_03_IJobChunk example declares a Job struct that defines ArchetypeChunkComponentType<T> variables for two components, RotationQuaternion and RotationSpeed:

Expand Down Expand Up @@ -140,7 +140,7 @@ for (var i = 0; i < chunk.Count; i++)
}
```

If you the `Any` filter in your EntityArchetypeQuery or have completely optional components that don’t appear in the query at all, you can use the `ArchetypeChunk.Has<T>` function to test whether the current chunk contains the one of those components before using it:
If you the `Any` filter in your EntityQueryDesc or have completely optional components that don’t appear in the query at all, you can use the `ArchetypeChunk.Has<T>` function to test whether the current chunk contains the one of those components before using it:

if (chunk.Has<OptionalComp>(OptionalCompType))
{//...}
Expand All @@ -149,20 +149,20 @@ __Note:__ If you use a concurrent entity command buffer, pass the chunkIndex arg

## Skipping chunks with unchanged entities

If you only need to update entities when a component value has changed, you can add that component type to the change filter of the ComponentGroup used to select the entities and chunks for the job. For example, if you have a system that reads two components and only needs to update a third when one of the first two has changed, you could use a ComponentGroup as follows:
If you only need to update entities when a component value has changed, you can add that component type to the change filter of the EntityQuery used to select the entities and chunks for the job. For example, if you have a system that reads two components and only needs to update a third when one of the first two has changed, you could use a EntityQuery as follows:

``` c#
ComponentGroup m_Group;
protected override void OnCreateManager()
EntityQuery m_Group;
protected override void OnCreate()
{
m_Group = GetComponentGroup(typeof(Output),
m_Group = GetEntityQuery(typeof(Output),
ComponentType.ReadOnly<InputA>(),
ComponentType.ReadOnly<InputB>());
m_Group.SetFilterChanged(new ComponentType{ typeof(InputA), typeof(InputB)});
}
```

The ComponentGroup change filter supports up to two components. If you want to check more or aren't using a ComponentGroup, you can make the check manually. To make this check, compare the chunk’s change version for the component to the system’s LastSystemVersion using the `ArchetypeChunk.DidChange()` function. If this function returns false, you can skip the current chunk altogether since none of the components of that type have changed since the last time the system ran.
The EntityQuery change filter supports up to two components. If you want to check more or aren't using a EntityQuery, you can make the check manually. To make this check, compare the chunk’s change version for the component to the system’s LastSystemVersion using the `ArchetypeChunk.DidChange()` function. If this function returns false, you can skip the current chunk altogether since none of the components of that type have changed since the last time the system ran.

The LastSystemVersion from the system must be passed into the Job using a struct field:

Expand Down Expand Up @@ -214,6 +214,6 @@ protected override JobHandle OnUpdate(JobHandle inputDependencies)
}
```

When you call the GetArchetypeChunkComponentType<T> function to set your component type variables, make sure that you set the isReadOnly to true for components that the Job reads, but doesn’t write. Setting these parameters correctly can have a significant impact on how efficiently the ECS framework can schedule your Jobs. These access mode settings must match their equivalents in both the struct definition, and the ComponentGroup.
When you call the GetArchetypeChunkComponentType<T> function to set your component type variables, make sure that you set the isReadOnly to true for components that the Job reads, but doesn’t write. Setting these parameters correctly can have a significant impact on how efficiently the ECS framework can schedule your Jobs. These access mode settings must match their equivalents in both the struct definition, and the EntityQuery.

Do not cache the return value of GetArchetypeChunkComponentType<T> in a system class variable. The function must be called every time the system runs and the updated value passed to the Job.
Loading

0 comments on commit 8bb5e65

Please sign in to comment.