Flecs: Entities and Components
Description: A fast entity component system (ECS) for C & C++

| Flecs v4.1 A fast entity component system (ECS) for C & C++

Loading...
Searching...
No Matches
Entities and Components

# Introduction

Entities and components are the main building blocks of any ECS application. This manual describes the behavior of entities and components in Flecs.

# Entities

Entities are uniquely identifiable objects in a game or simulation. In a real time strategy game, there may be entities for the different units, buildings, UI elements and particle effects, but also for example the camera, world and player.

By itself, an entity is just a unique identifier that does not contain any state. You cannot tell from the entity's type what kind of entity it is, as the type is just "entity".

In Flecs, an entity is represented by a 64 bit integer, which is also how it is exposed in the C API:

typedef uint64_t ecs_entity_t;
ecs_entity_t
ecs_id_t ecs_entity_t
An entity identifier.
Definition flecs.h:361

The first 32 bits of the entity are the "identifying" part: it is the number that uniquely identifies an object in the game. The remaining 32 bits are used by Flecs for liveliness tracking and various other purposes. This article has more details on the exact bit representation of entities.

Zero ("`0`") is the value that is reserved for invalid ids. Functions that return an entity id may return 0 to indicate that the function failed. 0 can also be used to indicate the absence of an entity, for example when a lookup by name didn't find anything.

## Creation

The following example shows how to create a new entity without any components:

- C

  ecs_entity_t my_entity = ecs_new(world);
  ecs_new
  ecs_entity_t ecs_new(ecs_world_t *world)
  Create new entity id.

- C++

  flecs::entity my_entity = world.entity();
  flecs::entity
  Entity.
  Definition entity.hpp:30

- C#

  Entity myEntity world.Entity();

- Rust

  let my_entity = world.entity();

Empty entities don't have any components, and are therefore not matched by any queries or systems. They won't show up in the tree view of the explorer, as it is query based.

The id of the first returned entity is not 1, but likely a much higher number like 500. The reason for this is that Flecs creates a bunch of builtin entities, and reserves some of the id space for components (more on that later).

## Deletion

The following examples show how to delete entities:

- C

  ecs_delete(world, my_entity);
  ecs_delete
  void ecs_delete(ecs_world_t *world, ecs_entity_t entity)
  Delete an entity.

- C++

  my_entity.destruct();
  flecs::entity::destruct
  void destruct() const
  Delete an entity.
  Definition entity.hpp:365

- C#

  myEntity.Destruct();

- Rust

  my_entity.destruct();

After an entity is deleted, it can no longer be used with most ECS operations. The deleted entity will be made available for reuse, so that the next time a new entity is created the deleted id can be recycled.

Whenever an id is recycled, Flecs increases a "version" counter in the upper 32 bits of the entity identifier. This can look strange, as it makes recycled entity ids large, often larger than 4 billion!. It is however 100% expected behavior, and happens as soon after the first entity is deleted.

The reason this happens is so that the Flecs API can tell whether an entity id is alive or not. Consider the following example, where "v" denotes the version part of the entity id:

- C

  ecs_entity_t e1 = ecs_new(world); // Returns 500v0
  ecs_delete(world, e1); // Recycle 500
  ecs_entity_t e2 = ecs_new(world); // Returns 500v1
  ecs_add(world, e1, Npc); // Fails, 500v0 is not alive
  ecs_add(world, e2, Npc); // OK, 500v1 is alive

- C++

  flecs::entity e1 = world.entity(); // Returns 500v0
  e1.destruct(); // Recycles 500
  flecs::entity e2 = world.entity(); // Returns 500v1
  e1.add<Npc>(); // Fails, 500v0 is not alive
  e2.add<Npc>(); // OK, 500v1 is alive
  flecs::entity_builder::add
  const Self & add() const
  Add a component to an entity.
  Definition builder.hpp:25

- C#

  Entity e1 = world.Entity(); // Returns 500v0
  e1.Destruct(); // Recycles 500
  Entity e2 = world.Entity(); // Returns 500v1
  e1.Add<Npc>(); // Fails, 500v0 is not alive
  e2.Add<Npc>(); // OK, 500v1 is alive

- Rust

  let e1 = world.entity(); // Returns 500v0
  e1.destruct(); // Recycles 500
  let e2 = world.entity(); // Returns 500v1
  // Fails, 500v0 is not alive
  e1.add::<Npc>();
  // OK, 500v1 is alive
  e2.add::<Npc>();

It is valid to delete an already deleted entity:

- C

  ecs_entity_t e1 = ecs_new(world);
  ecs_delete(world, e1);
  ecs_delete(world, e1); // OK: post condition is satisfied

- C++

  flecs::entity e1 = world.entity();
  e1.destruct();
  e1.destruct(); // OK: post condition is satisfied

- C#

  Entity e1 = world.Entity();
  e1.Destruct();
  e1.Destruct(); // OK: post condition is satisfied

- Rust

  let e1 = world.entity();
  e1.destruct();
  e1.destruct(); // OK: post condition is satisfied

## Clearing

An entity can be cleared, which means all components are removed without making the entity not alive. Clearing an entity is more efficient than removing components one by one. An example:

- C

  ecs_clear(world, my_entity);
  ecs_clear
  void ecs_clear(ecs_world_t *world, ecs_entity_t entity)
  Clear all components.

- C++

  my_entity.clear();
  flecs::entity::clear
  void clear() const
  Clear an entity.
  Definition entity.hpp:355

- C#

  myEntity.Clear();

- Rust

  my_entity.clear();

## Liveliness Checking

Applications can use the is_alive operation to test if an entity is alive or not. The entity passed to is_alive must be a valid entity, passing 0 will throw an error. An example:

- C

  ecs_entity_t e1 = ecs_new(world);
  ecs_entity_t e2 = ecs_new(world);
  ecs_delete(world, e1);
  ecs_is_alive(world, e1); // False
  ecs_is_alive(world, e2); // True
  ecs_is_alive
  bool ecs_is_alive(const ecs_world_t *world, ecs_entity_t e)
  Test whether an entity is alive.

- C++

  flecs::entity e1 = world.entity();
  flecs::entity e2 = world.entity();
  e1.destruct();
  e1.is_alive(); // False
  e2.is_alive(); // True
  flecs::entity_view::is_alive
  bool is_alive() const
  Check if entity is alive.
  Definition entity_view.hpp:76

- C#

  Entity e1 = world.Entity();
  Entity e2 = world.Entity();
  e1.Destruct();
  e1.IsAlive(); // False
  e2.IsAlive(); // True

- Rust

  let e1 = world.entity();
  let e2 = world.entity();
  e1.destruct();
  e1.is_alive(); // False
  e2.is_alive(); // True

The API also provides an is_valid operation. Whereas is_alive tests if an entity is alive, is_valid tests if the entity can be used with operations, and may be used with invalid (0) entity ids. An example:

- C

  ecs_entity_t e1 = ecs_new(world);
  ecs_entity_t e2 = ecs_new(world);
  ecs_delete(world, e1);
  ecs_is_valid(world, e1); // False
  ecs_is_valid(world, e2); // True
  ecs_is_valid(world, 0); // False
  ecs_is_valid
  bool ecs_is_valid(const ecs_world_t *world, ecs_entity_t e)
  Test whether an entity is valid.

- C++

  flecs::entity e1 = world.entity();
  flecs::entity e2 = world.entity();
  e1.destruct();
  e1.is_valid(); // False
  world.entity(0).is_valid(); // False
  flecs::entity_view::is_valid
  bool is_valid() const
  Check if entity is valid.
  Definition entity_view.hpp:63

- C#

  Entity e1 = world.Entity();
  Entity e2 = world.Entity();
  e1.Destruct();
  e1.IsValid(); // False
  e2.IsValid(); // True
  world.Entity(0).IsValid(); // False

- Rust

  let e1 = world.entity();
  let e2 = world.entity();
  e1.destruct();
  e1.is_valid(); // False
  world.entity_from_id(0).is_valid(); // False

## Manual Ids

Sometimes it can be useful to have direct control over which id an entity assumes. One example of this is to make sure that both sides of a networked application use the same entity id. Applications are allowed to do this, as long as the entity id is not yet in use, and it is made alive. The following example shows how to do this:

- C

  ecs_make_alive(world, 1000); // Make id 1000 alive
  ecs_make_alive
  void ecs_make_alive(ecs_world_t *world, ecs_entity_t entity)
  Ensure id is alive.

- C++

  flecs::entity e = world.make_alive(1000);

- C#

  Entity e = world.MakeAlive(1000);

- Rust

  let e = world.make_alive(1000);

The make_alive operation guarantees that the provided entity id will be alive after the operation finishes. The operation will fail if the provided entity id is already in use with a different version.

## Manual Versioning

Applications can manually override the version of an entity with the set_version operation. This can be useful when for example synchronizing networked ids. An example:

- C

  ecs_set_version(world, versioned_id);
  ecs_set_version
  void ecs_set_version(ecs_world_t *world, ecs_entity_t entity)
  Override the generation of an entity.

- C++

  world.set_version(versioned_id);

- C#

  world.SetVersion(versionedId);

- Rust

  //TODO does not exist yet
  //world.set_version(versioned_id);

## Ranges

An application can instruct Flecs to issue ids from a specific offset and up to a certain limit with the ecs_set_entity_range operation. This example ensures that id generation starts from id 5000:

- C

  ecs_set_entity_range(world, 5000, 0);
  ecs_set_entity_range
  void ecs_set_entity_range(ecs_world_t *world, ecs_entity_t id_start, ecs_entity_t id_end)
  Set a range for issuing new entity ids.

- C++

  world.set_entity_range(5000, 0);

- C#

  world.SetEntityRange(5000, 0);

- Rust

  world.set_entity_range(5000, 0);

If the last issued id was higher than 5000, the operation will not cause the last id to be reset to 5000. An application can also specify the highest id that can be generated:

- C

  ecs_set_entity_range(world, 5000, 10000);

- C++

  world.set_entity_range(5000, 10000);

- C#

  world.SetEntityRange(5000, 10000);

- Rust

  world.set_entity_range(5000, 10000);

If invoking ecs_new would result in an id higher than 10000, the application would assert. If 0 is provided for the maximum id, no upper bound will be enforced.

Note that at the moment setting the range does not affect recycled ids. It is therefore possible that ecs_new returns an id outside of the specified range if a recycle-able id is available. This is an issue that will be addressed in future versions.

It is possible for an application to enforce that entity operations are only allowed for the configured range with the ecs_enable_range_check operation:

- C

  ecs_enable_range_check(world, true);
  ecs_enable_range_check
  bool ecs_enable_range_check(ecs_world_t *world, bool enable)
  Enable/disable range limits.

- C++

  world.enable_range_check();

- C#

  world.EnableRangeCheck(true);

- Rust

  world.enable_range_check(true);

This can be useful for enforcing simple ownership behavior, where different id ranges are mapped out for different owners (often game clients or servers).

## Names

Entity can be given names, which allows them to be looked up on the world. An example:

- C

  ecs_entity_t e = ecs_entity(world, { .name = "MyEntity" });
  if (e == ecs_lookup(world, "MyEntity")) {
  // true
  }
  printf("%s\n", ecs_get_name(world, e));
  ecs_entity
  #define ecs_entity(world,...)
  Shorthand for creating an entity with ecs_entity_init().
  Definition flecs_c.h:235
  ecs_lookup
  ecs_entity_t ecs_lookup(const ecs_world_t *world, const char *path)
  Lookup an entity by it's path.
  ecs_get_name
  const char * ecs_get_name(const ecs_world_t *world, ecs_entity_t entity)
  Get the name of an entity.

- C++

  flecs::entity e = world.entity("MyEntity");
  if (e == world.lookup("MyEntity")) {
  // true
  }
  std::cout << e.name() << std::endl;
  flecs::entity_view::name
  flecs::string_view name() const
  Return the entity name.
  Definition entity_view.hpp:84

- C#

  Entity e = world.Entity("MyEntity");
  if (e == world.Lookup("MyEntity")) {
  // true
  }
  Console.WriteLine(e.Name());

- Rust

  let e = world.entity_named("MyEntity");
  if e == world.lookup("MyEntity") {
  // true
  }
  println!("{}", e.name());

Names are namespaced. They are similar to namespaced types in a programming language, or to files on a file system. If an entity is a child of a parent, a lookup will have to include the name of the parent:

- C

  ecs_entity_t p = ecs_entity(world, { .name = "Parent" });
  ecs_entity_t e = ecs_entity(world, { .name = "Child", .parent = p });
  if (e == ecs_lookup(world, "Parent.Child")) {
  // true
  }

- C++

  flecs::entity p = world.entity("Parent");
  flecs::entity e = world.entity("Child").child_of(p);
  if (e == world.lookup("Parent::Child")) {
  // true
  }

- C#

  Entity p = world.Entity("Parent");
  Entity e = world.Entity("Child").ChildOf(p);
  if (e == world.Lookup("Parent.Child")) {
  // true
  }

- Rust

  let p = world.entity_named("Parent");
  let e = world.entity_named("Child").child_of_id(p);
  if e == world.lookup("Parent::Child") {
  // true
  }

Lookups can be relative to an entity. The following example shows how to lookup an entity relative to a parent:

- C

  ecs_entity_t p = ecs_entity(world, { .name = "Parent" });
  ecs_entity_t e = ecs_entity(world, { .name = "Child", .parent = p });
  if (e == ecs_lookup_from(world, p, "Child")) {
  // true
  }

- C++

  flecs::entity p = world.entity("Parent");
  flecs::entity e = world.entity("Child").child_of(p);
  if (e == p.lookup("Child")) {
  // true
  }
  flecs::entity_view::lookup
  flecs::entity lookup(const char *path, bool search_path=false) const
  Lookup an entity by name.
  Definition impl.hpp:172

- C#

  Entity p = world.Entity("Parent");
  Entity e = world.Entity("Child").ChildOf(p);
  if (e == p.Lookup("Child")) {
  // true
  }

- Rust

  let p = world.entity_named("Parent");
  let e = world.entity_named("Child").child_of_id(p);
  if e == p.lookup("Child") {
  // true
  }

An application can request the name and path of an entity. The name is the direct name given to an entity, without the names of the parent. The path is the name and names of the entity's parent, separated by a separator. If an entity has no parents, the name and the path are the same. An example:

- C

  ecs_entity_t p = ecs_entity(world, { .name = "Parent" });
  ecs_entity_t e = ecs_entity(world, { .name = "Child", .parent = p });
  // Returns name, result does not need to be freed
  const char *name = ecs_get_name(world, e);
  printf("%s\n", name); // Child
  // Returns path, result must be freed
  char *path = ecs_get_path(world, e);
  printf("%s\n", path) // Parent.Child
  ecs_os_free(path);

- C++

  flecs::entity p = world.entity("Parent");
  flecs::entity e = world.entity("Child").child_of(p);
  // Returns entity name, does not allocate
  std::cout << e.name() << std::endl; // Child
  // Returns entity path, does allocate
  std::cout << e.path() << std::endl; // Parent.Child
  flecs::entity_view::path
  flecs::string path(const char *sep="::", const char *init_sep="::") const
  Return the entity path.
  Definition entity_view.hpp:100

- C#

  Entity p = world.Entity("Parent");
  Entity e = world.Entity("Child").ChildOf(p);
  // Returns entity name
  Console.WriteLine(e.Name()); // Child
  // Returns entity path
  Console.WriteLine(e.Path()); // Parent.Child

- Rust

  let p = world.entity_named("Parent");
  let e = world.entity_named("Child").child_of_id(p);
  // Returns entity name, does not allocate
  println!("{}", e.name()); // Child
  // Returns entity path, does allocate
  println!("{}", e.path().unwrap()); // Parent.Child

Names must be unique. There can only be one entity with a specific name in the scope of a parent. Entities can be annotated with a doc name, which does not need to be unique. See the doc addon for more details.

When the name for an existing entity is used during the creation of a named entity, the existing entity is returned. An example:

- C

  ecs_entity_t e1 = ecs_entity(world, { .name = "Parent.Child" });
  ecs_entity_t e2 = ecs_entity(world, { .name = "Parent.Child" });
  if (e1 == e2) {
  // true
  }

- C++

  flecs::entity e1 = world.entity("Parent::Child");
  flecs::entity e2 = world.entity("Parent::Child");
  if (e1 == e2) {
  // true
  }

- C#

  Entity e1 = world.Entity("Parent.Child");
  Entity e2 = world.Entity("Parent.Child");
  if (e1 == e2) {
  // true
  }

- Rust

  let e1 = world.entity_named("Parent::Child");
  let e2 = world.entity_named("Parent::Child");
  if e1 == e2 {
  // true
  }

Entity names can be changed after the entity is created, as long as the specified name is unique (e.g. there isn't a sibling entity with the same name). An example:

- C

  ecs_entity_t e = ecs_entity(world, { .name = "Foo" });
  // Change name
  ecs_set_name(world, e, "Bar");
  ecs_set_name
  ecs_entity_t ecs_set_name(ecs_world_t *world, ecs_entity_t entity, const char *name)
  Set the name of an entity.

- C++

  flecs::entity e = world.entity("Foo");
  // Change name
  e.set_name("Bar");

- C#

  Entity e = world.Entity("Foo");
  e.SetName("Bar");

- Rust

  let e = world.entity_named("Foo");
  // Change name
  e.set_name("Bar");

Entity names can be plain numbers:

- C

  ecs_entity_t ten = ecs_entity(world, { .name = "10" });
  ecs_entity_t twenty = ecs_entity(world, { .name = "20" });

- C++

  flecs::entity ten = world.entity("10");
  flecs::entity twenty = world.entity("20");

- C#

  Entity ten = world.Entity("10");
  Entity twenty = world.Entity("20");

- Rust

  let ten = world.entity_named("10");
  let twenty = world.entity_named("20");

Entity names can be used to refer directly to an entity id by prefixing them with a #. For example, looking up #1 will return the entity with id 1. This allows applications that work with names to treat anonymous entities the same as named entities.

## Disabling

Entities can be disabled which prevents them from being matched with queries. This can be used to temporarily turn off a feature in a scene during game play. It is also used for Flecs systems, which can be disabled to temporarily remove them from a schedule. The following example shows how to disable and reenable an entity:

- C

  ecs_entity_t e = ecs_new(world);
  // Enable entity
  ecs_enable(world, e, true);
  // Disable entity
  ecs_enable(world, e, false);
  ecs_enable
  void ecs_enable(ecs_world_t *world, ecs_entity_t entity, bool enabled)
  Enable or disable entity.

- C++

  flecs::entity e = world.entity();
  // Enable entity
  e.enable();
  // Disable entity
  e.disable();
  flecs::entity_builder::disable
  const Self & disable() const
  Disable an entity.
  Definition builder.hpp:566
  flecs::entity_builder::enable
  const Self & enable() const
  Enable an entity.
  Definition builder.hpp:557

- C#

  Entity e = world.Entity();
  // Enable entity
  e.Enable();
  // Disable entity
  e.Disable();

- Rust

  let e = world.entity();
  // Enable entity
  e.enable_self();
  // Disable entity
  e.disable_self();

Entity disabling can be combined with prefabs to create lists of entities that can be disabled with a single operation. The following example shows how to disable three entities with a single operation:

- C

  // Three entities to disable
  ecs_entity_t e1 = ecs_new(world);
  ecs_entity_t e2 = ecs_new(world);
  ecs_entity_t e3 = ecs_new(world);
  // Create prefab that has the three entities
  ecs_entity_t p = ecs_new_w_id(world, EcsPrefab);
  ecs_add_id(world, p, e1);
  ecs_add_id(world, p, e2);
  ecs_add_id(world, p, e3);
  // Disable entities
  ecs_enable(world, p, false);
  // Enable entities
  ecs_enable(world, p, true);
  ecs_add_id
  void ecs_add_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
  Add a (component) id to an entity.
  EcsPrefab
  const ecs_entity_t EcsPrefab
  Tag added to prefab entities.
  ecs_new_w_id
  ecs_entity_t ecs_new_w_id(ecs_world_t *world, ecs_id_t component)
  Create new entity with (component) id.

- C++

  // Three entities to disable
  flecs::entity e1 = world.entity();
  flecs::entity e2 = world.entity();
  flecs::entity e3 = world.entity();
  // Create prefab that has the three entities
  flecs::entity p = world.prefab();
  p.add(e1);
  p.add(e2);
  p.add(e3);
  // Disable entities
  p.disable();
  // Enable entities
  p.enable();

- C#

  // Three entities to disable
  Entity e1 = world.Entity();
  Entity e2 = world.Entity();
  Entity e3 = world.Entity();
  // Create prefab that has the three entities
  Entity p = world.Prefab();
  p.Add(e1);
  p.Add(e2);
  p.Add(e3);
  // Disable entities
  p.Disable();
  // Enable entities
  p.Enable();

- Rust

  // Three entities to disable
  let e1 = world.entity();
  let e2 = world.entity();
  let e3 = world.entity();
  // Create prefab that has the three entities
  let p = world.prefab();
  p.add_id(e1);
  p.add_id(e2);
  p.add_id(e3);
  // Disable entities
  p.disable_self();
  // Enable entities
  p.enable_self();

This also works with prefab hierarchies, as shown in the following example:

- C

  // Three entities to disable
  ecs_entity_t e1 = ecs_new(world);
  ecs_entity_t e2 = ecs_new(world);
  ecs_entity_t e3 = ecs_new(world);
  // Create prefab hierarchy with the three entities
  ecs_entity_t p1 = ecs_new_w_id(world, EcsPrefab);
  ecs_add_id(world, p1, e1);
  ecs_entity_t p2 = ecs_new_w_id(world, EcsPrefab);
  ecs_add_pair(world, p2, EcsIsA, p1);
  ecs_add_id(world, p2, e2);
  ecs_add_id(world, p2, e3);
  // Disable e1, e2, e3
  ecs_enable(world, p2, false);
  // Enable e1
  ecs_enable(world, p1, true);
  EcsIsA
  const ecs_entity_t EcsIsA
  Used to express inheritance relationships.

- C++

  // Three entities to disable
  flecs::entity e1 = world.entity();
  flecs::entity e2 = world.entity();
  flecs::entity e3 = world.entity();
  // Create prefab hierarchy with the three entities
  flecs::entity p1 = world.prefab()
  .add(e1);
  flecs::entity p2 = world.prefab()
  .is_a(p1)
  .add(e2)
  .add(e3);
  // Disable e1, e2, e3
  p2.disable();
  // Enable e1
  p1.enable();
  flecs::entity_builder::is_a
  const Self & is_a(entity_t second) const
  Shortcut for add(IsA, entity).
  Definition builder.hpp:213

- C#

  // Three entities to disable
  Entity e1 = world.Entity();
  Entity e2 = world.Entity();
  Entity e3 = world.Entity();
  // Create prefab hierarchy with the three entities
  Entity p1 = world.Prefab()
  .Add(e1);
  Entity p2 = world.Prefab()
  .IsA(p1)
  .Add(e2)
  .Add(e3);
  // Disable e1, e2, e3
  p2.Disable();
  // Enable e1
  p1.Enable();

- Rust

  // Three entities to disable
  let e1 = world.entity();
  let e2 = world.entity();
  let e3 = world.entity();
  // Create prefab hierarchy with the three entities
  let p1 = world.prefab().add_id(e1);
  let p2 = world.prefab().is_a_id(p1).add_id(e2).add_id(e3);
  // Disable e1, e2, e3
  p2.disable_self();
  // Enable e1
  p1.enable_self();

Entity disabling works by adding a Disabled tag to the entity, which can also be added manually with regular add/remove operations. An example:

- C

  ecs_add_id(world, e, EcsDisabled);
  EcsDisabled
  const ecs_entity_t EcsDisabled
  When this tag is added to an entity it is skipped by queries, unless EcsDisabled is explicitly querie...

- C++

  e.add(flecs::Disabled);

- C#

  e.Add(Ecs.Disabled);

- Rust

  e.add::<flecs::Disabled>();

# Components

A component is something that is added to an entity. Components can simply tag an entity ("this entity is an `Npc`"), attach data to an entity ("this entity is at `Position` `{10, 20}`") and create relationships between entities ("bob `Likes` alice") that may also contain data ("bob `Eats` `{10}` apples").

To disambiguate between the different kinds of components in Flecs, they are named separately in Flecs:

Name | Has Data | Is Pair
--- | --- | ---
Tag | No | No
Component | Yes | No
Relationship | No | Yes
Relationship component | Yes | Yes

Here, "has data" indicates whether a component attaches data to the entity. This means that in addition to asking whether an entity has a component, we can also ask what the value of a component is.

A pair is a component that's composed out of two elements, such as "Likes, alice" or "Eats, apples". See the Relationship manual for more details.

## Operations

The following table provides the base set of operations that Flecs offers for components:

Operation | Description
--- | ---
add | Adds component to entity. If entity already has the component, add does nothing. Requires that the component is default constructible.
remove | Removes component from entity. If entity doesn't have the component, remove does nothing.
get | Returns a immutable reference to the component. If the entity doesn't have the component, get returns nullptr.
get_mut | Returns a mutable reference to the component. If the entity doesn't have the component, get_mut returns nullptr.
ensure | Returns a mutable reference to the component. ensure behaves as a combination of add and get_mut.
emplace | Returns a mutable reference to the component. If the entity doesn't have the component, emplace returns a reference to unconstructed memory. This enables adding components that are not default constructible.
modified | Emits a modified event for a component. This ensures that OnSet observers and on_set hooks are invoked, and updates change detection administration.
set | Sets the value of a component. set behaves as a combination of ensure and modified. set does not take ownership of the provided value.
assign | Sets the value of an existing component. assign behaves as a combination of get_mut and modified. set does not take ownership of the provided value.

The following component lifecycle diagram shows how the different operations mutate the storage and cause hooks and observers to be invoked:

Component Lifecycle

## Hooks

Hooks are callbacks that are invoked for various lifecycle stages of a component. Hooks come in two kinds: type hooks and component hooks. Type hooks apply to all instances of a type (for example: a constructor). Component hooks only apply when that type is used as a component (for example: it is added to an entity).

Type hooks are usually used for resource management, whereas component hooks are used for application behavior. Using type hooks for application behavior or component hooks for resource management is bad practice, and will likely lead to memory leaks, crashes or other bugs.

Hooks example code:

- https://github.com/SanderMertens/flecs/blob/master/examples/c/entities/hooks/src/main.c
- https://github.com/SanderMertens/flecs/blob/master/examples/cpp/entities/hooks/src/main.cpp

A type can only have a single hook of each kind. This differentiates them from observers, of which there can be many instances for the same component. Hooks also have guaranteed execution order (before or after observers, depending on the kind of hook) which allows them to be used to validate or patch up component values before they're visible to observers.

Another difference is that hooks apply to all instances of a component, even if that component is used as part of a pair. For example, the constructor for Eats will be invoked if (Eats, Apples) is added to an entity.

Hooks can only be specified for that are not zero-sized. If hooks need to be specified on a tag, the easiest workaround is to turn the tag into a component with a dummy member.

The following table lists all type hooks:

Name | Signature | Description
--- | --- | ---
ctor | (T *ptr, const ecs_type_info_t *ti) | Invoked when a new instance is created (default constructor in C++).
move | (T *dst, T* src, const ecs_type_info_t *ti) | Invoked when an instance is moved to constructed memory (move assign in C++).
move_ctor | (T *dst, T* src, const ecs_type_info_t *ti) | Invoked when an instance is moved to unconstructed memory (move ctor in C++).
copy | (T *dst, const T* src, const ecs_type_info_t *ti) | Invoked when an instance is copied to constructed memory (copy assign in C++).
copy_ctor | (T *dst, const T* src, const ecs_type_info_t *ti) | Invoked when an instance is coped to unconstructed memory. (copy ctor in C++).
dtor | (T *ptr, const ecs_type_info_t *ti) | Invoked when an instance is deleted (destructor in C++).
cmp | int (const T* a, const T* b, const ecs_type_info_t *ti) | Invoked when two values are compared. Returns -1, 0, 1 for smaller, equal or larger
equals | bool (const T* a, const T* b, const ecs_type_info_t *ti) | Invoked to test if two values are equal.

When move_ctor and copy_ctor are not explicitly set, they are synthesized from move, copy and ctor hooks. Two additional hooks exist that are usually not set by the application as they are synthesized from other hooks:

Name | Signature | Description
--- | --- | ---
move_dtor | (T *dst, T* src, const ecs_type_info_t *ti) | Destructive move to constructed memory location.
ctor_move_dtor | (T *dst, T* src, const ecs_type_info_t *ti) | Destructive move to an unconstructed memory location.

Hook implementations must follow the rule of 5.

When type hooks are configured and a hook is left to NULL, it is assumed that the type has no behavior for that hook. In some cases though, an application may want to express that the component has reached an invalid lifecycle state, for example when a move hook is invoked for a type that is not movable. To express this an application can set the .flags member of the ecs_type_hooks_t struct (passed to ecs_set_hooks) to one of these flags:

- ECS_TYPE_HOOK_CTOR_ILLEGAL
- ECS_TYPE_HOOK_DTOR_ILLEGAL
- ECS_TYPE_HOOK_COPY_ILLEGAL
- ECS_TYPE_HOOK_MOVE_ILLEGAL
- ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL
- ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL
- ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL
- ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL
- ECS_TYPE_HOOK_CMP_ILLEGAL
- ECS_TYPE_HOOK_EQUALS_ILLEGAL

In the C++ API the hooks and flags are set automatically when registering a component type.

The following table lists all component hooks:

Name | Description
--- | ---
on_add | Invoked when a component is added to an entity.
on_replace | Invoked with the previous value when a component is set.
on_set | Invoked when a component is set.
on_remove | Invoked when a component is removed.

The signature for component hooks is the same as for systems:

- C

  void on_set_position(ecs_iter_t *it) {
  Position *p = ecs_field(it, Position, 0);
  for (int i = 0; i < it->count; i ++) {
  ecs_entity_t e = it->entities[i];
  printf("{%f, %f}\n", p[i].x, p[i].y);
  }
  }
  ECS_COMPONENT(world, Position);
  ecs_set_hooks(world, Position, {
  .on_set = on_set_position
  });
  ECS_COMPONENT
  #define ECS_COMPONENT(world, id)
  Declare & define a component.
  Definition flecs_c.h:145
  ecs_iter_t
  Iterator.
  Definition flecs.h:1142
  ecs_iter_t::count
  int32_t count
  Number of entities to iterate.
  Definition flecs.h:1149
  ecs_iter_t::entities
  const ecs_entity_t * entities
  Entity identifiers.
  Definition flecs.h:1150

- C++

  world.component<Position>()
  .on_set([](Position& p) {
  std::cout << "{" << p.x << ", " << p.y << "}" << std::endl;
  });

- C#

  file struct Position(float x, float y) :
  IOnSetHook<Position>,
  {
  public IntPtr Value = Marshal.StringToHGlobalAnsi(str);
  // The on set hook gets called when the component is set.
  public static void OnSet(Iter it, int i, ref Position p)
  {
  Console.WriteLine($"{p.x}, {p.y}");
  }
  }

- Rust

  world
  .component::<Position>()
  .on_set(|entity, pos| {
  println!("{:?}", pos);
  });

For the on_replace hook, the previous value is provided as the first field, and the new value as the second field. An example:

- C

  void on_replace_position(ecs_iter_t *it) {
  Position *prev = ecs_field(it, Position, 0);
  Position *next = ecs_field(it, Position, 1);
  for (int i = 0; i < it->count; i ++) {
  printf("prev = {%f, %f}\n", prev[i].x, prev[i].y);
  printf("next = {%f, %f}\n", next[i].x, next[i].y);
  }
  }
  ECS_COMPONENT(world, Position);
  ecs_set_hooks(world, Position, {
  .on_replace = on_replace_position
  });

- C++

  world.component<Position>()
  .on_replace([](Position& prev, Position& next) {
  std::cout << "prev = {" << prev.x << ", " << prev.y << "}" << std::endl;
  std::cout << "next = {" << next.x << ", " << next.y << "}" << std::endl;
  });

- C#

  // TODO

- Rust

  world
  .component::<Position>()
  .on_replace(|entity, prev, next| {
  println!("prev = {:?}", prev);
  println!("next = {:?}", next);
  });

## Components have entity handles

In an ECS framework, components need to be uniquely identified. In Flecs this is done by making each component is its own unique entity. If an application has a component Position and Velocity, there will be two entities, one for each component. Component entities can be distinguished from "regular" entities as they have a Component component. An example:

- C

  // Register component (see below)
  ECS_COMPONENT(world, Position);
  // The ecs_id() macro can be used in C to obtain the component id from a type
  ecs_entity_t pos = ecs_id(Position);
  // Component entities have the Component component
  const EcsComponent *comp_data = ecs_get(world, pos, EcsComponent);
  printf("{size: %d, alignment: %d}\n",
  comp_data->size,
  comp_data->alignment);
  ecs_id
  FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
  Component id for EcsDocDescription.
  EcsComponent
  Component information.
  Definition flecs.h:1537
  EcsComponent::size
  ecs_size_t size
  Component size.
  Definition flecs.h:1538
  EcsComponent::alignment
  ecs_size_t alignment
  Component alignment.
  Definition flecs.h:1539

- C++

  // Get the entity for the Position component
  flecs::entity pos = world.component<Position>();
  // Component entities have the Component component
  const flecs::Component& comp_data = pos.get<flecs::Component>();
  std::cout << "{size: " << comp_data.size << ", "
  << comp_data.alignment << "}\n";
  flecs::entity_view::get
  const T & get() const
  Get component value.
  Definition entity_view.hpp:396

- C#

  // Get the entity for the Position component
  Entity pos = world.Component<Position>();
  // Component entities have the Component component
  ref readonly flecs.EcsComponent compData = ref e.Get<flecs.EcsComponent>();
  Console.WriteLine($"Size: {compData.size}, Alignment: {compData.alignment}");

- Rust

  // Get the entity for the Position component
  let pos = world.component::<Position>();
  // Component entities have the Component component
  pos.get::<&flecs::Component>(|comp_data| {
  println!(
  "size: {}, alignment: {}",
  comp_data.size, comp_data.alignment
  );
  });

All of the APIs that apply to regular entities also apply to component entities. Many Flecs features leverage this. It is for example possible to customize component behavior by adding tags to components. The following example shows how a component can be customized to use sparse storage by adding a Sparse tag to the component entity:

- C

  // Register a sparse component
  ECS_COMPONENT(world, Position);
  ecs_add_id(world, ecs_id(Position), EcsSparse);
  EcsSparse
  const ecs_entity_t EcsSparse
  Mark component as sparse.

- C++

  // Register a sparse component
  world.component<Position>().add(flecs::Sparse);

- C#

  // Register a sparse component
  world.Component<Position>().Entity.add(Ecs.Sparse);

- Rust

  // Register a sparse component
  world.component::<Position>().add_trait::<flecs::Sparse>();

These kinds of tags are called "traits". To see which kinds of traits you can add to components to customize their behavior, see the component traits manual.

## Registration

Components must be registered before they can be used. The following sections describe how component registration works for the different language bindings.

- C

  In C, the easiest way to register a component is with the ECS_COMPONENT macro:

  ECS_COMPONENT(world, Position);
  ecs_entity_t e = ecs_new_w(world, Position); // OK

  However, if you try to use the component from another function or across files, you will find that this doesn't work. To fix this, the component has to be forward declared. The following example shows how to forward declare a component that is used from multiple C files:

  // position.h
  extern ECS_COMPONENT_DECLARE(Position);
  ECS_COMPONENT_DECLARE
  #define ECS_COMPONENT_DECLARE(id)
  Forward declare a component.
  Definition flecs_c.h:112
  // position.c
  #include "position.h"
  ECS_COMPONENT_DECLARE(Position);
  void register_components(ecs_world_t *world) {
  ECS_COMPONENT_DEFINE(world, Position);
  }
  ecs_world_t
  struct ecs_world_t ecs_world_t
  A world is the container for all ECS data and supporting features.
  Definition flecs.h:405
  ECS_COMPONENT_DEFINE
  #define ECS_COMPONENT_DEFINE(world, id_)
  Define a forward declared component.
  Definition flecs_c.h:122
  // something.c
  #include "position.h"
  void do_something(ecs_world_t *world) {
  ecs_entity_t e = ecs_new_w(world, Position); // OK
  }
  int main(int argc, char *argv[]) {
  ecs_world_t *world = ecs_init();
  register_components(world);
  do_something(world);
  ecs_fini(world);
  }
  ecs_fini
  int ecs_fini(ecs_world_t *world)
  Delete a world.
  ecs_init
  ecs_world_t * ecs_init(void)
  Create a new world.

  Note that this is just an example, and that typically you would not create a file per component. A more common way to organize components is with modules, which often register multiple components, amongst others. The following code shows an example with a module setup:

  // movement.h
  extern ECS_COMPONENT_DECLARE(Position);
  extern ECS_COMPONENT_DECLARE(Velocity);
  void MovementImport(ecs_world_t *world);
  // movement.c
  #include "movement.h"
  ECS_COMPONENT_DECLARE(Position);
  ECS_COMPONENT_DECLARE(Velocity);
  void MovementImport(ecs_world_t *world) {
  ECS_MODULE(world, Movement);
  ECS_COMPONENT_DEFINE(world, Position);
  ECS_COMPONENT_DEFINE(world, Velocity);
  }
  ECS_MODULE
  #define ECS_MODULE(world, id)
  Create a module.
  Definition module.h:107
  // something.c
  #include "movement.h"
  void do_something(ecs_world_t *world) {
  ecs_new_w(world, Position); // OK
  }
  int main(int argc, char *argv[]) {
  ecs_world_t *world = ecs_init();
  ECS_IMPORT(world, Movement);
  do_something(world);
  ecs_fini(world);
  }
  ECS_IMPORT
  #define ECS_IMPORT(world, id)
  Wrapper around ecs_import().
  Definition module.h:119

- C++

  In C++ components are automatically registered upon first usage. The following example shows how:

  flecs::world world;
  flecs::entity e1 = world.entity()
  .set(Position{10, 20}) // Position registered here
  .set(Velocity{1, 2}); // Velocity registered here
  flecs::entity e2 = world.entity()
  .set(Position{10, 20}) // Position already registered
  .set(Velocity{1, 2}); // Velocity already registered
  flecs::world::entity
  flecs::entity entity(Args &&... args) const
  Create an entity.
  Definition impl.hpp:190
  flecs::entity_builder::set
  const Self & set(T &&value) const
  Set a component for an entity.
  Definition builder.hpp:705
  flecs::world
  The world.
  Definition world.hpp:158

  Components can be registered in advance, which can be done for several reasons:

  - Makes it easier to see which components are used by an application
  - No unexpected registration code that suddenly runs in the middle of a frame
  - Component needs to be setup with traits, reflection data, hooks etc.

  To register a component in advance, do:

  world.component<Position>();
  flecs::world::component
  flecs::component< T > component(Args &&... args) const
  Find or register component.
  Definition impl.hpp:11

  In general it is recommended to register components in advance, and to only use automatic registration during prototyping. Applications can enforce manual registration by defining the FLECS_CPP_NO_AUTO_REGISTRATION macro at compile time, when building Flecs. This will cause a panic whenever a component is used that was not yet registered. Disabling auto registration also improves performance of the C++ API.

  A convenient way to organize component registration code is to use Flecs modules. An example:

  struct movement {
  movement(flecs::world& world) {
  world.component<Position>();
  world.component<Velocity>();
  }
  };
  flecs::world world;
  world.import<movement>();
  flecs::world::import
  flecs::entity import()
  Import a module.
  Definition impl.hpp:115

- C#

  In C# components are automatically registered upon first usage. The following example shows how:

  public static void Main()
  {
  using World world = World.Create();
  Entity e1 = world.Entity()
  .Set(new Position(10, 20)) // Position registered here
  .Set(new Velocity(1, 2)); // Velocity registered here
  Entity e2 = world.Entity()
  .Set(new Position(10, 20)) // Position already registered
  .Set(new Velocity(1, 2)); // Velocity already registered
  }

  Components can be registered in advance, which can be done for several reasons:

  - Makes it easier to see which components are used by an application
  - No unexpected registration code that suddenly runs in the middle of a frame
  - Component needs to be setup with traits, reflection data, hooks etc.

  To register a component in advance, do:

  world.Component<Position>();

  In general it is recommended to register components in advance, and to only use automatic registration during prototyping.

  A convenient way to organize component registration code is to use Flecs modules. An example:

  public struct Movement : IFlecsModule
  {
  public void InitModule(World world)
  {
  world.Component<Position>();
  world.Component<Velocity>();
  }
  }
  public static void Main()
  {
  using World world = World.Create();
  world.Import<Movement>();
  }

- Rust

  In Rust components are automatically registered upon first usage. The following example shows how:

  fn main() {
  let world = World::new();
  let e1 = world
  .entity()
  .set(Position { x: 10.0, y: 20.0 }) // Position registered here
  .set(Velocity { x: 1.0, y: 2.0 }); // Velocity registered here
  let e2 = world
  .entity()
  .set(Position { x: 10.0, y: 20.0 }) // Position already registered
  .set(Velocity { x: 1.0, y: 2.0 }); // Velocity already registered
  }

  Components can be registered in advance, which can be done for several reasons:

  - Makes it easier to see which components are used by an application
  - No unexpected registration code that suddenly runs in the middle of a frame
  - Component needs to be setup with traits, reflection data, hooks etc.

  To register a component in advance, do:

  world.component::<Position>();

  In general it is recommended to register components in advance, and to only use automatic registration during prototyping. Applications can enforce manual registration by activating the rust feature flecs_manual_registration. This will cause a panic whenever a component is used that was not yet registered. Disabling auto registration also improves performance of the Rust API.

  A convenient way to organize component registration code is to use Flecs modules. An example:

  use flecs_ecs::prelude::*;
  #[derive(Component)]
  struct Movement;
  impl Module for Movement {
  fn module(world: &World) {
  world.module::<Movement>("Movement");
  // Define components, systems, triggers, ... as usual. They will be
  // automatically created inside the scope of the module.
  }
  }
  let world = World::new();
  world.import::<Movement>();

### Runtime Type Registration

In some cases, typically when using scripting, components must be registered for types that do not exist at compile time. In Flecs this is possible by calling the ecs_component_init function. This function returns a component entity, which can then be used with regular ECS operations. An example:

- C

  // Register component
  ecs_entity_t comp = ecs_component(world, {
  .type = {
  .size = 8,
  .alignment = 8
  }
  });
  ecs_entity_t e = ecs_new(world);
  // Add component
  ecs_add_id(world, e, comp);
  // Get component
  const void *ptr = ecs_get_id(world, e, comp);
  ecs_component
  #define ecs_component(world,...)
  Shorthand for creating a component with ecs_component_init().
  Definition flecs_c.h:249
  ecs_get_id
  const void * ecs_get_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
  Get an immutable pointer to a component.

- C++

  ecs_component_desc_t desc = {0};
  desc.type.size = 8;
  desc.type.alignment = 8;
  flecs::entity_t comp = ecs_component_init(world, &desc);
  flecs::entity e = world.entity();
  // Add component
  e.add(comp);
  // Get component
  const void *ptr = e.get(comp);
  ecs_component_init
  ecs_entity_t ecs_component_init(ecs_world_t *world, const ecs_component_desc_t *desc)
  Find or create a component.
  ecs_component_desc_t
  Used with ecs_component_init().
  Definition flecs.h:1094
  ecs_component_desc_t::type
  ecs_type_info_t type
  Parameters for type (size, hooks, ...).
  Definition flecs.h:1101
  ecs_type_info_t::alignment
  ecs_size_t alignment
  Alignment of type.
  Definition flecs.h:997
  ecs_type_info_t::size
  ecs_size_t size
  Size of type.
  Definition flecs.h:996

- C#

  TODO

- Rust

  TODO

Often when registering a component at runtime, it needs to be described with reflection data so it can be serialized & deserialized. See the "reflection/runtime_component" example on how to do this.

When registering a component, it is good practice to give it a name. This makes it much easier to debug the application with tools like the explorer. To create a component with a name, we can pass a named entity to the ecs_component_init function. An example:

- C

  // Register named component
  ecs_entity_t comp = ecs_component(world, {
  .entity = ecs_entity(world, { .name = "MyComponent" }),
  .type = {
  .size = 8,
  .alignment = 8
  }
  });
  ecs_entity_t e = ecs_new(world);
  // Add component
  ecs_add_id(world, e, comp);
  // Get component
  const void *ptr = ecs_get_id(world, e, comp);

- C++

  ecs_component_desc_t desc = {0};
  desc.entity = world.entity("MyComponent");
  desc.type.size = 8;
  desc.type.alignment = 8;
  flecs::entity_t comp = ecs_component_init(world, &desc);
  flecs::entity e = world.entity();
  // Add component
  e.add(comp);
  // Get component
  const void *ptr = e.get(comp);
  ecs_component_desc_t::entity
  ecs_entity_t entity
  Existing entity to associate with observer (optional).
  Definition flecs.h:1098

- C#

  TODO

- Rust

  TODO

See the documentation for ecs_component_desc_t for more component registration options.

## Unregistration

A component can be unregistered from a world by deleting its entity. When a component is deleted, by default it will be removed from all entities that have the component. This behavior is customizable, see the "cleanup traits" section in the component trait manual.

The following example shows how to unregister a component:

- C

  ECS_COMPONENT(world, Position);
  // Create entity with Position
  ecs_entity_t e = ecs_new_w(world, Position);
  // Unregister the component
  ecs_delete(world, ecs_id(Position));
  // Position is removed from e

- C++

  flecs::entity pos = world.component<Position>();
  // Create entity with Position
  flecs::entity e = world.entity().add<Position>();
  // Unregister the component
  pos.destruct();
  // Position is removed from e

- C#

  Entity pos = world.Component<Position>();
  // Create entity with Position
  Entity e = world.Entity().Add<Position>();
  // Unregister the component
  pos.Destruct();
  // Position is removed from e

- Rust

  let pos = world.component::<Position>();
  // Create entity with Position
  let e = world.entity().add::<Position>();
  // Unregister the component
  pos.destruct();
  // Position is removed from e

## Singletons

Singletons are components for which only a single instance exists on the world. They can be accessed on the world directly and do not require providing an entity. Singletons are useful for global game resources, such as game state, a handle to a physics engine or a network socket. An example:

- C

  ECS_COMPONENT(world, TimeOfDay);
  // Set singleton
  ecs_singleton_set(world, TimeOfDay, { 0.5 });
  // Unregister the component
  const TimeOfDay *t = ecs_singleton_get(world, TimeOfDay);

- C++

  // Set singleton
  world.set<TimeOfDay>({ 0.5 });
  // Get singleton
  const TimeOfDay& t = world.get<TimeOfDay>();
  flecs::world::set
  void set(const T &value) const
  Set singleton component.
  Definition world.hpp:689
  flecs::world::get
  const void * get(flecs::id_t id) const
  Get singleton component.
  Definition world.hpp:158

- C#

  // Set singleton
  world.Set(new TimeOfDay(0.5));
  // Get singleton
  ref readonly TimeOfDay t = ref world.Get<TimeOfDay>();

- Rust

  // Set singleton
  world.set(TimeOfDay { value: 0.5 });
  // Get singleton
  world.get::<&TimeOfDay>(|time| println!("{}", time.value));

Singletons are implemented as components that are added to themselves. The rationale for this design is that it allows for reusing all of the existing logic implemented for entities and components, as for the storage there is no fundamental difference between a singleton and a regular component. Additionally, it spreads out the storage of singletons across multiple entities which is favorable for performance when compared to a single entity that contains all singleton components. Since the component's entity is known during the singleton lookup, it makes most sense to use this as the entity on which to store the data.

The following example shows how the singleton APIs are equivalent to using the regular APIs with the component entity:

- C

  // Set singleton
  ecs_singleton_set(world, TimeOfDay, { 0.5 });
  // Equivalent to:
  ecs_set(world, ecs_id(TimeOfDay), TimeOfDay, {0.5});

- C++

  // Set singleton
  world.set<TimeOfDay>({ 0.5 });
  // Equivalent to:
  world.component<TimeOfDay>().set(TimeOfDay{ 0.5 });

- C#

  // Set singleton
  world.Set(new TimeOfDay(0.5));
  // Equivalent to:
  world.Component<TimeOfDay>().Entity.Set(new TimeOfDay(0.5));

- Rust

  // Set singleton
  world.set(TimeOfDay { value: 0.5 });
  // Equivalent to:
  world.component::<TimeOfDay>().set(TimeOfDay { value: 0.5 });

## Disabling

Components can be disabled, which prevents them from being matched by queries. When a component is disabled, it behaves as if the entity doesn't have it. Only components that have the CanToggle trait can be disabled (see the component traits manual for more details). The following example shows how to disable a component:

- C

  // Register toggle-able component
  ECS_COMPONENT(world, Position);
  ecs_add_id(world, ecs_id(Position), EcsCanToggle);
  ecs_entity_t e = ecs_insert(world, ecs_value(Position, {10, 20}));
  // Disable component
  ecs_enable_component(world, e, Position, false);
  ecs_is_enabled(world, e, Position); // False
  // Enable component
  ecs_enable_component(world, e, Position, true);
  ecs_is_enabled(world, e, Position); // True
  EcsCanToggle
  const ecs_entity_t EcsCanToggle
  Mark a component as toggleable with ecs_enable_id().
  ecs_value
  #define ecs_value(T,...)
  Convenience macro for creating compound literal value literal.
  Definition flecs_c.h:714

- C++

  // Register toggle-able component
  world.component<Position>().add(flecs::CanToggle);
  flecs::entity e = world.entity().set(Position{10, 20});
  // Disable component
  e.disable<Position>();
  e.enabled<Position>(); // False
  // Enable component
  e.enable<Position>();
  e.enabled<Position>(); // True

- C#

  ecs.Component<Position>().Entity
  .Add(Ecs.CanToggle);
  Entity e = world.Entity()
  .Set<Position>(new(10, 20));
  // Disable component
  e.Disable<Position>();
  e.IsEnabled<Position>(); // False
  // Enable component
  e.Enable<Position>();
  e.IsEnabled<Position>(); // True

- Rust

  // Register toggle-able component
  world
  .component::<Position>()
  .add_trait::<flecs::CanToggle>();
  let e = world.entity().set(Position { x: 10.0, y: 20.0 });
  // Disable component
  e.disable::<Position>();
  e.enabled::<Position>(); // False
  // Enable component
  e.enable::<Position>();
  e.enabled::<Position>(); // True

Disabling a component is a cheaper alternative to removing it from an entity, as it relies on setting a bit vs. moving an entity to another table. Component toggling can also be used to restore a component with its old value.