A Component is data attached to an entity. Extend the base class, add fields, you're done.
The smallest possible Component
That's a complete, valid Component. It has no logic — logic lives in Systems. Components are data containers.
What the base class gives you
- A unique component ID
- A reference to the owning entity once attached (
this.entityId) - Optional lifecycle hooks:
onAttachOverride(),onDetachOverride() - An
eventBusreference once the parent entity is created in a World
Lifecycle hooks
Most Components don't need them. Use them when you need to allocate or release a resource that lives as long as the component is attached.
onAttachOverride fires after the Component is added to an Entity and the Entity is in a World — this.eventBus is safe to use. onDetachOverride fires when the Component is removed or the Entity is destroyed.
Naming convention
By convention, every Component in this ecosystem follows the same shape:
{Name}Component— the data class{Name}System— the System that operates on it{Name}Events— an object with event-name constants the System emits{Name}InputEvents— an object with event-name constants the System listens to
This convention is what lets the lazy SceneLoader in @babylonjsmarket/arcade find your component classes by name from a JSON scene file. Stick to it and your components are JSON-loadable for free.
Component data is just data
Don't put functions on Components. Don't put references to other entities (use IDs). Don't put renderer handles directly. The reason: state that's hard to serialize is hard to save, hard to replay, hard to test.
Serialization
The base Component exposes a serialize() method that JSON-encodes the public fields. The SceneLoader uses this format both ways: it writes scene state to JSON and instantiates entities from JSON.
Override it if you need custom serialization, but the default is usually enough:
Multiple components on one entity
Entities can hold any number of components, one per class. Adding a second instance of the same class replaces the first: