#gamedev #ecs #game-engine


An Entity-Component-System library

26 releases

0.5.10 Apr 8, 2022
0.5.8 Mar 31, 2022
0.3.3 Oct 21, 2021

#165 in Game dev

Download history 5/week @ 2023-06-10 63/week @ 2023-06-17 19/week @ 2023-06-24 87/week @ 2023-07-01 18/week @ 2023-07-08 14/week @ 2023-07-15 76/week @ 2023-07-22 37/week @ 2023-07-29 16/week @ 2023-08-05 20/week @ 2023-08-12 36/week @ 2023-08-19 34/week @ 2023-08-26 14/week @ 2023-09-02 44/week @ 2023-09-09 38/week @ 2023-09-16 13/week @ 2023-09-23

109 downloads per month
Used in 4 crates

MIT license

3.5K SLoC


An Entity-Component-System library

Simple Example

// Define two components struct
// Component is Send + Sync + 'static
struct Position{
    x : f32,
    y : f32
struct Hidden;

// create an empty world
let mut world = World::new();

// generate 10 entities
for _ in 0..10 {
    let x = random();
    lety = random();
    // andomly generate the positions
        .attach(Position { x,y });

// print all postions
for pos in world.query::<&Position>() {

// filter some entities need to be hidden
let ids = world.query::<&Position>()

// attach hidden to id
for id in ids {

// make a full-owning group to accelerate the query

// only print postions with id that is not hidden
for (id,data) in world.query::<&Position,Without<&Hidden>>() {

About entity

Entity in XECS is just an number ID.In XECS, it's just a NonZeroUsize. The ID is allocated from 1 by world automatically. The id=0 represents a recycled ID without any other flags through Option<EntityId>.

ID recycling

When you call world.create_entity(), an ID will be allocated automatically. If you call world.remove_entity(id), this ID will be a pit. If the next world.create_entity() is called, it will allocate this ID to fill the pit.Thanks to sparse set, it's still fast to iterate all components no matter how random of ID

Concurrency Safety

Because Component is just T : Send + Sync. World can use RwLock to ensure the borrow check relations of all components.And World can also be Send + Sync.Therefore,the all other states of world can be guarded by RwLock.So we can use world in concurrency environment by RwLock<World>.

System in XECS

System is a Stream with World as Context. Because Stream is not stable in std, XECS use futures::Stream instead.

To Run System

Because system is just an async trait, you need a wrapper of runtime from tokio or async-std


~26K SLoC