A system is a unit of code which belongs to a world and which runs on the main thread (usually once per frame). Normally, a system will only access entities of its own world, but this is not an enforced restriction.
A system is defined as a struct implementing the ISystem
interface, which has three key methods:
ISystemState method |
Description |
---|---|
OnUpdate() |
Normally called once per frame, though this depends upon the SystemGroup to which the system belongs. |
OnCreate() |
Called before the first call to OnUpdate and whenever a system resumes running. |
OnDestroy() |
Called when a system is destroyed. |
A system may additionally implement ISystemStartStop
, which has these methods:
ISystemStartStop method |
Description |
---|---|
OnStartRunning() |
Called before the first call to OnUpdate and after any time the system's Enabled property is changed from false to true . |
OnStopRunning() |
Called before OnDestroy and after any time the system's Enabled property is changed from true to false . |
The systems of a world are organized into system groups. Each system group has an ordered list of systems and other system groups as its children, so the system groups form a hierarchy, which determines the update order. A system group is defined as a class inheriting from ComponentSystemGroup
.
When a system group is updated, the group normally updates its children in their sorted order, but this default behavior can be overridden by overriding the group's update method.
A group's children are re-sorted every time a child is added or removed from the group.
The [UpdateBefore]
and [UpdateAfter]
attributes can be used to determine the relative sort order amongst the children in a group. For example, if a FooSystem
has the attribute UpdateBefore(typeof(BarSystem))]
, then FooSystem
will be put somewhere before BarSystem
in the sorted order. If, however, FooSystem
and BarSystem
don't belong to the same group, the attribute is ignored. If an ordering attribute contradicts another, an exception is thrown.
By default, an automatic bootstrapping process creates a default world with three system groups:
InitializationSystemGroup
, which updates at the end of theInitialization
phase of the Unity player loop.SimulationSystemGroup
, which updates at the end of theUpdate
phase of the Unity player loop.PresentationSystemGroup
, which updates at the end of thePreLateUpdate
phase of the Unity player loop.
The systems and system groups will normally be added to the SimulationSystemGroup
, but this can be overridden by marking them with the [UpdateInGroup]
attribute. For example, if a FooSystem
has the attribute UpdateInGroup(typeof(InitializationSystemGroup))]
, then FooSystem
will be added to the InitializationSystemGroup
instead of the SimulationSystemGroup
. A system or system group with the [DisableAutoCreation]
attribute will not be instantiated by the automatic bootstrapping.
The automatic bootstrapping process can be disabled with scripting defines:
Scripting define | Description |
---|---|
#UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_RUNTIME_WORLD |
Disables automatic bootstrapping of the default world. |
#UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_EDITOR_WORLD |
Disables automatic bootstrapping of the Editor world. |
#UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP |
Disables automatic bootstrapping of both the default world and the Editor world. |
When automatic bootstrapping is disabled, your code is responsible for:
- Creating any worlds you need.
- Calling
World.GetOrCreateSystem<T>()
to add the system and system group instances to the worlds. - Inserting updates of the top-level system groups (e.g.
SimulationSystemGroup
) into the Unity PlayerLoop.
Alternatively, automatic bootstrapping can be customized by creating a class that implements ICustomBootstrap
.
🕹 See examples of world creation and customized bootstrapping.
A world has a Time
property, which returns a TimeData
struct, containing the frame delta time and elapsed time. The time value is updated by the world's UpdateWorldTimeSystem
. The time value can be manipulated with these World
methods:
World method |
Description |
---|---|
SetTime |
Set the time value. |
PushTime |
Temporarily change the time value. |
PopTime |
Restore the time value from before the last push. |
Some system groups, like FixedStepSimulationSystemGroup
, push a time value before updating their children and then pop the value once done updating. Systems in these groups effectively see the pushed time value.
The SystemState
parameter of a system's OnUpdate()
, OnCreate()
, and OnDestroy()
methods represents the state of the system instance and has important methods and properties, including:
Method or property | Description |
---|---|
World |
The system's world. |
EntityManager |
The EntityManager of the system's world. |
Dependency |
A JobHandle used to pass job dependencies between systems. |
GetEntityQuery() |
Returns an EntityQuery . |
GetComponentTypeHandle<T>() |
Returns a ComponentTypeHandle<T> . |
GetComponentLookup<T>() |
Returns a ComponentLookup<T> . |
⚠ IMPORTANT |
---|
Although entity queries, component type handles, and component lookups can be acquired directly from the EntityManager , it is generally proper for a system to only acquire these things from the SystemState instead. By going through SystemState , the component types accessed get tracked by the system, which is essential for the Dependency property to correctly pass job dependencies between systems. See more about jobs that access entities. |
The SystemAPI
class has many static convenience methods, covering much of the same functionality as World
, EntityManager
, and SystemState
.
The SystemAPI
methods rely upon source generators, so they only work in systems and IJobEntity
(but not IJobChunk
). The advantage of using SystemAPI
is that these methods produce the same results in both contexts, so code that uses SystemAPI
will generally be easier to copy-paste between these two contexts.
📝 NOTE |
---|
If you get confused about where to look for key Entities functionality, the general rule is to check SystemAPI first. If SystemAPI doesn't have what you're looking for, look in SystemState , and if what you're looking for isn't there, look in the EntityManager and World . |
SystemAPI
provides a special Query()
method that, through source generation, helps conveniently create a foreach that loops through the entities and components matching a query.
🕹 See examples of using SystemAPI.Query()
.