Skip to content
dubaldaPublic

About

ECS (an entity component system) for Luau and Roblox built on inverted bitsets

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

mErCS

ECS (an entity component system) for Luau and Roblox built on inverted bitsets

Instead of archetypes, every component, tag and pair keeps a bitset of the entities that have it. Adding or removing a component never moves an entity and never creates an archetype, so frequent structural changes — state tags, relationships, spawning and despawning — stay O(1), memory does not grow with the number of component combinations, and there is nothing to clean up. The API follows jecs; moving jecs code over takes a few mechanical changes (see Migrating from jecs).

Version 1.2.0 is validated with the standalone luau 0.740 CLI (interpreter and native code generation); the Benchmarker results were captured in Roblox Studio with 1.0.0, and the full Studio check (studio/) is pending.

The 1.2.0 reference workload report compares this version with 1.1.0 and includes raw measurements, controls and reproduction commands.

Why

jecs 0.11.0 mErCS 1.2.0
add / remove a component moves the entity, copies all its columns sets a bit and a value: O(1)
new combination of components creates an archetype, kept until world:cleanup() nothing to create
pair with many targets an archetype per target one small record per pair, freed when unused (in batches) or with its target
a synthetic game frame (interpreter / native) 5.8 / 5.62 ms 2.47 / 1.61 ms
heap growth with changing targets after 5000 frames (interpreter) +15.38 MiB +0.32 MiB
memory per entity with 4 components 320 B 131 B

On the query cases where an archetype ECS is expected to be at its best, mErCS 1.2.0 takes 0.44–0.85× of the time of jecs 0.11.0 in native code. The comparison gives the ranges and the raw samples; ecr has a page of its own, and the Roblox Studio screenshots are on Benchmarker.

Beyond jecs: query:each (the fastest loop), OR terms, batch operations on query matches, toggles, change tracking by ticks and of new entities, disabled entities, hierarchies of any depth, slot pools, a read of a component that an entity must have (world:expect, an error that names both instead of nil), a debug world that names the wrong argument of a call (world:query: id 2 is nil). Query monitors (query:monitor()) take the place of the monitors of the jecs addon modules/OB.

Installation

Copy src/init.luau into your project as a ModuleScript (for example ReplicatedStorage.mErCS; src/jabby.luau is an optional child module for the jabby debugger), or sync the repository with Rojo (default.project.json), or depend on it through Wally (mercs = "dubalda/mercs@1.2.0"). The module has no dependencies; --!native is enabled at the top of the file.

Quick start

local ecs = require(ReplicatedStorage.mErCS)
local world = ecs.world()

local Position = world:component() :: ecs.Component<Vector3>
local Velocity = world:component() :: ecs.Component<Vector3>
local Frozen = world:entity() -- any entity can be used as a tag

local e = world:entity()
world:set(e, Position, Vector3.zero)
world:set(e, Velocity, Vector3.xAxis)

-- the fastest loop: a callback per entity
world:query(Position, Velocity):without(Frozen):each(function(entity, position, velocity)
    world:set(entity, Position, position + velocity)
end)

-- or a for-in loop, as in jecs
for entity, position, velocity in world:query(Position, Velocity) do
    world:set(entity, Position, position + velocity)
end

-- relationships
local parent = world:entity()
world:add(e, ecs.pair(ecs.ChildOf, parent))
print(world:parent(e) == parent) --> true
world:delete(parent) -- deletes e as well (ChildOf cascades)

-- one change to every match of a query
world:query(Position):with(Frozen):remove_all(Velocity)

examples/basics.luau is a runnable tour: luau examples/basics.luau.

Documentation

The documentation site holds the API reference (built from the doc comments of src/) and these pages:

  • Guide — worlds, components, queries, batch operations, relationships, hooks, query monitors, change tracking, the jabby adapter, types.
  • Comparison — the Benchmarker screenshots, 1.2.0 against 1.1.0, and jecs and ecr: design, differences, benchmarks, migrating.
  • Development — layout, tests, checks, benchmarks, Roblox Studio, CI and releases.

License

MIT

About

ECS (an entity component system) for Luau and Roblox built on inverted bitsets

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages