Builtins
Tecs provides various builtin plugins, components, and events. These builtins are registered with every World by default.
Components
| Component | Description |
|---|---|
| Name | Provides a name for an entity |
| ChildOf | Parent/child relationship between entities |
| Transform | Position, rotation, scale, and layer |
| RelativeTransform | Transform relative to parent entity |
| TTL | Automatically despawn after time expires |
| Disabled | Excludes entity from all queries |
| Paused | Excludes from gameplay queries, keeps rendering |
Name component
Provides a name for an entity. Stored as a scalar component of kind string, so the column holds the raw string and world:get(id, Name) returns a string directly.
Teal type:
Name: tecs.ScalarComponent<string>Example:
local tecs = require("tecs")
local entity = world:spawn(
tecs.builtins.Name("Phreddy")
)
local name = world:get(entity, tecs.builtins.Name) -- "Phreddy"To update an existing entity's name, prefer the 3-arg form of world:set:
world:set(entity, tecs.builtins.Name, "Greg")ChildOf relationship component
Defines an exclusive parent-child relationship between two entities. Uses sparse storage with cascade delete: despawning a parent automatically despawns all children (and grandchildren, recursively).
Registered with: exclusive = true, sparse = true, reverseIndex = true, cascadeDelete = true
Example:
local parent = world:spawn()
local child = world:spawn(tecs.builtins.ChildOf(parent))
-- Find all children of a parent
world:targets(parent, tecs.builtins.ChildOf, function(childId: integer)
print("Child:", childId)
end)
-- Despawning the parent cascades to children
world:despawn(parent)See Relationships for details on sparse storage and cascade delete.
Transform component
Provides the position, rotation, scale, and layer of an entity. You can use this component if it works for your game, or ignore it if not.
Teal type:
record Transform is components.Component
--- The x coordinate of the entity.
x: number
--- The y coordinate of the entity.
y: number
--- The z coordinate of the entity.
z: number
--- The layer of the entity (or nil if you don't use layers).
layer: integer
--- The rotation of the entity in radians (default: 0).
rotation: number
--- The horizontal scale of the entity (default: 1).
scaleX: number
--- The vertical scale of the entity (default: 1).
scaleY: number
--- Creates a new Transform component.
---
--- @param xOrValue The x position or full transform data if passing a table.
--- @param y The y position.
--- @param z The z position.
--- @param layer The layer.
--- @return the created transform component.
metamethod __call: function(
self,
xOrValue?: Transform | number,
y?: number,
z?: number,
layer?: integer
): Transform
endExamples:
You can create a Transform component using positional arguments. This is ideal for performance:
local entity = world:spawn(
tecs.builtins.Transform(10, 11, 1, 2) -- x, y, z, layer
)Alternatively, you can pass a table of named arguments. This generates garbage due to the table input, but it's more readable.
world:spawn(
tecs.builtins.Transform.new({
x = 10,
y = 11,
z = 1,
layer = 2
})
)After the component is created, you can modify anything inside of it as needed, like rotation and scale.
local transform = world:get(entity, tecs.builtins.Transform)
transform.rotation = math.pi / 4 -- Rotate 45 degrees
transform.scaleX = 2 -- Scale 2x horizontally
transform.scaleY = 2 -- Scale 2x verticallyAuto-sync
Modifying anything in the Transform component automatically syncs to all builtin GPU systems in Tecs. No dirty tracking needed.
RelativeTransform component
Defines an entity's transform relative to its parent entity. Requires the ChildOf component to be present on the same entity. A builtin system automatically composes the parent's transform with the relative transform to compute the final world-space position, rotation, and scale.
This component:
- Can position an entity relative to another, allowing use cases like GUI elements
- Causes child entities to hierarchically inherit the position, scaling, and rotation of a parent entity
- Automatically adds a
Transformcomponent if one is not present when added to an entity
Parameters:
x: The x offset from the parent (default: 0)y: The y offset from the parent (default: 0)z: The z offset from the parent (default: 0)rotation: The rotation offset in radians from the parent (default: 0)scaleX: The x scale multiplier relative to the parent (default: 1)scaleY: The y scale multiplier relative to the parent (default: 1)originX: Origin as a fraction (0-1) of the entity's width; 0 = left, 0.5 = center, 1 = right (default: 0)originY: Origin as a fraction (0-1) of the entity's height; 0 = top, 0.5 = center, 1 = bottom (default: 0)
Teal type:
record RelativeTransform is components.Component
x: number
y: number
z: number
rotation: number
scaleX: number
scaleY: number
--- Origin as a fraction (0-1) of the entity's width: 0 = left, 0.5 = center, 1 = right.
originX: number
--- Origin as a fraction (0-1) of the entity's height: 0 = top, 0.5 = center, 1 = bottom.
originY: number
metamethod __call: function(
self,
x?: number,
y?: number,
z?: number,
rotation?: number,
scaleX?: number,
scaleY?: number,
originX?: number,
originY?: number
): RelativeTransform
endExamples:
Create a child entity positioned relative to its parent:
local parent = world:spawn(
tecs.builtins.Transform(100, 100, 0)
)
local child = world:spawn(
tecs.builtins.ChildOf(parent),
tecs.builtins.RelativeTransform(50, 30) -- 50px right, 30px down
)The child's world-space position is automatically calculated as (150, 130) and updated each frame as the parent moves.
TTL component
Automatically despawns an entity when the TTL, or "time to live", reaches zero. Tecs automatically adds a system that tracks entities with a TTL and despawns them.
Teal type:
--- Despawns an entity when the TTL reaches zero.
record TTL is components.Component
--- The total amount of time the entity had to live.
startingTime: number
--- The remaining time the entity has to live.
remaining: number
--- Compute the percentage of completion as a number between 0 and 1.
percentComplete: function(self): number
--- Create a new TTL component.
---
--- @param remaining The amount of time the entity has to live.
--- @return the created TTL component.
metamethod __call: function(self, remaining: number): TTL
endExample:
world:spawn(
-- Despawn the entity after 10 seconds.
tecs.builtins.TTL(10)
)Disabled component
A tag component that marks an entity as disabled, causing it to be excluded from all queries by default. This is useful for temporarily hiding entities without despawning them.
Usage:
-- Spawn a disabled entity (won't appear in queries by default)
local entity = world:spawn(
tecs.builtins.Disabled
)See also
See Disabled entities for more on how disabled entities work with queries.
Paused component
A tag component that marks an entity as paused. Unlike Disabled, Paused is not auto-excluded from queries. Paused entities should still render; only gameplay systems that need to skip them should use exclude = {Paused}.
This is typically managed automatically by the state stack when a state's onBlur policy is set to "pause". You can also add it manually:
-- Pause an entity (excluded from gameplay queries, still renders)
world:set(entity, tecs.builtins.Paused)
-- Unpause
world:remove(entity, tecs.builtins.Paused)When Paused is added to an entity with a Sprite component, the sprite animation is automatically frozen at the current frame. When Paused is removed, the animation resumes from where it left off.
See also
See Paused entities for more on how paused entities work with queries.
Events
| Event | Description |
|---|---|
| ArchetypeCreated | Emitted when a new archetype is created |
| OnSpawn | Emitted when an entity is spawned |
| OnDespawn | Emitted when an entity is despawned |
ArchetypeCreated event
An event emitted when a new archetype is created in the world. Observe this event at address 0 (world-level) to discover new archetypes as entities with new component combinations are spawned.
Teal type:
--- An event emitted when a new archetype is created.
record ArchetypeCreated is events.Event
archetype: Archetype
--- Create a new ArchetypeCreated event.
metamethod __call: function(self, archetype: Archetype): ArchetypeCreated
endUsage:
world:observe(0, tecs.builtins.ArchetypeCreated, function(event: tecs.builtins.ArchetypeCreated)
local archetype = event.archetype
if archetype:get(Position) and archetype:get(Velocity) then
-- Inspect or introspect newly-created archetypes here.
end
end)Advanced feature
This event is primarily used internally by queries to track matching archetypes. For normal "react when entities match a component signature" use cases, prefer query callbacks (onEntitiesAdded / onEntitiesRemoved).
OnSpawn event
An event emitted when an entity is spawned. The event is emitted globally (address 0). Observe this event to react when entities are created.
Event timing
The OnSpawn event is emitted at spawn time (when world:spawn is called), before the entity is committed:
- The entity is not yet placed in an archetype or visible to queries
world:isAlive(entity)returnsfalseuntil commit- You can stage further mutations on the entity ID between spawn and commit
Teal type:
--- An event emitted when a specific entity is spawned.
record OnSpawn is events.Event
entity: integer
--- Create a new OnSpawn event.
metamethod __call: function(self, entity: integer): OnSpawn
endUsage:
Observe globally to react to all spawns:
world:observe(0, tecs.builtins.OnSpawn, function(event: tecs.builtins.OnSpawn)
print("Entity spawned: " .. event.entity)
end)OnDespawn event
An event emitted when an entity is despawned. The event is emitted both globally (address 0) and to the entity's address. Observe this event to clean up resources, spawn effects, or react to entity removal.
Event timing
The OnDespawn event is emitted during the despawn call, before the entity is physically removed at commit. When this event fires:
world:isAlive(entity)still returnstrue(the entity index entry is intact)- Entity components are still accessible via
world:get() - The entity has not yet been removed from queries
- After all observers complete, all observers on the entity's address are automatically cleaned up
Teal type:
--- An event emitted when a specific entity is despawned.
record OnDespawn is events.Event
entity: integer
--- Create a new OnDespawn event.
metamethod __call: function(self, entity: integer): OnDespawn
endUsage:
Observe a specific entity:
world:observe(entityId, tecs.builtins.OnDespawn, function(e: tecs.builtins.OnDespawn)
-- Entity is no longer "alive" but components are still accessible
local pos = world:get(e.entity, Position)
if pos then
spawnExplosionAt(pos.x, pos.y)
end
print("Entity " .. e.entity .. " was despawned")
end)Observe globally to react to all despawns:
world:observe(0, tecs.builtins.OnDespawn, function(e: tecs.builtins.OnDespawn)
print("Entity " .. e.entity .. " was despawned")
end)