This is an old revision of the document!
IEntity
An IEntity is the central runtime structure of the ECS architecture and the primary container for application state. Most state represented by the ECS exists as an Entity composed of one or more Components.
An Entity itself intentionally contains very little domain-specific state or behavior. Instead, its purpose is to group Components into a single runtime object, provide access to those Components, retain the EntityStaticData that defines its composition, and manage the Entity's lifecycle.
This separation is fundamental to the architecture: the Entity represents the object, while its Components represent the individual pieces of state and functionality that make that object what it is.
Broadcasts Events: EntityIsNullTopic
Entity Composition
The composition of an Entity is defined by its EntityStaticData. EntityStaticData acts as the definition or archetype from which runtime Entities are created and contains the ComponentStaticData entries describing which Components belong to the Entity.
Entity creation is handled by the IEntityFactory. When an Entity is created from a StaticDataID, the factory:
- Retrieves the corresponding Entity Static Data.
- Examines the Component Static Data contained within it.
- Determines the runtime IComponent type associated with each Component Static Data type.
- Creates each required Component.
- Associates each Component with the newly created Entity and its corresponding Component Static Data.
- Initializes Component properties configured to receive values from Static Data.
- Attaches the completed Component collection to the Entity.
As a result, users do not normally construct an Entity and manually decide which Components it contains. The Entity's composition originates from its EntityStaticData and is assembled automatically by the IEntityFactory.
Conceptually, the relationship can be viewed as:
Entity Static Data → Component Static Data → Runtime Components → Entity Instance
Entity Static Data defines what an Entity is composed of, Component Static Data defines the initial configuration of those Components, and the runtime Components contain the changing state of the individual Entity instance.
Entities and Components
An Entity can contain many Components, with each Component type representing a particular capability or piece of state. Systems and services can query an Entity for a specific Component rather than depending on a specialized Entity class.
For example, the presence of an ITransformComponent allows an Entity to contain positional state, while an IEntityIdentifierComponent allows it to participate in the framework's UID system. These capabilities are determined by composition rather than inheritance.
An Entity therefore should generally be treated as a collection of capabilities. Code interested in a particular capability should query for the corresponding Component using GetComponent, TryGetComponent or HasComponent.
Static Data ID and Entity Identity
The ID stored by Entity Static Data identifies the type or definition of Entity being created, not a unique runtime Entity instance. Multiple Entity instances can be created from the same Entity Static Data and therefore share the same Static Data ID.
When an Entity requires a persistent unique runtime identifier, it contains an IEntityIdentifierComponent. That Component's UID is used by systems such as serialization to identify a specific Entity instance independently of its Static Data definition.
Implementations
There are two internal implementations of IEntity: ArrayEntity and SetEntity. Both expose the same IEntity API and this distinction is intentionally hidden from consumers.
The IEntityFactory automatically selects the implementation based on the number of Components defined by the Entity Static Data.
* ArrayEntity is currently used for Entities with fewer than 10 Components. Components and their Types are stored in arrays and Component lookups perform a small linear search. This avoids the additional overhead of a dictionary for Entities with small Component collections. * SetEntity is currently used for Entities with 10 or more Components. Components are stored by Type in a dictionary, providing more efficient type-based lookup as the number of Components increases.
This is purely a runtime optimization. Consumers should always interact with IEntity and should not depend on which concrete implementation the factory selects.
Lifecycle
Entities should normally be created through the IEntityFactory, which performs Component composition, initialization and registration with the rest of the framework.
Calling Destroy begins the Entity's destruction process. Its Components are first unregistered as Message Broker broadcasters and the Entity transitions into its null state, broadcasting an EntityIsNullTopic. The framework uses this notification to perform the remaining cleanup associated with the Entity.
Destroying an Entity that has already been destroyed has no effect.
Properties
| Property | IEntityStaticData StaticData |
|---|---|
| Description | Returns the Entity Static Data from which the Entity was created. This describes the Entity's static definition and Component composition. |
Methods
| Method | void AddComponents(Dictionary<Type, IComponent> components) |
|---|---|
| Description | Attaches supplied Components to the Entity. This method is primarily used by the IEntityFactory during Entity construction after the Component collection has been generated from the Entity's Static Data and generally does not need to be called directly by consumers. |
| Method | T GetComponent<T>() where T : IComponent |
|---|---|
| Description | Returns the Component of type T attached to the Entity. Throws an InvalidOperationException if the Entity does not contain a Component of specified type. |
| Method | IComponent GetComponent(Type type) |
|---|---|
| Description | Returns the Component of specified Type attached to the Entity. Throws an InvalidOperationException if the Entity does not contain a Component of specified Type. |
| Method | bool TryGetComponent<T>(out T? component) where T : IComponent |
|---|---|
| Description | Attempts to retrieve the Component of type T attached to the Entity. Returns true and outputs the Component when present. Returns false and outputs null when the Entity does not contain the requested Component. |
| Method | bool TryGetComponent(Type componentType, out IComponent? component) |
|---|---|
| Description | Attempts to retrieve the Component of specified Type attached to the Entity. Returns true and outputs the Component when present. Returns false and outputs null when the Entity does not contain the requested Component. |
| Method | IEnumerable<IComponent> GetComponents() |
|---|---|
| Description | Returns all Components attached to the Entity. |
| Method | IEnumerable<Type> GetComponentTypes() |
|---|---|
| Description | Returns the Types of all Components attached to the Entity. |
| Method | bool HasComponent<T>() where T : IComponent |
|---|---|
| Description | Returns true if the Entity contains a Component of type T. |
| Method | bool HasComponent(Type componentType) |
|---|---|
| Description | Returns true if the Entity contains a Component of specified Type. |
| Method | void Destroy() |
|---|---|
| Description | Destroys the Entity. All Components belonging to the Entity are unregistered as Message Broker broadcasters before the Entity transitions into its null state and broadcasts an EntityIsNullTopic, allowing the framework to perform the remaining Entity cleanup. Nothing happens if the Entity has already been destroyed. |

