Flecs: Flecs Quickstart
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
Flecs Quickstart

This document provides a quick overview of the different features and concepts in Flecs with short examples. This is a good resource if you're just getting started or just want to get a better idea of what kind of features are available in Flecs!

# Building Flecs

See the Building Flecs manual.

# Concepts

This section contains an overview of all the different concepts in Flecs and how they wire together. The sections in the quickstart go over them in more detail and with code examples.

Flecs Overview

## World

The world is the container for all ECS data. It stores the entities and their components, does queries and runs systems. Typically there is only a single world, but there is no limit on the number of worlds an application can create.

- C

  ecs_world_t *world = ecs_init();
  // Do the ECS stuff
  ecs_fini(world);
  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:429
  ecs_fini
  int ecs_fini(ecs_world_t *world)
  Delete a world.
  ecs_init
  ecs_world_t * ecs_init(void)
  Create a new world.

- C++

  flecs::world world;
  // Do the ECS stuff
  flecs::world
  The world.
  Definition world.hpp:246

- C#

  using World world = World.Create();
  // Do the ECS stuff

- Rust

  let world = World::new();
  // Do the ECS stuff

- Clojure

  ;; The dependency for this binding is at https://clojars.org/io.github.pfeodrippe/vybe-flecs,
  ;; code at https://github.com/pfeodrippe/vybe, see also https://vybegame.dev/vybe-flecs
  ;; Require a higher-level binding and a lower-level one.
  (require '[vybe.flecs :as vf])
  (require '[vybe.flecs.c :as vf.c])
  (import '(org.vybe.flecs flecs))
  (def w (vf/make-world))
  ;; Do the ECS stuff

## Entity

An entity is a unique thing in the world, and is represented by a 64 bit id. Entities can be created and deleted. If an entity is deleted it is no longer considered "alive". A world can contain up to 4 billion(!) alive entities. Entity identifiers contain a few bits that make it possible to check whether an entity is alive or not.

- C

  ecs_entity_t e = ecs_new(world);
  ecs_is_alive(world, e); // true!
  ecs_delete(world, e);
  ecs_is_alive(world, e); // false!
  ecs_entity_t
  ecs_id_t ecs_entity_t
  An entity identifier.
  Definition flecs.h:385
  ecs_new
  ecs_entity_t ecs_new(ecs_world_t *world)
  Create new entity ID.
  ecs_delete
  void ecs_delete(ecs_world_t *world, ecs_entity_t entity)
  Delete an entity.
  ecs_is_alive
  bool ecs_is_alive(const ecs_world_t *world, ecs_entity_t e)
  Test whether an entity is alive.

- C++

  auto e = world.entity();
  e.is_alive(); // true!
  e.destruct();
  e.is_alive(); // false!
  flecs::world::entity
  flecs::entity entity(Args &&... args) const
  Create an entity.
  Definition impl.hpp:190
  flecs::entity_view::is_alive
  bool is_alive() const
  Check if entity is alive.
  Definition entity_view.hpp:80

- C#

  Entity e = world.Entity();
  e.IsAlive(); // true!
  e.Destruct();
  e.IsAlive(); // false!

- Rust

  let e = world.entity();
  e.is_alive(); // true!
  e.destruct();
  e.is_alive(); // false!

- Clojure

  (merge w {:e []})
  (vf/alive? (:e w))
  ;; => #{}
  (dissoc w :e)
  (:e w)
  ;; => nil

Entities can have names which makes it easier to identify them in an application. In C++ the name can be passed to the constructor. If a name is provided during entity creation time and an entity with that name already exists, the existing entity will be returned.

- C

  In C a name can be assigned with the ecs_entity_init function or ecs_entity macro.

  ecs_entity_t e = ecs_entity(world, { .name = "Bob" });
  printf("Entity name: %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_get_name
  const char * ecs_get_name(const ecs_world_t *world, ecs_entity_t entity)
  Get the name of an entity.

- C++

  auto e = world.entity("Bob");
  std::cout << "Entity name: " << e.name() << std::endl;
  flecs::entity_view::name
  flecs::string_view name() const
  Return the entity name.
  Definition entity_view.hpp:88

- C#

  Entity e = world.Entity("Bob");
  Console.WriteLine($"Entity name: {e.Name()}");

- Rust

  let e = world.entity_named("bob");
  println!("Entity name: {}", e.name());

- Clojure

  (merge w {:bob []})
  (vf/get-name (:bob w))
  ;; => "bob"

Entities can be looked up by name with the lookup function:

- C

  ecs_entity_t e = ecs_lookup(world, "Bob");
  ecs_lookup
  ecs_entity_t ecs_lookup(const ecs_world_t *world, const char *path)
  Look up an entity by its path.

- C++

  auto e = world.lookup("Bob");
  flecs::world::lookup
  flecs::entity lookup(const char *name, const char *sep="::", const char *root_sep="::", bool recursive=true) const
  Lookup entity by name.
  Definition world.hpp:102

- C#

  Entity e = world.Lookup("Bob");

- Rust

  let e = world.lookup("bob");

- Clojure

  (def e (w :bob))

## Id

An id is a 64 bit number that can encode anything that can be added to an entity. In flecs this can be either a component, tag or a pair. A component is data that can be added to an entity. A tag is an "empty" component. A pair is a combination of two component/tag ids which is used to encode entity relationships. All entity/component/tag identifiers are valid ids, but not all ids are valid entity identifier.

The following sections describe components, tags and pairs in more detail.

## Component

A component is a type of which instances can be added and removed to entities. Each component can be added only once to an entity (though not really, see PairPair). In C applications components must be registered before use. By default in C++ this happens automatically.

- C

  ECS_COMPONENT(world, Position);
  ECS_COMPONENT(world, Velocity);
  ecs_entity_t e = ecs_new(world);
  // Add a component. This creates the component in the ECS storage, but does not
  // assign it with a value.
  ecs_add(world, e, Velocity);
  // Set the value for the Position & Velocity components. A component will be
  // added if the entity doesn't have it yet.
  ecs_set(world, e, Position, {10, 20});
  ecs_set(world, e, Velocity, {1, 2});
  // Get a component
  const Position *p = ecs_get(world, e, Position);
  // Remove component
  ecs_remove(world, e, Position);
  ecs_remove
  #define ecs_remove(world, entity, T)
  Remove a component from an entity.
  Definition flecs_c.h:326
  ecs_add
  #define ecs_add(world, entity, T)
  Add a component to an entity.
  Definition flecs_c.h:318
  ECS_COMPONENT
  #define ECS_COMPONENT(world, id)
  Declare and define a component.
  Definition flecs_c.h:145
  ecs_set
  #define ecs_set(world, entity, component,...)
  Set a component value.
  Definition flecs_c.h:357
  ecs_get
  #define ecs_get(world, entity, T)
  Get a component.
  Definition flecs_c.h:386

- C++

  auto e = world.entity();
  // Add a component. This creates the component in the ECS storage, but does not
  // assign it with a value.
  e.add<Velocity>();
  // Set the value for the Position & Velocity components. A component will be
  // added if the entity doesn't have it yet.
  e.set<Position>({10, 20})
  .set<Velocity>({1, 2});
  // Get a component
  const Position& p = e.get<Position>();
  // Get mutable:
  // Position& p = e.get_mut<Position>();
  // Get optional:
  // const Position* p = e.try_get<Position>();
  // Get optional mutable:
  // Position* p = e.try_get_mut<Position>();
  // Remove component
  e.remove<Position>();
  flecs::entity_builder::set
  const Self & set(T &&value) const
  Set a component for an entity.
  Definition builder.hpp:705
  flecs::entity_builder::add
  const Self & add() const
  Add a component to an entity.
  Definition builder.hpp:25
  flecs::entity_view::get
  const T & get() const
  Get component value.
  Definition entity_view.hpp:432

- C#

  Entity e = world.Entity();
  // Add a component. This creates the component in the ECS storage, but does not
  // assign it with a value.
  e.Add<Velocity>();
  // Set the value for the Position & Velocity components. A component will be
  // added if the entity doesn't have it yet.
  e.Set<Position>(new(10, 20))
  .Set<Velocity>(new(1, 2));
  // Get a component
  ref readonly Position p = ref e.Get<Position>();
  // Remove component
  e.Remove<Position>();

- Rust

  let e = world.entity();
  // Add a component. This creates the component in the ECS storage, but does not
  // assign it with a value.
  e.add::<Velocity>();
  // Set the value for the Position & Velocity components. A component will be
  // added if the entity doesn't have it yet.
  e.set(Position { x: 10.0, y: 20.0 })
  .set(Velocity { x: 1.0, y: 2.0 });
  // Get a component
  e.get::<&Position>(|p| {
  println!("Position: ({}, {})", p.x, p.y);
  });
  // Remove component
  e.remove::<Position>();

- Clojure

  (merge w {:e []})
  (def e (:e w))
  ;; Add a component. This creates the component in the ECS storage, but does not
  ;; assign it with a value.
  (conj e Velocity)
  ;; Set the value for the Position & Velocity components. A component will be
  ;; added if the entity doesn't have it yet.
  (conj e (Position [10 20]) (Velocity [1 2]))
  ;; Get a component
  (e Position)
  ;; => {Position {:x 10.0, :y 20.0}}
  ;; Remove component
  (disj e Position)

Each component is associated by a unique entity identifier by Flecs. This makes it possible to inspect component data, or attach your own data to components.

- C

  C applications can use the ecs_id macro to get the entity id for a component.

  ECS_COMPONENT(world, Position);
  ecs_entity_t pos_e = ecs_id(Position);
  printf("Name: %s\n", ecs_get_name(world, pos_e)); // outputs 'Name: Position'
  // It's possible to add components like you would for any entity
  ecs_add(world, pos_e, Serializable);
  ecs_id
  FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
  Component ID for EcsDocDescription.

- C++

  C++ applications can use the world::entity function.

  flecs::entity pos_e = world.entity<Position>();
  std::cout << "Name: " << pos_e.name() << std::endl; // outputs 'Name: Position'
  // It's possible to add components like you would for any entity
  pos_e.add<Serializable>();
  flecs::entity
  Entity.
  Definition entity.hpp:30

- C#

  C# applications can use the World.Entity() function.

  Entity posE = world.Entity<Position>();
  Console.WriteLine($"Name: {posE.Name()}"); // outputs 'Name: Position'
  // It's possible to add components like you would for any entity
  posE.Add<Serializable>();

- Rust

  Rust applications can use the world::entity_from function.

  let pos_e = world.entity_from::<Position>();
  println!("Name: {}", pos_e.name()); // outputs 'Name: Position'
  // It's possible to add components like you would for any entity
  pos_e.add::<Serializable>();

- Clojure

  Clojure applications can use the vf/ent function.

  (def pos-e (vf/ent w Position))
  ;; Components generated from Clojure have the name prefixed with `C_` in the Flecs internal name
  (vf/get-name pos-e)
  ;; => "C_Position"
  ;; It's possible to add components like you would for any entity
  (conj pos-e Serializable)

The thing that makes an ordinary entity a component is the EcsComponent (or flecs::Component, in C++) component. This is a builtin component that tells Flecs how much space is needed to store a component, and can be inspected by applications:

- C

  ECS_COMPONENT(world, Position);
  ecs_entity_t pos_e = ecs_id(Position);
  const EcsComponent *c = ecs_get(world, pos_e, EcsComponent);
  printf("Component size: %u\n", c->size);
  EcsComponent
  Component information.
  Definition flecs.h:1600
  EcsComponent::size
  ecs_size_t size
  Component size.
  Definition flecs.h:1601

- C++

  flecs::entity pos_e = world.entity<Position>();
  const EcsComponent& c = pos_e.get<flecs::Component>();
  std::cout << "Component size: " << c.size << std::endl;
  flecs::Component
  EcsComponent Component
  Built-in EcsComponent type.
  Definition c_types.hpp:77

- C#

  Entity posE = world.Entity<Position>();
  ref readonly EcsComponent c = ref posE.Get<EcsComponent>();
  Console.WriteLine($"Component size: {c.size}");

- Rust

  let pos_e = world.entity_from::<Position>();
  pos_e.get::<&flecs::Component>(|c| {
  println!("Component size: {}", c.size);
  });

- Clojure

  ;; We use the lower-level C Flecs API directly.
  (-> (vf.c/ecs-get-id w (vf/eid pos-e) (vf/eid w :vf/component))
  (vp/as vf/EcsComponent))
  ;; => #:vybe.flecs{EcsComponent {:size 8, :alignment 4}}

Because components are stored as regular entities, they can in theory also be deleted. To prevent unexpected accidents however, by default components are registered with a tag that prevents them from being deleted. If this tag were to be removed, deleting a component would cause it to be removed from all entities. For more information on these policies, see Relationship cleanup propertiesRelationship cleanup properties.

## Tag

A tag is a component that does not have any data. In Flecs tags can be either empty types (in C++) or regular entities (C & C++) that do not have the EcsComponent component (or have an EcsComponent component with size 0). Tags can be added & removed using the same APIs as adding & removing components, but because tags have no data, they cannot be assigned a value. Because tags (like components) are regular entities, they can be created & deleted at runtime.

- C

  // Create Enemy tag
  ecs_entity_t Enemy = ecs_new(world);
  // Create entity, add Enemy tag
  ecs_entity_t e = ecs_new(world);
  ecs_add_id(world, e, Enemy);
  ecs_has_id(world, e, Enemy); // true!
  ecs_remove_id(world, e, Enemy);
  ecs_has_id(world, e, Enemy); // false!
  ecs_remove_id
  void ecs_remove_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
  Remove a component from an entity.
  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.
  ecs_has_id
  bool ecs_has_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
  Test if an entity has a component.

- C++

  // Option 1: create Tag as empty struct
  struct Enemy { };
  // Create entity, add Enemy tag
  auto e = world.entity().add<Enemy>();
  e.has<Enemy>(); // true!
  e.remove<Enemy>();
  e.has<Enemy>(); // false!
  // Option 2: create Tag as entity
  auto Enemy = world.entity();
  // Create entity, add Enemy tag
  auto e2 = world.entity().add(Enemy);
  e2.has(Enemy); // true!
  e2.remove(Enemy);
  e2.has(Enemy); // false!
  flecs::entity_view::has
  bool has(flecs::id_t e) const
  Check if entity has the provided entity.
  Definition entity_view.hpp:1032

- C#

  // Option 1: create Tag as empty struct
  public struct Enemy { }
  // Create entity, add Enemy tag
  Entity e = world.Entity().Add<Enemy>();
  e.Has<Enemy>(); // true!
  e.Remove<Enemy>();
  e.Has<Enemy>(); // false!
  // Option 2: create Tag as entity
  Entity Enemy = world.Entity();
  // Create entity, add Enemy tag
  Entity e = world.Entity().Add(Enemy);
  e.Has(Enemy); // true!
  e.Remove(Enemy);
  e.Has(Enemy); // false!

- Rust

  // Option 1: create Tag as empty struct
  #[derive(Component)]
  struct Enemy;
  // Create entity, add Enemy tag
  let e = world.entity().add::<Enemy>();
  e.has::<Enemy>(); // true!
  e.remove::<Enemy>();
  e.has::<Enemy>(); // false!
  // Option 2: create Tag as entity
  let enemy = world.entity();
  // Create entity, add Enemy tag
  let e = world.entity().add_id(enemy);
  e.has_id(enemy); // true!
  e.remove_id(enemy);
  e.has_id(enemy); // false!

- Clojure

  ;; Add tag (it will create the tag if it doesn't already exist) to an entity
  (merge w {:e [:enemy]})
  (:enemy (w :e))
  ;; => :enemy
  (disj (w :e) :enemy)
  (:enemy (w :e))
  ;; => nil

Note that both options in the C++ example achieve the same effect. The only difference is that in option 1 the tag is fixed at compile time, whereas in option 2 the tag can be created dynamically at runtime.

When a tag is deleted, the same rules apply as for components (see Relationship cleanup propertiesRelationship cleanup properties).

## Pair

A pair is a combination of two entity ids. Pairs can be used to store entity relationships, where the first id represents the relationship kind and the second id represents the relationship target (called "object"). This is best explained by an example:

- C

  // Create Likes relationship
  ecs_entity_t Likes = ecs_new(world);
  // Create a small graph with two entities that like each other
  ecs_entity_t Bob = ecs_new(world);
  ecs_entity_t Alice = ecs_new(world);
  ecs_add_pair(world, Bob, Likes, Alice); // Bob likes Alice
  ecs_add_pair(world, Alice, Likes, Bob); // Alice likes Bob
  ecs_has_pair(world, Bob, Likes, Alice); // true!
  ecs_remove_pair(world, Bob, Likes, Alice);
  ecs_has_pair(world, Bob, Likes, Alice); // false!
  ecs_add_pair
  #define ecs_add_pair(world, subject, first, second)
  Add a pair to an entity.
  Definition flecs_c.h:322
  ecs_remove_pair
  #define ecs_remove_pair(world, subject, first, second)
  Remove a pair from an entity.
  Definition flecs_c.h:330
  ecs_has_pair
  #define ecs_has_pair(world, entity, first, second)
  Test if an entity has a pair.
  Definition flecs_c.h:534

- C++

  // Create Likes relationship as empty type (tag)
  struct Likes { };
  // Create a small graph with two entities that like each other
  auto Bob = world.entity();
  auto Alice = world.entity();
  Bob.add<Likes>(Alice); // Bob likes Alice
  Alice.add<Likes>(Bob); // Alice likes Bob
  Bob.has<Likes>(Alice); // true!
  Bob.remove<Likes>(Alice);
  Bob.has<Likes>(Alice); // false!

- C#

  // Create Likes relationship as empty type (tag)
  public struct Likes { }
  // Create a small graph with two entities that like each other
  Entity Bob = world.Entity();
  Entity Alice = world.Entity();
  Bob.Add<Likes>(Alice); // Bob likes Alice
  Alice.Add<Likes>(Bob); // Alice likes Bob
  Bob.Has<Likes>(Alice); // true!
  Bob.Remove<Likes>(Alice);
  Bob.Has<Likes>(Alice); // false!

- Rust

  // Create Likes relationship as empty type (tag)
  #[derive(Component)]
  struct Likes;
  // Create a small graph with two entities that like each other
  let bob = world.entity();
  let alice = world.entity();
  bob.add_first::<Likes>(alice); // bob likes alice
  alice.add_first::<Likes>(bob); // alice likes bob
  bob.has_first::<Likes>(alice); // true!
  bob.remove_first::<Likes>(alice);
  bob.has_first::<Likes>(alice); // false!

- Clojure

  ;; Create a small graph with two entities that like each other
  ;; NOTE that relationships are encoded using `[...]`
  (merge w {:bob [[:likes :alice]]
  :alice [[:likes :bob]]})
  (get (w :bob) [:likes :alice])
  ;; => [:likes :alice]
  (disj (w :bob) [:likes :alice])
  (get (w :bob) [:likes :alice])
  ;; => nil

A pair can be encoded in a single 64 bit identifier by using the ecs_pair macro in C, or the world.pair function in C++:

- C

  ecs_id_t id = ecs_pair(Likes, Bob);
  ecs_id_t
  uint64_t ecs_id_t
  IDs are the things that can be added to an entity.
  Definition flecs.h:378

- C++

  flecs::id id = world.pair<Likes>(Bob);
  flecs::id
  Class that wraps around a flecs::id_t.
  Definition decl.hpp:27
  flecs::world::pair
  flecs::id pair() const
  Get pair ID from relationship and object.
  Definition impl.hpp:80

- C#

  Id id = world.Pair<Likes>(bob);

- Rust

  let id = world.id_first::<Likes>(bob);

- Clojure

  (vf/eid w [:likes :bob])

The following examples show how to get back the elements from a pair:

- C

  if (ecs_id_is_pair(id)) {
  ecs_entity_t relationship = ecs_pair_first(world, id);
  ecs_entity_t target = ecs_pair_second(world, id);
  }
  ecs_id_is_pair
  bool ecs_id_is_pair(ecs_id_t component)
  Utility to check if a component is a pair.

- C++

  flecs::id id = world.pair<Likes>(Bob);
  if (id.is_pair()) {
  auto relationship = id.first();
  auto target = id.second();
  }

- C#

  Id id = ...;
  if (id.IsPair())
  {
  Entity relationship = id.First();
  Entity target = id.Second();
  }

- Rust

  let id = world.id_from::<(Likes, Apples)>();
  if id.is_pair() {
  let relationship = id.first_id();
  let target = id.second_id();
  }

- Clojure

  (let [id (vf/eid w [:alice :likes])]
  [(vf/get-name (vf/pair-first w id))
  (vf/get-name (vf/pair-second w id))])
  ;; => ["alice" "likes"]

A component or tag can be added multiple times to the same entity as long as it is part of a pair, and the pair itself is unique:

- C

  ecs_add_pair(world, Bob, Eats, Apples);
  ecs_add_pair(world, Bob, Eats, Pears);
  ecs_add_pair(world, Bob, Grows, Pears);
  ecs_has_pair(world, Bob, Eats, Apples); // true!
  ecs_has_pair(world, Bob, Eats, Pears); // true!
  ecs_has_pair(world, Bob, Grows, Pears); // true!

- C++

  flecs::entity bob = world.entity();
  bob.add(Eats, Apples);
  bob.add(Eats, Pears);
  bob.add(Grows, Pears);
  bob.has(Eats, Apples); // true!
  bob.has(Eats, Pears); // true!
  bob.has(Grows, Pears); // true!

- C#

  Entity Bob = ...;
  Bob.Add(Eats, Apples);
  Bob.Add(Eats, Pears);
  Bob.Add(Grows, Pears);
  Bob.Has(Eats, Apples); // true!
  Bob.Has(Eats, Pears); // true!
  Bob.Has(Grows, Pears); // true!

- Rust

  let bob = world.entity();
  bob.add_id((eats, apples));
  bob.add_id((eats, pears));
  bob.add_id((grows, pears));
  bob.has_id((eats, apples)); // true!
  bob.has_id((eats, pears)); // true!
  bob.has_id((grows, pears)); // true!

- Clojure

  (merge w {:bob [[:eats :apple] [:eats :pears] [:grows :pears]]})
  (:bob w)
  ;; => #{[:grows :pears] [:eats :pears] [:eats :apple]}

The target function can be used in C and C++ to get the object for a relationship:

- C

  ecs_entity_t o = ecs_get_target(world, Alice, Likes, 0); // Returns Bob
  ecs_get_target
  ecs_entity_t ecs_get_target(const ecs_world_t *world, ecs_entity_t entity, ecs_entity_t rel, int32_t index)
  Get the target of a relationship.

- C++

  flecs::entity alice = world.entity();
  auto o = alice.target<Likes>(); // Returns Bob
  flecs::entity_view::target
  flecs::entity target(int32_t index=0) const
  Get target for a given pair.
  Definition impl.hpp:36

- C#

  Entity Alice = ...;
  Entity o = Alice.Target<Likes>(); // Returns Bob

- Rust

  let alice = world.entity().add_first::<Likes>(bob);
  let o = alice.target::<Likes>(0); // Returns bob

- Clojure

  (vf/get-name (vf/target (w :alice) :likes))
  ;; => "bob"

Entity relationships enable lots of interesting patterns and possibilities. Make sure to check out the Relationships manual.

## Hierarchies

Flecs has builtin support for hierarchies with the builtin EcsChildOf (or flecs::ChildOf, in C++) relationship. A hierarchy can be created with the regular relationship API, or with the child_of shortcut in C++:

- C

  ecs_entity_t parent = ecs_new(world);
  // ecs_new_w_pair is the same as ecs_new_id + ecs_add_pair
  ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
  // Deleting the parent also deletes its children
  ecs_delete(world, parent);
  EcsChildOf
  const ecs_entity_t EcsChildOf
  Used to express parent-child relationships.
  ecs_new_w_pair
  #define ecs_new_w_pair(world, first, second)
  Create a new entity with a pair.
  Definition flecs_c.h:303

- C++

  auto parent = world.entity();
  auto child = world.entity().child_of(parent);
  // Deleting the parent also deletes its children
  parent.destruct();
  flecs::entity_builder::child_of
  const Self & child_of(entity_t second) const
  Shortcut for add(ChildOf, entity).
  Definition builder.hpp:230
  flecs::entity::destruct
  void destruct() const
  Delete an entity.
  Definition entity.hpp:416

- C#

  Entity parent = world.Entity();
  Entity child = world.Entity().ChildOf(parent);
  // Deleting the parent also deletes its children
  parent.Destruct();

- Rust

  let parent = world.entity();
  let child = world.entity().child_of_id(parent);
  // Deleting the parent also deletes its children
  parent.destruct();

- Clojure

  ;; Note the nested map representing a child.
  (merge w {:parent [{:child []}]})
  (def child (w [:parent :child]))
  (vf/alive? child)
  ;; => true
  ;; Deleting the parent also deletes its children
  (dissoc w :parent)
  (vf/alive? child)
  ;; => false

When entities have names, they can be used together with hierarchies to generate path names or do relative lookups:

- C

  ecs_entity_t parent = ecs_entity(world, {
  .name = "parent"
  });
  ecs_entity_t child = ecs_entity(world, {
  .name = "child"
  });
  ecs_add_pair(world, child, EcsChildOf, parent);
  char *path = ecs_get_path(world, child);
  printf("%s\n", path); // output: 'parent.child'
  ecs_os_free(path);
  ecs_lookup(world, "parent.child"); // returns child
  ecs_lookup_from(world, parent, "child"); // returns child
  ecs_lookup_from
  #define ecs_lookup_from(world, parent, path)
  Lookup an entity from a parent.
  Definition flecs_c.h:593
  ecs_get_path
  #define ecs_get_path(world, child)
  Get path from root.
  Definition flecs_c.h:601

- C++

  auto parent = world.entity("parent");
  auto child = world.entity("child").child_of(parent);
  std::cout << child.path() << std::endl; // output: 'parent::child'
  world.lookup("parent::child"); // returns child
  parent.lookup("child"); // returns child
  flecs::entity_view::path
  flecs::string path(const char *sep="::", const char *init_sep="::") const
  Return the entity path.
  Definition entity_view.hpp:106
  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 parent = world.Entity("parent");
  Entity child = world.Entity("child").ChildOf(parent);
  Console.WriteLine(child.Path()); // output: 'parent.child'
  world.Lookup("parent.child"); // returns child
  parent.Lookup("child"); // returns child

- Rust

  let parent = world.entity_named("parent");
  let child = world.entity_named("child").child_of_id(parent);
  println!("Child path: {}", child.path().unwrap()); // output: 'parent::child'
  world.lookup("parent::child"); // returns child
  parent.lookup("child"); // returns child

- Clojure

  (vf/get-name (w [:parent :child]))
  ;; => "parent.child"

Queries (see below) can use hierarchies to order data breadth-first, which can come in handy when you're implementing a transform system:

- C

  ecs_query_t *q = ecs_query(world, {
  .terms = {
  { .id = ecs_id(Position) },
  { .id = ecs_id(Position),
  .trav = EcsChildOf, // Use ChildOf relationship for traversal
  .src.id = EcsCascade // Breadth-first order
  }}
  });
  ecs_iter_t it = ecs_query_iter(world, q);
  while (ecs_query_next(&it)) {
  Position *p = ecs_field(&it, Position, 0);
  Position *p_parent = ecs_field(&it, Position, 1);
  for (int i = 0; i < it.count; i++) {
  // Do the thing
  }
  }
  ecs_query
  #define ecs_query(world,...)
  Shorthand for creating a query with ecs_query_init().
  Definition flecs_c.h:262
  ecs_field
  #define ecs_field(it, T, index)
  Get field data for a component.
  Definition flecs_c.h:727
  ecs_query_next
  bool ecs_query_next(ecs_iter_t *it)
  Progress a query iterator.
  EcsCascade
  #define EcsCascade
  Sort results breadth-first.
  Definition flecs.h:760
  ecs_query_iter
  ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
  Create a query iterator.
  ecs_iter_t
  Iterator.
  Definition flecs.h:1170
  ecs_query_t
  Queries are lists of constraints (terms) that match entities.
  Definition flecs.h:838

- C++

  auto q = world.query_builder<Position, Position>()
  .term_at(1).parent().cascade()
  .build();
  q.each([](Position& p, Position& p_parent) {
  // Do the thing
  });
  flecs::world::query_builder
  flecs::query_builder< Comps... > query_builder(Args &&... args) const
  Create a query builder.
  Definition impl.hpp:325

- C#

  Query q = world.QueryBuilder<Position, Position>()
  .TermAt(1).Parent().Cascade()
  .Build();
  q.Each((ref Position p, ref Position pParent) =>
  {
  // Do the thing
  });

- Rust

  let q = world
  .query::<(&Position, &mut Position)>()
  .term_at(1)
  .parent()
  .cascade()
  .build();
  q.each(|(p, p_parent)| {
  // Do the thing
  });

- Clojure

  ;; The result of `with-query` will be available for you in the form of a vector.
  (vf/with-query w [pos Position
  pos-parent [:meta {:flags #{:up :cascade}}
  Position]]
  ;; Process each entity.
  )
  ;; => [...]

## Type

The type (often referred to as "archetype") is the list of ids an entity has. Types can be used for introspection which is useful when debugging, or when for example building an entity editor. The most common thing to do with a type is to convert it to text and print it:

- C

  ECS_COMPONENT(world, Position);
  ECS_COMPONENT(world, Velocity);
  ecs_entity_t e = ecs_new(world);
  ecs_add(world, e, Position);
  ecs_add(world, e, Velocity);
  const ecs_type_t *type = ecs_get_type(world, e);
  char *type_str = ecs_type_str(world, type);
  printf("Type: %s\n", type_str); // output: 'Position,Velocity'
  ecs_os_free(type_str);
  ecs_get_type
  const ecs_type_t * ecs_get_type(const ecs_world_t *world, ecs_entity_t entity)
  Get the type of an entity.
  ecs_type_str
  char * ecs_type_str(const ecs_world_t *world, const ecs_type_t *type)
  Convert a type to a string.
  ecs_type_t
  A type is a list of (component) IDs.
  Definition flecs.h:402

- C++

  auto e = world.entity()
  .add<Position>()
  .add<Velocity>();
  std::cout << e.type().str() << std::endl; // output: 'Position,Velocity'

- C#

  Entity e = ecs.Entity()
  .Add<Position>()
  .Add<Velocity>();
  Console.WriteLine(e.Type().Str()); // output: 'Position,Velocity'

- Rust

  let e = world.entity().add::<Position>().add::<Velocity>();
  println!("Components: {}", e.archetype().to_string().unwrap()); // output: 'Position,Velocity'

- Clojure

  (merge w {:some-entity [(Position) (Velocity)]})
  (:some-entity w)
  ;; => #{{Position {:x 0.0, :y 0.0}}, {Velocity {:x 0.0, :y 0.0}} }

A type can also be iterated by an application:

- C

  const ecs_type_t *type = ecs_get_type(world, e);
  for (int i = 0; i < type->count; i++) {
  if (type->array[i] == ecs_id(Position)) {
  // Found Position component!
  }
  }
  ecs_type_t::array
  ecs_id_t * array
  Array with IDs.
  Definition flecs.h:403
  ecs_type_t::count
  int32_t count
  Number of elements in array.
  Definition flecs.h:404

- C++

  auto e = world.entity();
  e.each([&](flecs::id id) {
  if (id == world.id<Position>()) {
  // Found Position component!
  }
  });
  flecs::entity_view::each
  void each(const Func &func) const
  Iterate (component) IDs of an entity.
  Definition impl.hpp:112
  flecs::world::id
  flecs::id id() const
  Get ID from a type.
  Definition impl.hpp:70

- C#

  e.Each((Id id) =>
  {
  if (id == world.Id<Position>())
  {
  // Found Position component!
  }
  });

- Rust

  e.each_component(|id| {
  if id == world.component_id::<Position>() {
  // Found Position component!
  }
  });

- Clojure

  (for [c (:some-entity w)]
  (vf/get-name w c))

## Singleton

A singleton is a single instance of a component that can be retrieved without an entity. The functions for singletons are very similar to the regular API:

- C

  // Register singleton component
  ecs_add_id(world, ecs_id(Gravity), EcsSingleton);
  // Set singleton component
  ecs_singleton_set(world, Gravity, { 9.81 });
  // Get singleton component
  const Gravity *g = ecs_singleton_get(world, Gravity);
  EcsSingleton
  const ecs_entity_t EcsSingleton
  Mark component as singleton.
  ecs_singleton_set
  #define ecs_singleton_set(world, comp,...)
  Set a singleton component value.
  Definition flecs_c.h:507
  ecs_singleton_get
  #define ecs_singleton_get(world, comp)
  Get a singleton component.
  Definition flecs_c.h:495

- C++

  // Register singleton component
  world.component<Gravity>().add(flecs::Singleton);
  // Set singleton component
  world.set<Gravity>({ 9.81 });
  // Get singleton component
  const Gravity& g = world.get<Gravity>();
  flecs::world::component
  flecs::component< T > component(Args &&... args) const
  Find or register a component.
  Definition impl.hpp:11
  flecs::world::set
  void set(const T &value) const
  Set singleton component.
  Definition world.hpp:779
  flecs::world::get
  const void * get(flecs::id_t id) const
  Get singleton component.
  Definition world.hpp:178

- C#

  // Set singleton component
  world.Set<Gravity>(new(9.81));
  // Get singleton component
  ref readonly Gravity g = ref world.Get<Gravity>();

- Rust

  // Set singleton component
  world.set(Gravity { x: 10, y: 20 });
  // Get singleton component
  world.get::<&Gravity>(|g| {
  println!("Gravity: {}, {}", g.x, g.y);
  });

- Clojure

  (vf/singleton! w (Position [30 40]))
  (vf/singleton w Position)
  ;; => {Position {:x 30.0, :y 40.0}}

Singleton components are created by adding the component to its own entity id. The above code examples are shortcuts for these regular API calls:

- C

  ecs_set(world, ecs_id(Gravity), Gravity, {9.81});
  const Gravity *g = ecs_get(world, ecs_id(Gravity), Gravity);

- C++

  flecs::entity grav_e = world.entity<Gravity>();
  grav_e.set<Gravity>({9.81});
  const Gravity& g = grav_e.get<Gravity>();

- C#

  Entity gravE = world.Entity<Gravity>();
  gravE.Set<Gravity>(new(10, 20));
  ref readonly Gravity g = ref gravE.Get<Gravity>();

- Rust

  let grav_e = world.entity_from::<Gravity>();
  grav_e.set(Gravity { x: 10, y: 20 });
  grav_e.get::<&Gravity>(|g| {
  println!("Gravity: {}, {}", g.x, g.y);
  });

- Clojure

  (merge w {Position [(Position [30 40])]})
  (get-in w [Position Position])

The following examples show how to query for a singleton component:

- C

  ecs_add_id(world, ecs_id(Gravity), EcsSingleton);
  // Create query that matches Gravity as singleton
  ecs_query_t *q = ecs_query(world, {
  .terms = {
  // Regular component
  { .id = ecs_id(Velocity) },
  // A singleton is a component matched on itself
  { .id = ecs_id(Gravity), .src.id = ecs_id(Gravity) }
  }
  });
  // Create a system using the query DSL with a singleton:
  ECS_SYSTEM(world, ApplyGravity, EcsOnUpdate, Velocity, Gravity);
  EcsOnUpdate
  const ecs_entity_t EcsOnUpdate
  OnUpdate pipeline phase.
  ECS_SYSTEM
  #define ECS_SYSTEM(world, id, phase,...)
  Declare and define a system.
  Definition system.h:263

- C++

  world.query_builder<Velocity, Gravity>()
  .build();

- C#

  world.QueryBuilder<Velocity, Gravity>().Build();

- Rust

  world
  .query::<(&Velocity, &Gravity)>()
  .build();

- Clojure

  (vf/with-query w [_ Velocity
  pos [:src Position Position]]
  pos)

## Query

Queries are the main mechanism for finding and iterating through entities. Queries are used in many parts of the API, such as for systems and observers. The following example shows a simple query:

- C

  ecs_query_t *q = ecs_query(world, {
  .terms = {
  { .id = ecs_id(Position) },
  { .id = ecs_pair(EcsChildOf, parent) }
  }
  });
  // Iterate the query results. Because entities are grouped by their type there
  // are two loops: an outer loop for the type, and an inner loop for the entities
  // for that type.
  ecs_iter_t it = ecs_query_iter(world, q);
  while (ecs_query_next(&it)) {
  // Each type has its own set of component arrays
  Position *p = ecs_field(&it, Position, 0);
  // Iterate all entities for the type
  for (int i = 0; i < it.count; i++) {
  printf("%s: {%f, %f}\n", ecs_get_name(world, it.entities[i]),
  p[i].x, p[i].y);
  }
  }
  ecs_query_fini(q);
  ecs_query_fini
  void ecs_query_fini(ecs_query_t *query)
  Delete a query.

- C++

  // For simple queries the world::each function can be used
  world.each([](Position& p, Velocity& v) { // flecs::entity argument is optional
  p.x += v.x;
  p.y += v.y;
  });
  // More complex queries can first be created, then iterated
  auto q = world.query_builder<Position>()
  .with(flecs::ChildOf, parent)
  .build();
  // Option 1: the each() callback iterates over each entity
  q.each([](flecs::entity e, Position& p) {
  std::cout << e.name() << ": {" << p.x << ", " << p.y << "}" << std::endl;
  });
  // Option 2: the run() callback offers more control over the iteration
  q.run([](flecs::iter& it) {
  while (it.next()) {
  auto p = it.field<Position>(0);
  for (auto i : it) {
  std::cout << it.entity(i).name()
  << ": {" << p[i].x << ", " << p[i].y << "}" << std::endl;
  }
  }
  });
  flecs::world::each
  void each(Func &&func) const
  Iterate over all entities with components in the argument list of the function.
  Definition impl.hpp:391
  flecs::iter
  Class for iterating over query results.
  Definition iter.hpp:68
  flecs::iter::field
  flecs::field< A > field(int8_t index) const
  Get read-only access to field data.
  Definition iter.hpp:80
  flecs::iter::next
  bool next()
  Progress iterator.
  Definition iter.hpp:439

- C#

  // For simple queries the each function can be used
  world.Each((ref Position p, ref Velocity v) => // Entity argument is optional
  {
  p.X += v.X;
  p.Y += v.Y;
  });
  // More complex filters can first be created, then iterated
  using Query q = world.QueryBuilder<Position>()
  .With(Ecs.ChildOf, parent)
  .Build();
  // Option 1: The Each() callback that iterates each entity
  q.Each((Entity e, ref Position p) =>
  {
  Console.WriteLine($"{e.Name()}: ({p.X}, {p.Y})")
  });
  // Option 2: The Iter() callback provides more control over the iteration
  q.Iter((Iter it, Field<Position> p) =>
  {
  foreach (int i in it)
  Console.WriteLine($"{it.Entity(i).Name()}: ({p[i].X}, {p[i].Y})")
  });

- Rust

  // For simple queries the world::each function can be used
  world.each::<(&mut Position, &Velocity)>(|(p, v)| {
  // EntityView argument is optional, use each_entity to get it
  p.x += v.x;
  p.y += v.y;
  });
  // More complex queries can first be created, then iterated
  let q = world
  .query::<&Position>()
  .with_id((flecs::ChildOf::ID, parent))
  .build();
  // Option 1: the each() callback iterates over each entity
  q.each_entity(|e, p| {
  println!("{}: ({}, {})", e.name(), p.x, p.y);
  });
  // Option 2: the run() callback offers more control over the iteration
  q.run(|mut it| {
  while it.next() {
  let p = it.field::<Position>(0).unwrap();
  for i in it.iter() {
  println!("{}: ({}, {})", it.entity(i).name(), p[i].x, p[i].y);
  }
  }
  });

- Clojure

  ;; We create a parent and a child, with the child containing Position and Velocity
  (merge w {:parent [{:child [(Position [1 2]) (Velocity [0.1 0.2])]}]})
  ;; Simple query, the bindings are const by default, :mut should be used to indicate
  ;; that you plan to mutate binding, otherwise an exception will be thrown
  (vf/with-query w [p [:mut Position]
  {:keys [x y]} Velocity]
  (-> p
  (update :x + x)
  (update :y + y)))
  ;; => [{Position {:x 1.1, :y 2.2}}]
  ;; We can do more complex queries, e.g. query for all the entities
  ;; that have Position and that are a child of :parent, :vf/entity
  ;; is a way to retrieve the entity which we are iterating over
  (vf/with-query w [p Position
  _ [:vf/child-of :parent]
  e :vf/entity]
  (vf/get-name e))
  ;; => ["parent.child"]

Queries can use operators to exclude components, optionally match components or match one out of a list of components. Additionally filters may contain wildcards for terms which is especially useful when combined with pairs.

The following example shows a query that matches all entities with a parent that do not have Position:

- C

  ecs_query_t *q = ecs_query(world, {
  .terms = {
  { ecs_pair(EcsChildOf, EcsWildcard) },
  { ecs_id(Position), .oper = EcsNot },
  }
  });
  // Iteration code is the same
  EcsWildcard
  const ecs_entity_t EcsWildcard
  Wildcard entity ("*").
  EcsNot
  @ EcsNot
  The term must not match.
  Definition flecs.h:721

- C++

  flecs::query<> q = world.query_builder()
  .with(flecs::ChildOf, flecs::Wildcard)
  .with<Position>().oper(flecs::Not)
  .build();
  // Iteration code is the same
  flecs::Not
  @ Not
  Not operator.
  Definition c_types.hpp:52
  flecs::query
  Typed query.
  Definition impl.hpp:262

- C#

  using Query q = world.QueryBuilder()
  .With(Ecs.ChildOf, Ecs.Wildcard)
  .With<Position>().Oper(Ecs.Not)
  .Build();
  // Iteration code is the same

- Rust

  let q = world
  .query::<()>()
  .with::<(flecs::ChildOf, flecs::Wildcard)>()
  .with::<Position>()
  .set_oper(OperKind::Not)
  .build();
  // Iteration code is the same

- Clojure

  (vf/with-query w [_ [:vf/child-of :*]
  _ [:not Position]]
  ...)

See the query manual for more details.

## System

A system is a query combined with a callback. Systems can be either ran manually or ran as part of an ECS-managed main loop (see PipelinePipeline). The system API looks similar to queries:

- C

  // Option 1, use the ECS_SYSTEM convenience macro
  ECS_SYSTEM(world, Move, 0, Position, Velocity);
  ecs_run(world, Move, delta_time, NULL); // Run system
  // Option 2, use the ecs_system_init function/ecs_system macro
  ecs_entity_t move_sys = ecs_system(world, {
  .query.terms = {
  { ecs_id(Position) },
  { ecs_id(Velocity) },
  },
  .callback = Move
  });
  ecs_run(world, move_sys, delta_time, NULL); // Run system
  // The callback code (same for both options)
  void Move(ecs_iter_t *it) {
  Position *p = ecs_field(it, Position, 0);
  Velocity *v = ecs_field(it, Velocity, 1);
  for (int i = 0; i < it->count; i++) {
  p[i].x += v[i].x * it->delta_time;
  p[i].y += v[i].y * it->delta_time;
  }
  }
  ecs_system
  #define ecs_system(world,...)
  Shorthand for creating a system with ecs_system_init().
  Definition system.h:287
  ecs_run
  FLECS_API ecs_entity_t ecs_run(ecs_world_t *world, ecs_entity_t system, ecs_ftime_t delta_time, void *param)
  Run a specific system manually.
  ecs_iter_t::delta_time
  float delta_time
  Time elapsed since last frame.
  Definition flecs.h:1214
  ecs_iter_t::count
  int32_t count
  Number of entities to iterate.
  Definition flecs.h:1177

- C++

  // Use each() function that iterates each individual entity
  auto move_sys = world.system<Position, Velocity>()
  .each([](flecs::iter& it, size_t, Position& p, Velocity& v) {
  p.x += v.x * it.delta_time();
  p.y += v.y * it.delta_time();
  });
  // Just like with queries, systems have both the run() and
  // each() methods to iterate entities.
  move_sys.run();
  flecs::world::system
  flecs::system system(flecs::entity e) const
  Upcast an entity to a system.
  Definition impl.hpp:204
  flecs::iter::delta_time
  ecs_ftime_t delta_time() const
  Get the time elapsed since the last frame.
  Definition iter.hpp:123

- C#

  // Use Each() function that iterates each individual entity
  System<Position, Velocity> moveSys = world.System<Position, Velocity>()
  .Each((Entity e, ref Position p, ref Velocity v) =>
  {
  p.X += v.X * it.DeltaTime();
  p.Y += v.Y * it.DeltaTime();
  });
  // Just like with queries, systems have both the Iter() and
  // Each() methods to iterate entities.
  moveSys.Run();

- Rust

  // Use each_entity() function that iterates each individual entity
  let move_sys = world
  .system::<(&mut Position, &Velocity)>()
  .each_iter(|it, i, (p, v)| {
  p.x += v.x * it.delta_time();
  p.y += v.y * it.delta_time();
  });
  // Just like with queries, systems have both the run() and
  // each() methods to iterate entities.
  move_sys.run();

- Clojure

  ;; Use with-system function that iterates each individual entity, the return
  ;; is the system entity, note that the body and bindings are just like with-query
  (vf/with-system w [:vf/name :my-system
  p [:mut Position]
  {:keys [x y]} Velocity]
  (-> p
  (update :x + x)
  (update :y + y)))
  ;; Run a system
  (vf/system-run (w :my-system))
  ;; Or you can also define it using defsystem, it will create a function that
  ;; can be called with a world later
  (vf/defsystem my-system w
  [p [:mut Position]
  {:keys [x y]} Velocity]
  (-> p
  (update :x + x)
  (update :y + y)))
  (my-system w)

Systems are stored as entities with an EcsSystem component (flecs::System in C++), similar to components. That means that an application can use a system as a regular entity:

- C

  printf("System: %s\n", ecs_get_name(world, move_sys));
  ecs_add(world, move_sys, EcsOnUpdate);
  ecs_delete(world, move_sys);

- C++

  std::cout << "System: " << move_sys.name() << std::endl;
  move_sys.add(flecs::OnUpdate);
  move_sys.destruct();

- C#

  Console.WriteLine($"System: {moveSys.Name()}");
  moveSys.Entity.Add(Ecs.OnUpdate);
  moveSys.Entity.Destruct();

- Rust

  println!("System: {}", move_sys.name());
  move_sys.add::<flecs::pipeline::OnUpdate>();
  move_sys.destruct();

- Clojure

  (vf/get-name (w :my-system))
  (conj ( :my-system) (flecs/EcsOnUpdate))
  (dissoc w :my-system)

## Pipeline

A pipeline is a list of tags that when matched, produces a list of systems to run. These tags are also referred to as a system "phase". Flecs comes with a default pipeline that has the following phases:

- C

  EcsOnLoad
  EcsPostLoad
  EcsPreUpdate
  EcsOnUpdate
  EcsOnValidate
  EcsPostUpdate
  EcsPreStore
  EcsOnStore
  EcsOnStore
  const ecs_entity_t EcsOnStore
  OnStore pipeline phase.
  EcsPreStore
  const ecs_entity_t EcsPreStore
  PreStore pipeline phase.
  EcsOnLoad
  const ecs_entity_t EcsOnLoad
  OnLoad pipeline phase.
  EcsPostUpdate
  const ecs_entity_t EcsPostUpdate
  PostUpdate pipeline phase.
  EcsOnValidate
  const ecs_entity_t EcsOnValidate
  OnValidate pipeline phase.
  EcsPreUpdate
  const ecs_entity_t EcsPreUpdate
  PreUpdate pipeline phase.
  EcsPostLoad
  const ecs_entity_t EcsPostLoad
  PostLoad pipeline phase.

- C++

  flecs::OnLoad
  flecs::PostLoad
  flecs::PreUpdate
  flecs::OnUpdate
  flecs::OnValidate
  flecs::PostUpdate
  flecs::PreStore
  flecs::OnStore

- C#

  Ecs.OnLoad
  Ecs.PostLoad
  Ecs.PreUpdate
  Ecs.OnUpdate
  Ecs.OnValidate
  Ecs.PostUpdate
  Ecs.PreStore
  Ecs.OnStore

- Rust

  flecs::pipeline::OnLoad;
  flecs::pipeline::PostLoad;
  flecs::pipeline::PreUpdate;
  flecs::pipeline::OnUpdate;
  flecs::pipeline::OnValidate;
  flecs::pipeline::PostUpdate;
  flecs::pipeline::PreStore;
  flecs::pipeline::OnStore;

- Clojure

  (flecs/EcsOnLoad)
  (flecs/EcsPostLoad)
  (flecs/EcsPreUpdate)
  (flecs/EcsOnUpdate)
  (flecs/EcsOnValidate)
  (flecs/EcsPostUpdate)
  (flecs/EcsPreStore)
  (flecs/EcsOnStore)

When a pipeline is executed, systems are ran in the order of the phases. This makes pipelines and phases the primary mechanism for defining ordering between systems. The following code shows how to assign systems to a pipeline, and how to run the pipeline with the progress() function:

- C

  ECS_SYSTEM(world, Move, EcsOnUpdate, Position, Velocity);
  ECS_SYSTEM(world, Transform, EcsPostUpdate, Position, Transform);
  ECS_SYSTEM(world, Render, EcsOnStore, Transform, Mesh);
  ecs_progress(world, 0); // run systems in default pipeline
  ecs_progress
  FLECS_API bool ecs_progress(ecs_world_t *world, ecs_ftime_t delta_time)
  Progress a world.

- C++

  world.system<Position, Velocity>("Move").kind(flecs::OnUpdate).each( ... );
  world.system<Position, Transform>("Transform").kind(flecs::PostUpdate).each( ... );
  world.system<Transform, Mesh>("Render").kind(flecs::OnStore).each( ... );
  world.progress();
  flecs::world::progress
  bool progress(ecs_ftime_t delta_time=0.0) const
  Progress the world one tick.
  Definition impl.hpp:47
  flecs::system::each
  system & each(Func &&func)
  Replace the system's each callback.
  Definition impl.hpp:122

- C#

  world.System<Position, Velocity>("Move").Kind(Ecs.OnUpdate).Each( ... );
  world.System<Position, Transform>("Transform").Kind(Ecs.PostUpdate).Each( ... );
  world.System<Transform, Mesh>("Render").Kind(Ecs.OnStore).Each( ... );
  world.Progress();

- Rust

  world
  .system_named::<(&mut Position, &Velocity)>("Move")
  .kind::<flecs::pipeline::OnUpdate>()
  .each(|(p, v)| {});
  world
  .system_named::<(&mut Position, &Transform)>("Transform")
  .kind::<flecs::pipeline::PostUpdate>()
  .each(|(p, t)| {});
  world
  .system_named::<(&Transform, &mut Mesh)>("Render")
  .kind::<flecs::pipeline::OnStore>()
  .each(|(t, m)| {});
  world.progress();

- Clojure

  ;; Define the systems
  (vf/defsystem move w
  [p Position
  v Velocity
  ;; This is the default phase.
  :vf/phase (flecs/EcsOnUpdate)]
  ...)
  (vf/defsystem transform w
  [p Position
  t Transform
  :vf/phase (flecs/EcsPostUpdate)]
  ...)
  (vf/defsystem render w
  [t Transform
  mesh Mesh
  :vf/phase (flecs/EcsOnStore)]
  ...)
  ;; Add systems to the world
  (move w)
  (transform w)
  (render w)
  ;; Run systems in default pipeline
  (vf/progress w)

Because phases are just tags that are added to systems, applications can use the regular API to add/remove systems to a phase:

- C

  ecs_remove_id(world, Move, EcsOnUpdate);
  ecs_add_id(world, Move, EcsPostUpdate);

- C++

  move_sys.add(flecs::OnUpdate);
  move_sys.remove(flecs::PostUpdate);

- C#

  moveSys.Add(Ecs.OnUpdate);
  moveSys.Remove(Ecs.PostUpdate);

- Rust

  move_sys.add::<flecs::pipeline::OnUpdate>();
  move_sys.remove::<flecs::pipeline::PostUpdate>();

- Clojure

  (conj (w :move) (flecs/EcsOnUpdate))
  (disj (w :move) (flecs/EcsPostUpdate))

Inside a phase, systems are guaranteed to be ran in their declaration order.

## Observer

Observers are callbacks that are invoked when one or more events matches the query of an observer. Events can be either user defined or builtin. Examples of builtin events are OnAdd, OnRemove and OnSet.

When an observer has a query with more than one component, the observer will not be invoked until the entity for which the event is emitted satisfies the entire query.

An example of an observer with two components:

- C

  ecs_observer(world, {
  .query.terms = { { ecs_id(Position) }, { ecs_id(Velocity) }},
  .events = { EcsOnSet },
  .callback = OnSetPosition
  });
  // Callback code is same as system
  ecs_entity_t e = ecs_new(world); // Doesn't invoke the observer
  ecs_set(world, e, Position, {10, 20}); // Doesn't invoke the observer
  ecs_set(world, e, Velocity, {1, 2}); // Invokes the observer
  ecs_set(world, e, Position, {20, 40}); // Invokes the observer
  EcsOnSet
  const ecs_entity_t EcsOnSet
  Event that triggers when a component is set for an entity.
  ecs_observer
  #define ecs_observer(world,...)
  Shorthand for creating an observer with ecs_observer_init().
  Definition flecs_c.h:277

- C++

  world.observer<Position, Velocity>("OnSetPosition")
  .event(flecs::OnSet)
  // Callback code is same as system
  .each([](Position& p, Velocity& v) { });
  auto e = world.entity(); // Doesn't invoke the observer
  e.set<Position>({10, 20}); // Doesn't invoke the observer
  e.set<Velocity>({1, 2}); // Invokes the observer
  e.set<Position>({20, 30}); // Invokes the observer
  flecs::world::observer
  flecs::observer observer(flecs::entity e) const
  Observer world mixin.
  Definition impl.hpp:108

- C#

  world.Observer<Position, Velocity>("OnSetPosition")
  .Event(Ecs.OnSet)
  .Each( ... ); // Callback code is same as system
  Entity e = ecs.Entity(); // Doesn't invoke the observer
  e.Set<Position>(new(10, 20)); // Doesn't invoke the observer
  e.Set<Velocity>(new(1, 2)); // Invokes the observer
  e.Set<Position>(new(20, 30)); // Invokes the observer

- Rust

  world
  .observer_named::<flecs::OnSet, (&Position, &Velocity)>("OnSetPosition")
  .each(|(p, v)| {}); // Callback code is same as system
  let e = world.entity(); // Doesn't invoke the observer
  e.set(Position { x: 10.0, y: 20.0 }); // Doesn't invoke the observer
  e.set(Velocity { x: 1.0, y: 2.0 }); // Invokes the observer
  e.set(Position { x: 30.0, y: 40.0 }); // Invokes the observer

- Clojure

  ;; Similar to with-system, but you have special configuration keys like :vf/events
  (vf/with-observer w [:vf/name ::on-set-position
  :vf/events #{:set}
  p Position
  v Velocity]
  ...)
  ;; Doesn't invoke the observer
  (merge w {:e []})
  ;; Doesn't invoke the observer
  (merge w {:e [(Position [10 20])]})
  ;; Invokes the observer
  (merge w {:e [(Velocity [1 2])]})
  ;; Invokes the observer
  (merge w {:e [(Position [30 40])]})

## Module

A module is a function that imports and organizes components, systems, triggers, observers, prefabs into the world as reusable units of code. A well designed module has no code that directly relies on code of another module, except for components definitions. All module contents are stored as child entities inside the module scope with the ChildOf relationship. The following examples show how to define a module in C and C++:

- C

  // Module header (e.g. MyModule.h)
  typedef struct {
  float x;
  float y;
  } Position;
  extern ECS_COMPONENT_DECLARE(Position);
  // The import function name has to follow the convention: <ModuleName>Import
  void MyModuleImport(ecs_world_t *world);
  // Module source (e.g. MyModule.c)
  ECS_COMPONENT_DECLARE(Position);
  void MyModuleImport(ecs_world_t *world) {
  ECS_MODULE(world, MyModule);
  ECS_COMPONENT_DEFINE(world, Position);
  }
  // Import code
  ECS_IMPORT(world, MyModule);
  ECS_MODULE
  #define ECS_MODULE(world, id)
  Create a module.
  Definition module.h:113
  ECS_IMPORT
  #define ECS_IMPORT(world, id)
  Wrapper around ecs_import().
  Definition module.h:125
  ECS_COMPONENT_DEFINE
  #define ECS_COMPONENT_DEFINE(world, id_)
  Define a forward-declared component.
  Definition flecs_c.h:122
  ECS_COMPONENT_DECLARE
  #define ECS_COMPONENT_DECLARE(id)
  Forward declare a component.
  Definition flecs_c.h:112

- C++

  struct my_module {
  my_module(flecs::world& world) {
  world.module<my_module>();
  // Define components, systems, triggers, ... as usual. They will be
  // automatically created inside the scope of the module.
  }
  };
  // Import code
  world.import<my_module>();
  flecs::world::import
  flecs::entity import()
  Import a module.
  Definition impl.hpp:107
  flecs::world::module
  flecs::entity module(const char *name=nullptr) const
  Define a module.
  Definition impl.hpp:83

- C#

  public struct MyModule : IFlecsModule
  {
  public void InitModule(ref World world)
  {
  world.Module<MyModule>();
  // Define components, systems, triggers, ... as usual. They will be
  // automatically created inside the scope of the module.
  }
  };
  // Import code
  world.Import<MyModule>();

- Rust

  #[derive(Component)]
  struct MyModule;
  impl Module for MyModule {
  fn module(world: &World) {
  world.module::<MyModule>("MyModule");
  // Define components, systems, triggers, ... as usual. They will be
  // automatically created inside the scope of the module.
  }
  }
  // Import code
  world.import::<MyModule>();

- Clojure

  ;; No wrapper for modules as Clojure has package namespacing already, but
  ;; you can use the the Flecs C Api directly if needed (vf.c/...)