A lightweight, high-performance Entity Component System (ECS) for s&box, designed for developers who want efficient, modular, and scalable game logic.
For full documentation, visit sbox.game/kfe/kecs.
k.ECS enables efficient game development by separating data (components) from behavior (systems) and using entities as simple IDs to group components. It is built for performance, clarity, and easy integration with s&box projects.
- Entities: Simple integer IDs, act as containers for components.
- Components: Pure data structs (no logic), attached to entities.
- Systems: Implement game logic, process entities with required components.
- World: Contains and manages all entities, components, and systems. Supports multiple worlds for different game states or client/server logic.
- Manages entity and component lifecycles.
- Entity creation, destruction, and component management.
- Entity filtering for efficient queries.
- Example:
var world = World.Default; int entity = world.CreateEntity(); world.AddComponent(entity, new PositionComponent { X = 10, Y = 20 });
- Creates/destroys entities and tracks their existence.
- Efficiently stores components for each entity.
- O(1) add, remove, get, and reference operations.
- Manages all component storages in a world.
- Type-safe and dynamic.
- Query/filter entities by their components.
- Fluent API for complex queries.
var filter = new EntityFilter(world).With<PositionComponent>().With<VelocityComponent>(); foreach (var entity in filter) { ... }
- Highly efficient storage for entity-value pairs.
- O(1) operations, memory efficient, reference access.
- FeatureBase: Groups systems related to a feature (e.g., "Combat").
- SystemBase: Implements logic for a filtered set of entities.
public class AttackSystem : SystemBase { private EntityFilter _filter; public override bool Initialize() => _filter = new EntityFilter(World.Default).With<AttackComponent>(); public override void Update(float deltaTime) { foreach (var entity in _filter) { ref var attack = ref entity.Get<AttackComponent>(); // attack logic } } }
- Use structs for components (no classes).
- Data-only components—no logic.
- Use
ref
returns for direct modification. - Batch entity/component operations.
- Use and reuse filters for queries.
var world = World.Default;
int entityId = world.CreateEntity();
world.AddComponent(entityId, new PositionComponent { X = 10, Y = 20 });
world.AddComponent(entityId, new VelocityComponent { X = 5, Y = 0 });
world.AddComponent(entityId, new HealthComponent { Value = 100 });
var filter = new Filter(world)
.With<PositionComponent>()
.With<VelocityComponent>();
foreach (var entity in filter)
{
ref var pos = ref world.GetComponentRef<PositionComponent>(entity);
ref var vel = ref world.GetComponentRef<VelocityComponent>(entity);
pos.X += vel.X;
pos.Y += vel.Y;
}
- See the full API and guides at https://sbox.game/kfe/kecs/
- For questions or issues, use GitHub Issues
MIT (or see LICENSE file)