Components

Components contain the data associated to an Entity, i.e. their properties or state variables.

Component types

Components are distinguished by their type, and each entity can only have one component of a certain type.

In Ark, any type can be used as a component. However, it is highly recommended to use immutable types, because mutable objects are usually allocated on the heap in Julia, which defeats Ark's claim of high performance. Immutable types are disallowed by default, but can be enabled when constructing a World by the optional argument allow_mutable of the world constructor.

Accessing components

Although the majority of the logic in an application that uses Ark will be performed in Queries, it may be necessary to access components for a particular entity. One or more components of an entity can be accessed via @get_components:

(pos, vel) = @get_components(world, entity, (Position, Velocity))

Similarly, the components of an entity can be overwritten by new values via set_components!, which is particularly useful for immutable components (which are the default):

set_components!(world, entity, (Position(0, 0), Velocity(1,1)))

Adding and removing components

A feature that makes ECS particularly flexible and powerful is the ability to add components to and remove them from entities at runtime. This works similar to component access and can be done via add_components! and @remove_components!:

entity = new_entity!(world, ())

add_components!(world, entity, (Position(0, 0), Velocity(1,1)))
@remove_components!(world, entity, (Velocity,))

Note that adding an already existing component or removing a missing one results in an error.

Also note that it is more efficient to add/remove multiple components at once instead of one by one. To allow for efficient exchange of components (i.e. add some and remove others in the same operation), @exchange_components! can be used:

entity = new_entity!(world, (Position(0, 0), Velocity(1,1)))

@exchange_components!(world, entity; 
    add    = (Health(100),),
    remove = (Position, Velocity),
)

Component storages

Components are stored in archetypes, with the values for each component type stored in a separate array-like column. For these columns, Ark offers two storage modes:

  • Vector storage stores component object in a simple vector per column. This is the default.

  • StructArray storage stores components in an SoA data structure similar to StructArrays. This allows access to field vectors in queries, enabling SIMD-accelerated, vectorized operations and increased cache-friendliness if not all of the component's fields are used. However, this storage mode comes with an overhead of ≈10-20% for component operations and entity creation. Further, component access with @get_components and set_components! is also slower. Also note the mutable components are not allowed in StructArray storages.

The storage mode can be selected per component type by using StructArrayStorage or VectorStorage during world construction.

world = World(
    Position => VectorStorage,
    Velocity => StructArrayStorage,
)

The default is VectorStorage if no storage mode is specified:

world = World(
    Position,
    Velocity => StructArrayStorage,
)