# How to Create and Manage Entities with Custom Components in Flecs

> Learn to create and manage entities with custom components in Flecs. Define C structs, register components, and efficiently attach data to entities for your game engine.

- Repository: [Alexander/equilibriumengine](https://github.com/clibequilibrium/equilibriumengine)
- Tags: how-to-guide
- Published: 2026-02-27

---

**To create and manage entities with custom components in Flecs, declare a C struct for your data, register it with `ECS_COMPONENT_DEFINE`, then use `entity_create_empty` followed by `ecs_set` to attach component data to entities.**

The **EquilibriumEngine** leverages the [Flecs](https://github.com/flecs-factory/flecs) entity component system to compose game objects from reusable data structures. Understanding how to define, register, and manipulate custom components is essential for extending the engine's functionality. This guide walks through the exact patterns used in the `clibequilibrium/equilibriumengine` repository, referencing specific source files and function implementations.

## Declaring Custom Component Types

All custom components in EquilibriumEngine follow a standardized declaration pattern using Flecs macros. The process separates the component's entity ID declaration from its underlying C struct definition.

In **[[`equilibrium/components/transform.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/components/transform.c)](https://github.com/clibequilibrium/equilibriumengine/blob/master/equilibrium/components/transform.c)**, the engine declares transform-related components using:

```c
ECS_COMPONENT_DECLARE(Position);

```

This macro expands to a forward declaration of the component's entity ID. The concrete data structure—typically a plain C struct using types from the *cglm* math library—resides in the same translation unit. For example:

```c
typedef struct { vec3 value; } Position;
typedef struct { vec3 value; } Scale;
typedef struct { versor value; } Quaternion;

```

As implemented in `clibequilibrium/equilibriumengine`, components store primitive types, vectors (`vec3`), or quaternions (`versor`) depending on their purpose.

## Registering Components with the World

Before you can attach custom components to entities, you must register them with the Flecs world during engine initialization. This maps the C struct type to the component entity ID.

The registration function in **[[`equilibrium/components/transform.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/components/transform.c)](https://github.com/clibequilibrium/equilibriumengine/blob/master/equilibrium/components/transform.c)** demonstrates this pattern:

```c
void equilibrium_register_transform_components(void *world) {
    ECS_COMPONENT_DEFINE(world, Position);
    ECS_COMPONENT_DEFINE(world, Scale);
    ECS_COMPONENT_DEFINE(world, Rotation);
    ECS_COMPONENT_DEFINE(world, Quaternion);
    ECS_COMPONENT_DEFINE(world, Transform);
    ECS_COMPONENT_DEFINE(world, Project);
}

```

The `ECS_COMPONENT_DEFINE` macro (lines 14‑19 in the source) completes the registration process. This function is invoked from the engine's initialization routine in **[[`equilibrium/engine.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/engine.c)](https://github.com/clibequilibrium/equilibriumengine/blob/master/equilibrium/engine.c)** immediately after `ecs_init()` creates the world. Once registered, the component type is available for attachment to any entity throughout the application's lifetime.

## Creating Entities and Attaching Components

### Empty Entity Factory

The engine provides a convenience wrapper around `ecs_new` for creating bare entities. In **[[`equilibrium/entity.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/entity.c)](https://github.com/clibequilibrium/equilibriumengine/blob/master/equilibrium/entity.c)** (lines 5‑9), the `entity_create_empty` function creates an entity and tags it with the engine-wide `Entity` marker component:

```c
entity_t entity_create_empty(void *world, const char *name) {
    entity_t entity = (entity_t){ecs_new(world, 0), world};
    ecs_doc_set_name(world, entity.handle,
        name == NULL || name[0] == '\0' ? "Entity" : name);
    ecs_add(entity.world, entity.handle, Entity);
    return entity;
}

```

The function returns an `entity_t` struct containing both the Flecs entity handle (`ecs_entity_t`) and a pointer to the world, simplifying subsequent operations.

### Adding Component Data

After creation, attach custom components using one of two approaches:

- **`ecs_add`** – Attaches a tag component (zero-sized type) with no data. The engine uses this for the `Entity` marker.
- **`ecs_set`** – Attaches a component and initializes its fields in a single call.

To create a game object with custom `Position` and `Velocity` components:

```c
entity_t obj = entity_create_empty(world, "MovingBox");
ecs_set(world, obj.handle, Position, {.value = {0.0f, 0.0f, 0.0f}});
ecs_set(world, obj.handle, Velocity, {.value = {1.0f, 0.0f, 0.0f}});

```

The `ecs_set` macro handles type safety and automatically ensures the component is added if not present, then writes the data.

### Factory Function Patterns

For frequently instantiated archetypes, the engine uses "factory" functions that bundle creation and component attachment. While the repository does not expose a full camera factory, the pattern follows the `entity_create_empty` wrapper structure found throughout editor systems. For example, in **[[`editor/systems/mouse_picking_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/editor/systems/mouse_picking_system.c)](https://github.com/clibequilibrium/equilibriumengine/blob/master/editor/systems/mouse_picking_system.c)** (line 13 declares the component, line 130 registers it), custom components like `MousePickingData` are instantiated using the same workflow:

```c
entity_t create_camera(void *world, const char *name) {
    entity_t cam = entity_create_empty(world, name);
    ecs_set(world, cam.handle, Camera, {.type = CameraPerspective});
    ecs_set(world, cam.handle, Transform, {0}); // identity matrix
    return cam;
}

```

## Updating Component Data at Runtime

Components are mutable C structures. To modify data during the game loop, obtain a mutable pointer with `ecs_get_mut`, modify the fields, then notify Flecs of the change with `ecs_modified`:

```c
Position *p = ecs_get_mut(world, ent.handle, Position, NULL);
p->value.x += dt * speed;
ecs_modified(world, ent.handle, Position);

```

The `ecs_modified` call is critical—it signals Flecs to invalidate caches and ensures that systems reading `Position` receive the updated value during the current frame. Failing to call `ecs_modified` after mutation can result in stale data being read by query iterators.

## Destroying Entities and Cleanup

When an entity is no longer needed, the engine provides a thin wrapper around Flecs's deletion API. In **[[`equilibrium/entity.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/entity.c)](https://github.com/clibequilibrium/equilibriumengine/blob/master/equilibrium/engine.c)** (line 12), `entity_destroy` handles removal:

```c
void entity_destroy(entity_t entity) { 
    ecs_delete(entity.world, entity.handle); 
}

```

All components attached to the entity are automatically cleaned up by Flecs when `ecs_delete` is invoked. This includes any custom components registered earlier in the session.

## Summary

- **Declare** custom components using `ECS_COMPONENT_DECLARE` in headers, defining the underlying C struct with your data fields.
- **Register** components once during initialization using `ECS_COMPONENT_DEFINE` in functions like `equilibrium_register_transform_components`.
- **Create** entities via `entity_create_empty` (defined in [`equilibrium/entity.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/entity.c)), which returns a handle-world pair.
- **Attach** data components with `ecs_set` and tag components with `ecs_add`.
- **Modify** data using `ecs_get_mut` followed by `ecs_modified` to ensure system visibility.
- **Destroy** entities using `entity_destroy`, which calls `ecs_delete` and automatically releases all attached components.

## Frequently Asked Questions

### What is the difference between `ecs_add` and `ecs_set` in Flecs?

**`ecs_add`** attaches a component without initializing data, used primarily for zero-sized tag components like the `Entity` marker in EquilibriumEngine. **`ecs_set`** both attaches the component (if missing) and writes initial data to its fields, making it the preferred method for data-bearing components like `Position` or custom game logic components.

### How do I ensure systems see my component updates immediately?

After modifying component data through a pointer obtained via `ecs_get_mut`, you must call **`ecs_modified(world, entity, ComponentType)`**. This notifies Flecs that the component has changed, invalidating query caches so systems iterating over that component type receive the updated values during the current frame.

### Where should I register custom components in the EquilibriumEngine codebase?

Register custom components in a dedicated registration function (following the pattern in [`equilibrium/components/transform.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/components/transform.c)) and invoke it from **[`equilibrium/engine.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/engine.c)** during world initialization. The registry must happen after `ecs_init()` but before any entities attempt to use the component type.

### Can I create entities with multiple components in a single call?

While Flecs supports `ecs_new_w_id` for creating entities with an initial component, EquilibriumEngine typically uses the **factory pattern**: call `entity_create_empty` to get a bare entity, then chain `ecs_set` calls for each custom component. This explicit approach improves readability and allows conditional component attachment based on game logic.