Skip to content

Component Operations

Entities gain functionality by adding components. This section details all component operation APIs.

Add an already-created component instance:

import { Component, ECSComponent } from '@esengine/ecs-framework';
@ECSComponent('Position')
class Position extends Component {
x: number = 0;
y: number = 0;
constructor(x: number = 0, y: number = 0) {
super();
this.x = x;
this.y = y;
}
}
const player = scene.createEntity("Player");
const position = new Position(100, 200);
player.addComponent(position);

Pass the component type and constructor arguments directly—the entity creates the instance (recommended):

// Create and add component
const position = player.createComponent(Position, 100, 200);
const health = player.createComponent(Health, 150);
// Equivalent to:
// const position = new Position(100, 200);
// player.addComponent(position);

Add multiple components at once:

const components = player.addComponents([
new Position(100, 200),
new Health(150),
new Velocity(0, 0)
]);

Get a component of a specific type:

// Returns Position | null
const position = player.getComponent(Position);
if (position) {
position.x += 10;
position.y += 20;
}

Check if an entity has a specific component type:

if (player.hasComponent(Position)) {
const position = player.getComponent(Position)!;
// Use ! because we confirmed it exists
}

Get all components of a specific type (for multi-component scenarios):

const allHealthComponents = player.getComponents(Health);

Get components with inheritance support using instanceof checking:

// Find CompositeNodeComponent or any subclass
const composite = entity.getComponentByType(CompositeNodeComponent);
if (composite) {
// composite could be SequenceNode, SelectorNode, etc.
}

Difference from getComponent():

MethodLookup MethodPerformanceUse Case
getComponentExact type match (bitmask)HighKnown exact type
getComponentByTypeinstanceof checkLowerNeed inheritance support

Get or create a component—automatically creates if it doesn’t exist:

// Ensure entity has Position component
const position = player.getOrCreateComponent(Position, 0, 0);
position.x = 100;
// If exists, returns existing component
// If not, creates new component with (0, 0) args

Get all entity components (read-only):

const allComponents = player.components; // readonly Component[]
allComponents.forEach(component => {
console.log(component.constructor.name);
});

Remove by component instance:

const healthComponent = player.getComponent(Health);
if (healthComponent) {
player.removeComponent(healthComponent);
}

Remove by component type:

const removedHealth = player.removeComponentByType(Health);
if (removedHealth) {
console.log("Health component removed");
}

Remove multiple component types at once:

const removedComponents = player.removeComponentsByTypes([
Position,
Health,
Velocity
]);

Remove all components:

player.removeAllComponents();

Mark components as modified for frame-level change detection:

const pos = entity.getComponent(Position)!;
pos.x = 100;
entity.markDirty(pos);
// Or mark multiple components
const vel = entity.getComponent(Velocity)!;
entity.markDirty(pos, vel);

Use with reactive queries:

// Query for components modified this frame
const changedQuery = scene.createReactiveQuery({
all: [Position],
changed: [Position] // Only match modified this frame
});
for (const entity of changedQuery.getEntities()) {
// Handle entities with position changes
}

Each entity maintains a component bitmask for efficient hasComponent checks:

// Get component mask (internal use)
const mask = entity.componentMask;
import { Component, ECSComponent, Scene } from '@esengine/ecs-framework';
@ECSComponent('Position')
class Position extends Component {
constructor(public x = 0, public y = 0) { super(); }
}
@ECSComponent('Health')
class Health extends Component {
constructor(public current = 100, public max = 100) { super(); }
}
// Create entity and add components
const player = scene.createEntity("Player");
player.createComponent(Position, 100, 200);
player.createComponent(Health, 150, 150);
// Get and modify component
const position = player.getComponent(Position);
if (position) {
position.x += 10;
player.markDirty(position);
}
// Get or create component
const velocity = player.getOrCreateComponent(Velocity, 0, 0);
// Check component existence
if (player.hasComponent(Health)) {
const health = player.getComponent(Health)!;
health.current -= 10;
}
// Remove component
player.removeComponentByType(Velocity);
// List all components
console.log(player.components.map(c => c.constructor.name));